[
  {
    "path": ".gitignore",
    "content": "*.o\ncompareTopKAlgorithms\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2016 Anil Shanbhag\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "OS_SIZE = $(shell uname -m | sed -e \"s/i.86/32/\" -e \"s/x86_64/64/\")\n\nCUDA_PATH       ?= /usr/local/cuda-10.0\nCUDA_INC_PATH   ?= $(CUDA_PATH)/include\nCUDA_BIN_PATH   ?= $(CUDA_PATH)/bin\n\nifeq ($(OS_SIZE),32)\n    CUDA_LIB_PATH  ?= $(CUDA_PATH)/lib\nelse\n    CUDA_LIB_PATH  ?= $(CUDA_PATH)/lib64\nendif\n\nNVCC            ?= $(CUDA_BIN_PATH)/nvcc\n\n# Make sure to choose the right SM for your device\nGENCODE_SM70    := -gencode arch=compute_70,code=sm_70\nGENCODE_SM50    := -gencode arch=compute_50,code=sm_50\nGENCODE_SM35    := -gencode arch=compute_35,code=sm_35\nGENCODE_FLAGS   := $(GENCODE_SM50)\n\nLDFLAGS   := -lcudart -lrt -lcurand -lm\nCFLAGS := -O3 -lineinfo -Xptxas=\"-dlcm=ca -v\"\nCUB_DIR = ./external/cub/\nSOURCE_DIR = ./src/\nTEST_DIR = ./test/\nINCLUDES := -I$(CUB_DIR) -I$(SOURCE_DIR) -I$(TEST_DIR)\n\n#obj/%.o: src/%.cu $(DEPS)\n#\t$(NVCC) $(CFLAGS) -I. $(INCLUDES) -g $(GENCODE_FLAGS) $< -o $@\n\ncompareTopKAlgorithms: test/compareTopKAlgorithms.cu src/bitonicTopK.cuh src/radixSelectTopK.cuh src/sortTopK.cuh\n\t$(NVCC) $(CFLAGS) $(INCLUDES) test/compareTopKAlgorithms.cu $(LDFLAGS) -o compareTopKAlgorithms\n\nclean:\n\trm -rf *.o compareTopKAlgorithms\n"
  },
  {
    "path": "README.md",
    "content": "GPU-TopK\n========\n\nGPU-TopK implements efficient top-k runtimes for GPUs. The specific problem solved is given a array of entries (key-only or key-value), find the top-k entries based on value of key. \n\nThe package implements the following routines:\n\n* Bitonic Top-K: reduction algorithm based on bitonic sort\n* Radix Select Top-K: reduction of radix sort to compute top-k\n* Sort Top-K: sorts the entire array and selects the top-k entries\n\nFor full details of the algorithms, see our [paper](http://anilshanbhag.in/static/papers/gputopk_sigmod18.pdf)\n\n```\n@inproceedings{shanbhag2018efficient,\n  title={Efficient Top-K query processing on massively parallel hardware},\n  author={Shanbhag, Anil and Pirk, Holger and Madden, Samuel},\n  booktitle={Proceedings of the 2018 International Conference on Management of Data},\n  pages={1557--1570},\n  year={2018},\n  organization={ACM}\n}\n```\n\nUsage\n----\n\nThe individual implementations can used directly as standalone header files. For example, to use `RadixSelectTopK`, \n\n```\n#include \"radixSelectTopK.cuh\"\n...\nfloat* d_keys_in; // device pointer to the array\nuint num_items;   // number of entries in the array\nuint k;           // \nfloat* d_keys_out;// device pointer to the result array (needs to be of size atleast k)\nCachingDeviceAllocator&  g_allocator // Cub memory allocator \nradixSelectTopK<float>(d_keys_in, num_items, k, d_keys_out, g_allocator);\n```\n\nWe have implemented a testutil called `compareTopKAlgorithms` that can be used to benchmark the different algorithms. The testutil lets you test performance of the algorithms across standard data types and certain pre-defined distributions. To run the testutil:\n\n```\n# Edit Makefile to select the right Gencode for your GPU\n# For example: for V100 GPU set GENCODE_FLAGS to use GENCODE_SM70\n\nmake compareTopKAlgorithms\n./compareTopKAlgorithms\n```\n\nHere is an example tracelog:\n```\n$ ./compareTopKAlgorithms\nPlease enter the type of value you want to test:\n1-float\n2-double\n3-uint\n1\nPlease enter distribution type: 0\nPlease enter K: 32\nPlease enter number of tests to run per K: 3\nPlease enter start power (dataset size starts at 2^start)(max val: 29): 29\nPlease enter stop power (dataset size stops at 2^stop)(max val: 29): 29\nNOW STARTING A NEW K\n\nThe distribution is: UNIFORM FLOATS\nRunning test 1 of 3 for size: 536870912 and k: 32\nTESTING: 0 Sort\nTESTING: 2 Bitonic TopK\nTESTING: 1 Radix Select\nRunning test 2 of 3 for size: 536870912 and k: 32\nTESTING: 2 Bitonic TopK\nTESTING: 0 Sort\nTESTING: 1 Radix Select\nRunning test 3 of 3 for size: 536870912 and k: 32\nTESTING: 0 Sort\nTESTING: 1 Radix Select\nTESTING: 2 Bitonic TopK\n\n\nSort                 averaged: 219.273071 ms\nRadix Select         averaged: 132.391724 ms\nBitonic TopK         averaged: 134.959854 ms\nSort                 minimum: 215.583801 ms\nRadix Select         minimum: 63.751999 ms\nBitonic TopK         minimum: 28.718592 ms\nSort won 0 times\nRadix Select won 1 times\nBitonic TopK won 2 times\n```\n\nFor benchmarking, it is advisable to run the suite more than once inorder to have GPU warmed up. To see the full set of distributions implemented, check test/generateProblems.cuh. \n\nKnown Issues\n-----------\n1. Currently works for key-only, we will add key-value soon\n2. Works for data set size upto 2^29. This is due to inherent limitations of maximum array size on GPUs.\n3. Tested to work well on Nvidia Maxwell architecture and upwards (may not work on K80 GPU - you are welcome to submit a patch). \n4. BitonicTopK works only for K<=256, if you are testing K > 256, make sure to comment BitonicTopK\n"
  },
  {
    "path": "external/cub/.cproject",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<?fileVersion 4.0.0?><cproject storage_type_id=\"org.eclipse.cdt.core.XmlProjectDescriptionStorage\">\r\n\t<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\r\n\t\t<cconfiguration id=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311\">\r\n\t\t\t<storageModule buildSystemId=\"org.eclipse.cdt.managedbuilder.core.configurationDataProvider\" id=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311\" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Default\">\r\n\t\t\t\t<externalSettings>\r\n\t\t\t\t\t<externalSetting languages=\"cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1945715073\"/>\r\n\t\t\t\t</externalSettings>\r\n\t\t\t\t<extensions>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.Cygwin_PE\" point=\"org.eclipse.cdt.core.BinaryParser\"/>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GCCErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GASErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GLDErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.GmakeErrorParser\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\r\n\t\t\t\t\t<extension id=\"org.eclipse.cdt.core.CWDLocator\" point=\"org.eclipse.cdt.core.ErrorParser\"/>\r\n\t\t\t\t</extensions>\r\n\t\t\t</storageModule>\r\n\t\t\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\r\n\t\t\t\t<configuration artifactName=\"B40CTrunk\" buildProperties=\"\" description=\"\" id=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311\" name=\"Default\" parent=\"org.eclipse.cdt.build.core.emptycfg\">\r\n\t\t\t\t\t<folderInfo id=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113\" name=\"/\" resourcePath=\"\">\r\n\t\t\t\t\t\t<toolChain id=\"cdt.managedbuild.toolchain.gnu.cygwin.base.481495889\" name=\"Cygwin GCC\" superClass=\"cdt.managedbuild.toolchain.gnu.cygwin.base\">\r\n\t\t\t\t\t\t\t<targetPlatform archList=\"all\" binaryParser=\"org.eclipse.cdt.core.Cygwin_PE\" id=\"cdt.managedbuild.target.gnu.platform.cygwin.base.100038061\" name=\"Debug Platform\" osList=\"win32\" superClass=\"cdt.managedbuild.target.gnu.platform.cygwin.base\"/>\r\n\t\t\t\t\t\t\t<builder buildPath=\"${workspace_loc:/PrivateCub}/Default\" id=\"cdt.managedbuild.target.gnu.builder.cygwin.base.412463247\" keepEnvironmentInBuildfile=\"false\" name=\"Gnu Make Builder\" superClass=\"cdt.managedbuild.target.gnu.builder.cygwin.base\"/>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.assembler.cygwin.base.996758685\" name=\"GCC Assembler\" superClass=\"cdt.managedbuild.tool.gnu.assembler.cygwin.base\">\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.both.asm.option.include.paths.900454792\" name=\"Include paths (-I)\" superClass=\"gnu.both.asm.option.include.paths\" valueType=\"includePath\">\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/device_launch_parameters.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/crt/device_functions.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include&quot;\"/>\r\n\t\t\t\t\t\t\t\t</option>\r\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.assembler.input.221302756\" superClass=\"cdt.managedbuild.tool.gnu.assembler.input\"/>\r\n\t\t\t\t\t\t\t</tool>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.archiver.cygwin.base.1353653670\" name=\"GCC Archiver\" superClass=\"cdt.managedbuild.tool.gnu.archiver.cygwin.base\"/>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1401626953\" name=\"Cygwin C++ Compiler\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base\">\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.include.paths.1909687606\" name=\"Include paths (-I)\" superClass=\"gnu.cpp.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/device_launch_parameters.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/device_functions.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include&quot;\"/>\r\n\t\t\t\t\t\t\t\t</option>\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.preprocessor.def.1893619952\" name=\"Defined symbols (-D)\" superClass=\"gnu.cpp.compiler.option.preprocessor.def\" useByScannerDiscovery=\"false\" valueType=\"definedSymbols\">\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__global__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__shared__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__forceinline__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__host__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device_builtin__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device_builtin_texture_type__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"TEST_ARCH=200\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__launch_bounds__(...)\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__align__(...)\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__CUDA_ARCH__=350\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__CUDACC__=1\"/>\r\n\t\t\t\t\t\t\t\t</option>\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.cpp.compiler.option.dialect.std.49639338\" name=\"Language standard\" superClass=\"gnu.cpp.compiler.option.dialect.std\" useByScannerDiscovery=\"true\" value=\"gnu.cpp.compiler.dialect.default\" valueType=\"enumerated\"/>\r\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1708330939\" superClass=\"cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin\"/>\r\n\t\t\t\t\t\t\t</tool>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1940954787\" name=\"Cygwin C Compiler\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.cygwin.base\">\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.include.paths.1945618846\" name=\"Include paths (-I)\" superClass=\"gnu.c.compiler.option.include.paths\" useByScannerDiscovery=\"false\" valueType=\"includePath\">\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/device_launch_parameters.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include/crt/device_functions.h&quot;\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"&quot;${CUDA_PATH}/include&quot;\"/>\r\n\t\t\t\t\t\t\t\t</option>\r\n\t\t\t\t\t\t\t\t<option id=\"gnu.c.compiler.option.preprocessor.def.symbols.1005509663\" name=\"Defined symbols (-D)\" superClass=\"gnu.c.compiler.option.preprocessor.def.symbols\" useByScannerDiscovery=\"false\" valueType=\"definedSymbols\">\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__global__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__shared__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__forceinline__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__host__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device_builtin__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__device_builtin_texture_type__\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"TEST_ARCH=200\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__launch_bounds__(...)\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__align__(...)\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__CUDA_ARCH__=350\"/>\r\n\t\t\t\t\t\t\t\t\t<listOptionValue builtIn=\"false\" value=\"__CUDACC__=1\"/>\r\n\t\t\t\t\t\t\t\t</option>\r\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.469104331\" superClass=\"cdt.managedbuild.tool.gnu.c.compiler.input.cygwin\"/>\r\n\t\t\t\t\t\t\t</tool>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.c.linker.cygwin.base.1600375047\" name=\"Cygwin C Linker\" superClass=\"cdt.managedbuild.tool.gnu.c.linker.cygwin.base\"/>\r\n\t\t\t\t\t\t\t<tool id=\"cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base.1176124124\" name=\"Cygwin C++ Linker\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.cygwin.base\">\r\n\t\t\t\t\t\t\t\t<inputType id=\"cdt.managedbuild.tool.gnu.cpp.linker.input.958378367\" superClass=\"cdt.managedbuild.tool.gnu.cpp.linker.input\">\r\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinputdependency\" paths=\"$(USER_OBJS)\"/>\r\n\t\t\t\t\t\t\t\t\t<additionalInput kind=\"additionalinput\" paths=\"$(LIBS)\"/>\r\n\t\t\t\t\t\t\t\t</inputType>\r\n\t\t\t\t\t\t\t</tool>\r\n\t\t\t\t\t\t</toolChain>\r\n\t\t\t\t\t</folderInfo>\r\n\t\t\t\t</configuration>\r\n\t\t\t</storageModule>\r\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\"/>\r\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\r\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\"/>\r\n\t\t\t<storageModule moduleId=\"org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings\"/>\r\n\t\t</cconfiguration>\r\n\t</storageModule>\r\n\t<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\r\n\t\t<project id=\"B40CTrunk.null.1404415602\" name=\"B40CTrunk\"/>\r\n\t</storageModule>\r\n\t<storageModule moduleId=\"refreshScope\" versionNumber=\"2\">\r\n\t\t<configuration configurationName=\"Default\">\r\n\t\t\t<resource resourceType=\"PROJECT\" workspacePath=\"/GIT_CUB\"/>\r\n\t\t</configuration>\r\n\t</storageModule>\r\n\t<storageModule moduleId=\"org.eclipse.cdt.core.LanguageSettingsProviders\"/>\r\n\t<storageModule moduleId=\"org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings\">\r\n\t\t<doc-comment-owner id=\"org.eclipse.cdt.ui.doxygen\">\r\n\t\t\t<path value=\"\"/>\r\n\t\t</doc-comment-owner>\r\n\t</storageModule>\r\n\t<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\"/>\r\n\t<storageModule moduleId=\"scannerConfiguration\">\r\n\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t<buildOutputProvider>\r\n\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</buildOutputProvider>\r\n\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</scannerInfoProvider>\r\n\t\t</profile>\r\n\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t<buildOutputProvider>\r\n\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</buildOutputProvider>\r\n\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</scannerInfoProvider>\r\n\t\t</profile>\r\n\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t<buildOutputProvider>\r\n\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</buildOutputProvider>\r\n\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</scannerInfoProvider>\r\n\t\t</profile>\r\n\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t<buildOutputProvider>\r\n\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</buildOutputProvider>\r\n\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</scannerInfoProvider>\r\n\t\t</profile>\r\n\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t<buildOutputProvider>\r\n\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</buildOutputProvider>\r\n\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t</scannerInfoProvider>\r\n\t\t</profile>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1940954787;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.469104331\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1665401269;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.494265807\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.43985841;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1045483126\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1240277003;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1264397663\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.459535216;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.2120860882\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1758599759;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.466964704\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1401626953;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1708330939\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1671954574;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.304556051\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.2110267806;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.903720746\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1850250798;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1752562149\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1296776241;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.268633283\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.265387950;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.563557831\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.629007265;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.450470600\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.2085396856;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1885998497\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.652522784;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1098348915\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.1149397878;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1156849140\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.586941236;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1654082299\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.1214991320;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.332043455\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.cpp.compiler.cygwin.base.440957653;cdt.managedbuild.tool.gnu.cpp.compiler.input.cygwin.1117446939\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t\t<scannerConfigBuildInfo instanceId=\"cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311;cdt.managedbuild.toolchain.gnu.cygwin.base.1260156311.1722659113;cdt.managedbuild.tool.gnu.c.compiler.cygwin.base.158380621;cdt.managedbuild.tool.gnu.c.compiler.input.cygwin.1945715073\">\r\n\t\t\t<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\" selectedProfileId=\"org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC\"/>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"makefileGenerator\">\r\n\t\t\t\t\t<runAction arguments=\"-f ${project_name}_scd.mk\" command=\"make\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/${specs_file}\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.cpp\" command=\"g++\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t\t<profile id=\"org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC\">\r\n\t\t\t\t<buildOutputProvider>\r\n\t\t\t\t\t<openAction enabled=\"true\" filePath=\"\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</buildOutputProvider>\r\n\t\t\t\t<scannerInfoProvider id=\"specsFile\">\r\n\t\t\t\t\t<runAction arguments=\"-E -P -v -dD ${plugin_state_location}/specs.c\" command=\"gcc\" useDefault=\"true\"/>\r\n\t\t\t\t\t<parser enabled=\"true\"/>\r\n\t\t\t\t</scannerInfoProvider>\r\n\t\t\t</profile>\r\n\t\t</scannerConfigBuildInfo>\r\n\t</storageModule>\r\n</cproject>\r\n"
  },
  {
    "path": "external/cub/.project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<projectDescription>\r\n\t<name>GIT_CUB</name>\r\n\t<comment></comment>\r\n\t<projects>\r\n\t</projects>\r\n\t<buildSpec>\r\n\t\t<buildCommand>\r\n\t\t\t<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>\r\n\t\t\t<triggers>clean,full,incremental,</triggers>\r\n\t\t\t<arguments>\r\n\t\t\t</arguments>\r\n\t\t</buildCommand>\r\n\t\t<buildCommand>\r\n\t\t\t<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>\r\n\t\t\t<triggers>full,incremental,</triggers>\r\n\t\t\t<arguments>\r\n\t\t\t</arguments>\r\n\t\t</buildCommand>\r\n\t</buildSpec>\r\n\t<natures>\r\n\t\t<nature>org.eclipse.cdt.core.cnature</nature>\r\n\t\t<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>\r\n\t\t<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>\r\n\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\r\n\t</natures>\r\n</projectDescription>\r\n"
  },
  {
    "path": "external/cub/.settings/.gitignore",
    "content": "/language.settings.xml\n"
  },
  {
    "path": "external/cub/.settings/org.eclipse.cdt.codan.core.prefs",
    "content": "eclipse.preferences.version=1\r\norg.eclipse.cdt.codan.checkers.errnoreturn=Warning\r\norg.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\r\norg.eclipse.cdt.codan.checkers.errreturnvalue=Error\r\norg.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.checkers.nocommentinside=-Error\r\norg.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.checkers.nolinecomment=-Error\r\norg.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.checkers.noreturn=Error\r\norg.eclipse.cdt.codan.checkers.noreturn.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},implicit\\=>false}\r\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error\r\norg.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},no_break_comment\\=>\"no break\",last_case_param\\=>true,empty_case_param\\=>false}\r\norg.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning\r\norg.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},unknown\\=>false,exceptions\\=>()}\r\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning\r\norg.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},skip\\=>true}\r\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error\r\norg.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info\r\norg.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},pattern\\=>\"^[a-z]\",macro\\=>true,exceptions\\=>()}\r\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning\r\norg.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning\r\norg.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>()}\r\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},paramNot\\=>false}\r\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},else\\=>false,afterelse\\=>false}\r\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\r\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true}\r\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning\r\norg.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true},macro\\=>true,exceptions\\=>(\"@(\\#)\",\"$Id\")}\r\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error\r\norg.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\\=>{RUN_ON_FULL_BUILD\\=>true,RUN_ON_INC_BUILD\\=>true,RUN_ON_FILE_OPEN\\=>false,RUN_ON_FILE_SAVE\\=>false,RUN_AS_YOU_TYPE\\=>true,RUN_ON_DEMAND\\=>true}}\r\nuseParentScope=false\r\n"
  },
  {
    "path": "external/cub/.settings/org.eclipse.cdt.core.prefs",
    "content": "eclipse.preferences.version=1\r\nindexer/indexAllFiles=true\r\nindexer/indexAllHeaderVersions=false\r\nindexer/indexAllVersionsSpecificHeaders=\r\nindexer/indexOnOpen=false\r\nindexer/indexUnusedHeadersWithAlternateLang=false\r\nindexer/indexUnusedHeadersWithDefaultLang=true\r\nindexer/indexerId=org.eclipse.cdt.core.fastIndexer\r\nindexer/skipFilesLargerThanMB=8\r\nindexer/skipImplicitReferences=false\r\nindexer/skipIncludedFilesLargerThanMB=16\r\nindexer/skipMacroReferences=false\r\nindexer/skipReferences=false\r\nindexer/skipTypeReferences=false\r\nindexer/useHeuristicIncludeResolution=true\r\norg.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation=16\r\norg.eclipse.cdt.core.formatter.alignment_for_assignment=16\r\norg.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration=48\r\norg.eclipse.cdt.core.formatter.alignment_for_binary_expression=16\r\norg.eclipse.cdt.core.formatter.alignment_for_compact_if=0\r\norg.eclipse.cdt.core.formatter.alignment_for_conditional_expression=48\r\norg.eclipse.cdt.core.formatter.alignment_for_conditional_expression_chain=18\r\norg.eclipse.cdt.core.formatter.alignment_for_constructor_initializer_list=0\r\norg.eclipse.cdt.core.formatter.alignment_for_declarator_list=16\r\norg.eclipse.cdt.core.formatter.alignment_for_enumerator_list=48\r\norg.eclipse.cdt.core.formatter.alignment_for_expression_list=0\r\norg.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer=16\r\norg.eclipse.cdt.core.formatter.alignment_for_member_access=0\r\norg.eclipse.cdt.core.formatter.alignment_for_overloaded_left_shift_chain=16\r\norg.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration=48\r\norg.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration=48\r\norg.eclipse.cdt.core.formatter.brace_position_for_array_initializer=next_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_block=next_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_block_in_case=end_of_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_method_declaration=next_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration=end_of_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_switch=end_of_line\r\norg.eclipse.cdt.core.formatter.brace_position_for_type_declaration=next_line\r\norg.eclipse.cdt.core.formatter.comment.min_distance_between_code_and_line_comment=1\r\norg.eclipse.cdt.core.formatter.comment.never_indent_line_comments_on_first_column=true\r\norg.eclipse.cdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=true\r\norg.eclipse.cdt.core.formatter.compact_else_if=true\r\norg.eclipse.cdt.core.formatter.continuation_indentation=1\r\norg.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer=1\r\norg.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line=false\r\norg.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header=false\r\norg.eclipse.cdt.core.formatter.indent_access_specifier_extra_spaces=0\r\norg.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier=true\r\norg.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header=false\r\norg.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases=true\r\norg.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header=false\r\norg.eclipse.cdt.core.formatter.indent_empty_lines=false\r\norg.eclipse.cdt.core.formatter.indent_statements_compare_to_block=true\r\norg.eclipse.cdt.core.formatter.indent_statements_compare_to_body=true\r\norg.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases=true\r\norg.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch=false\r\norg.eclipse.cdt.core.formatter.indentation.size=4\r\norg.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_colon_in_constructor_initializer_list=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement=insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert\r\norg.eclipse.cdt.core.formatter.insert_new_line_in_empty_block=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_assignment_operator=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_binary_operator=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_colon_in_case=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_bracket=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_postfix_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_prefix_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for=insert\r\norg.eclipse.cdt.core.formatter.insert_space_after_unary_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_assignment_operator=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_binary_operator=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_bracket=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_colon_in_case=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_colon_in_default=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_bracket=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_postfix_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_prefix_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional=insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_semicolon=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_before_unary_operator=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_between_empty_brackets=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert\r\norg.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert\r\norg.eclipse.cdt.core.formatter.join_wrapped_lines=true\r\norg.eclipse.cdt.core.formatter.keep_else_statement_on_same_line=false\r\norg.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line=false\r\norg.eclipse.cdt.core.formatter.keep_imple_if_on_one_line=true\r\norg.eclipse.cdt.core.formatter.keep_then_statement_on_same_line=false\r\norg.eclipse.cdt.core.formatter.lineSplit=80\r\norg.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve=1\r\norg.eclipse.cdt.core.formatter.put_empty_statement_on_new_line=true\r\norg.eclipse.cdt.core.formatter.tabulation.char=space\r\norg.eclipse.cdt.core.formatter.tabulation.size=4\r\norg.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations=false\r\n"
  },
  {
    "path": "external/cub/.settings/org.eclipse.cdt.ui.prefs",
    "content": "eclipse.preferences.version=1\r\nformatter_profile=_B40C\r\nformatter_settings_version=1\r\n"
  },
  {
    "path": "external/cub/.settings/org.eclipse.core.runtime.prefs",
    "content": "content-types/enabled=true\r\ncontent-types/org.eclipse.cdt.core.cxxHeader/file-extensions=cuh\r\ncontent-types/org.eclipse.cdt.core.cxxSource/file-extensions=cu\r\neclipse.preferences.version=1\r\n"
  },
  {
    "path": "external/cub/CHANGE_LOG.TXT",
    "content": "1.7.4    09/20/2017\n    - Bug fixes: \n        - Issue #114: Can't pair non-trivially-constructible values in radix sort\n        - Issue #115: WarpReduce segmented reduction broken in CUDA 9 for logical warp sizes < 32 \n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.7.3    08/28/2017\n    - Bug fixes: \n        - Issue #110: DeviceHistogram null-pointer exception bug for iterator inputs\n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.7.2    08/26/2017\n    - Bug fixes: \n        - Issue #104: Device-wide reduction is now \"run-to-run\" deterministic for \n          pseudo-associative reduction operators (like floating point addition)\n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.7.1    08/18/2017\n    - Updated Volta radix sorting tuning policies \n    - Bug fixes: \n        - Issue #104 (uint64_t warp-reduce broken for cub 1.7.0 on cuda 8 and older)\n        - Issue #103 (Can't mix Thrust 9.0 and CUB)\n        - Issue #102 (CUB pulls in windows.h which defines min/max macros that conflict with std::min/std::max)\n        - Issue #99 (Radix sorting crashes NVCC on Windows 10 for SM52)\n        - Issue #98 (cuda-memcheck: --tool initcheck failed with lineOfSight)\n        - Issue #94 (Git clone size)\n        - Issue #93 (accept iterators for segment offsets)\n        - Issue #87 (CUB uses anonymous unions which is not valid C++)\n        - Issue #44 (Check for C++ 11 should be changed that Visual Studio 2013 is also recognized as C++ 11 capable)\n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.7.0    06/07/2017\n    - Compatible with CUDA9 and SM7.x (Volta) independent thread scheduling \n    - API change: remove cub::WarpAll() and cub::WarpAny().  These functions served to \n      emulate __all and __any functionality for SM1.x devices, which did not have those \n      operations.  However, the SM1.x devices are now deprecated in CUDA, and the \n      interfaces of the these two functions are now lacking the lane-mask needed \n      for collectives to run on Volta SMs having independent thread scheduling. \n    - Bug fixes: \n        - Issue #86 Incorrect results with ReduceByKey\n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.6.4    12/06/2016\n    - Updated sm_5x, sm_6x tuning policies for radix sorting (3.5B and 3.4B \n      32b keys/s on TitanX and GTX 1080, respectively)\n    - Bug fixes: \n        - Restore fence work-around for scan (reduce-by-key, etc.) hangs \n          in CUDA 8.5\n        - Issue 65: DeviceSegmentedRadixSort should allow inputs to have \n          pointer-to-const type \n        - Mollify Clang device-side warnings\n        - Remove out-dated VC project files\n          \t\t  \n//-----------------------------------------------------------------------------\n\n1.6.3    11/20/2016\n    - API change: BlockLoad and BlockStore are now templated by the local\n      data type, instead of the Iterator type.  This allows for output iterators\n      having \\p void as their \\p value_type (e.g., discard iterators).\n    - Updated GP100 tuning policies for radix sorting (6.2B 32b keys/s)\n    - Bug fixes: \n        - Issue #74: Warpreduce executes reduction operator for out-of-bounds items\n        - Issue #72 (cub:InequalityWrapper::operator() should be non-const)\n        - Issue #71 (KeyVairPair won't work if Key has non-trivial ctor)\n\t\t- Issue #70 1.5.3 breaks BlockScan API.  Retroactively reversioned\n\t\t  from v1.5.3 -> v1.6 to appropriately indicate API change.\n\t\t- Issue #69 cub::BlockStore::Store doesn't compile if OutputIteratorT::value_type != T  \n        - Issue #68 (cub::TilePrefixCallbackOp::WarpReduce doesn't permit ptx \n          arch specialization)\n\t\t- Improved support for Win32 platforms (warnings, alignment, etc)\n\t\t  \n//-----------------------------------------------------------------------------\n\n1.6.2 (was 1.5.5)    10/25/2016\n    - Updated Pascal tuning policies for radix sorting\n    - Bug fixes: \n        - Fix for arm64 compilation of caching allocator\n\n//-----------------------------------------------------------------------------\n\n1.6.1 (was 1.5.4)    10/14/2016\n    - Bug fixes: \n        - Fix for radix sorting bug introduced by scan refactorization\n\n//-----------------------------------------------------------------------------\n\n1.6.0 (was 1.5.3)    10/11/2016\n    - API change: Device/block/warp-wide exclusive scans have been revised to now \n      accept an \"initial value\" (instead of an \"identity value\") for seeding the \n      computation with an arbitrary prefix.  \n    - API change: Device-wide reductions and scans can now have input sequence types that are \n      different from output sequence types (as long as they are coercible)\n      value\") for seeding the computation with an arbitrary prefix\n    - Reduce repository size (move doxygen binary to doc repository)\n    - Minor reductions in block-scan instruction count\n    - Bug fixes: \n        - Issue #55: warning in cub/device/dispatch/dispatch_reduce_by_key.cuh \n        - Issue #59: cub::DeviceScan::ExclusiveSum can't prefix sum of float into double\n        - Issue #58: Infinite loop in cub::CachingDeviceAllocator::NearestPowerOf\n        - Issue #47: Caching allocator needs to clean up cuda error upon successful retry \n        - Issue #46: Very high amount of needed memory from the cub::DeviceHistogram::HistogramEven routine\n        - Issue #45: Caching Device Allocator fails with debug output enabled\n        - Fix for generic-type reduce-by-key warpscan (sm3.x and newer)\n\n//-----------------------------------------------------------------------------\n\n1.5.2    03/21/2016\n\t- Improved medium-size scan performance for sm5x (Maxwell)\n    - Refactored caching allocator for device memory\n   \t\t- Spends less time locked\n\t\t- Failure to allocate a block from the runtime will retry once after\n\t\t  freeing cached allocations\n\t\t- Now respects max-bin (issue where blocks in excess of max-bin were\n\t\t  still being retained in free cache)\n\t\t- Uses C++11 mutex when available\n    - Bug fixes: \n        - Fix for generic-type reduce-by-key warpscan (sm3.x and newer)\n          \n//-----------------------------------------------------------------------------\n\n1.5.1    12/28/2015\n    - Bug fixes: \n        - Fix for incorrect DeviceRadixSort output for some small problems on \n          Maxwell SM52 architectures\n        - Fix for macro redefinition warnings when compiling with Thrust sort\n          \n//-----------------------------------------------------------------------------\n\n1.5.0    12/14/2015\n    - New Features:\n        - Added new segmented device-wide operations for device-wide sort and \n          reduction primitives.\n    - Bug fixes: \n        - Fix for Git Issue 36 (Compilation error with GCC 4.8.4 nvcc 7.0.27) and\n          Forums thread (ThreadLoad generates compiler errors when loading from \n          pointer-to-const)\n        - Fix for Git Issue 29 (DeviceRadixSort::SortKeys<bool> yields compiler \n          errors)\n        - Fix for Git Issue 26 (CUDA error: misaligned address after \n          cub::DeviceRadixSort::SortKeys())\n        - Fix for incorrect/crash on 0-length problems, e.g., Git Issue 25 (Floating \n          point exception (core dumped) during cub::DeviceRadixSort::SortKeys)\n        - Fix for CUDA 7.5 issues on SM 5.2 with SHFL-based warp-scan and warp-reduction \n          on non-primitive data types (e.g., user-defined structs)\n        - Fix for small radix sorting problems where 0 temporary bytes were \n          required and users code was invoking malloc(0) on some systems where\n          that returns NULL.  (Impl assumed was asking for size again and was not \n          running the sort.)\n          \n//-----------------------------------------------------------------------------\n\n1.4.1    04/13/2015\n    - Bug fixes: \n        - Fixes for CUDA 7.0 issues with SHFL-based warp-scan and warp-reduction \n          on non-primitive data types (e.g., user-defined structs)\n        - Fixes for minor CUDA 7.0 performance regressions in cub::DeviceScan,\n          DeviceReduceByKey\n        - Fixes to allow cub::DeviceRadixSort and cub::BlockRadixSort on bool types\n        - Remove requirement for callers to define the CUB_CDP macro \n          when invoking CUB device-wide rountines using CUDA dynamic parallelism\n        - Fix for headers not being included in the proper order (or missing includes)\n          for some block-wide functions\n          \n//-----------------------------------------------------------------------------\n\n1.4.0    03/18/2015\n    - New Features:\n\t\t- Support and performance tuning for new Maxwell GPU architectures\n        - Updated cub::DeviceHistogram implementation that provides the same \n          \"histogram-even\" and \"histogram-range\" functionality as IPP/NPP.\n          Provides extremely fast and, perhaps more importantly, very \n          uniform performance response across diverse real-world datasets, \n          including pathological (homogeneous) sample distributions (resilience)\n        - New cub::DeviceSpmv methods for multiplying sparse matrices by \n          dense vectors, load-balanced using a merge-based parallel decomposition.\n        - New cub::DeviceRadixSort sorting entry-points that always return\n          the sorted output into the specified buffer (as opposed to the \n          cub::DoubleBuffer in which it could end up in either buffer)\n        - New cub::DeviceRunLengthEncode::NonTrivialRuns for finding the starting \n          offsets and lengths of all non-trivial runs (i.e., length > 1) of keys in \n          a given sequence.  (Useful for top-down partitioning algorithms like \n          MSD sorting of very-large keys.)\n          \n//-----------------------------------------------------------------------------\n\n1.3.2    07/28/2014\n    - Bug fixes: \n        - Fix for cub::DeviceReduce where reductions of small problems \n          (small enough to only dispatch a single thread block) would run in \n          the default stream (stream zero) regardless of whether an alternate\n          stream was specified.  \n          \n//-----------------------------------------------------------------------------\n\n1.3.1    05/23/2014\n    - Bug fixes: \n        - Workaround for a benign WAW race warning reported by cuda-memcheck\n          in BlockScan specialized for BLOCK_SCAN_WARP_SCANS algorithm.\n        - Fix for bug in DeviceRadixSort where the algorithm may sort more \n          key bits than the caller specified (up to the nearest radix digit).\n        - Fix for ~3% DeviceRadixSort performance regression on Kepler and \n          Fermi that was introduced in v1.3.0.  \n\n//-----------------------------------------------------------------------------\n\n1.3.0    05/12/2014\n    - New features:\n        - CUB's collective (block-wide, warp-wide) primitives underwent a minor \n          interface refactoring:\n            - To provide the appropriate support for multidimensional thread blocks,\n              The interfaces for collective classes are now template-parameterized \n              by X, Y, and Z block dimensions (with BLOCK_DIM_Y and BLOCK_DIM_Z being \n              optional, and BLOCK_DIM_X replacing BLOCK_THREADS).  Furthermore, the \n              constructors that accept remapped linear thread-identifiers have been \n              removed: all primitives now assume a row-major thread-ranking for \n              multidimensional thread blocks.  \n            - To allow the host program (compiled by the host-pass) to \n              accurately determine the device-specific storage requirements for \n              a given collective (compiled for each device-pass), the interfaces \n              for collective classes are now (optionally) template-parameterized \n              by the desired PTX compute capability. This is useful when \n              aliasing collective storage to shared memory that has been \n              allocated dynamically by the host at the kernel call site.   \n            - Most CUB programs having typical 1D usage should not require any \n              changes to accomodate these updates.\n        - Added new \"combination\" WarpScan methods for efficiently computing \n          both inclusive and exclusive prefix scans (and sums).\n    - Bug fixes: \n        - Fixed bug in cub::WarpScan (which affected cub::BlockScan and \n          cub::DeviceScan) where incorrect results (e.g., NAN) would often be \n          returned when parameterized for floating-point types (fp32, fp64).\n        - Workaround-fix for ptxas error when compiling with with -G flag on Linux \n          (for debug instrumentation) \n        - Misc. workaround-fixes for certain scan scenarios (using custom \n          scan operators) where code compiled for SM1x is run on newer \n          GPUs of higher compute-capability: the compiler could not tell\n          which memory space was being used collective operations and was \n          mistakenly using global ops instead of shared ops. \n\n//-----------------------------------------------------------------------------\n\n1.2.3    04/01/2014\n    - Bug fixes: \n        - Fixed access violation bug in DeviceReduce::ReduceByKey for non-primitive value types\n        - Fixed code-snippet bug in ArgIndexInputIteratorT documentation \n\n//-----------------------------------------------------------------------------\n\n1.2.2    03/03/2014\n    - New features:\n        - Added MS VC++ project solutions for device-wide and block-wide examples \n    - Performance:\n        - Added a third algorithmic variant of cub::BlockReduce for improved performance\n          when using commutative operators (e.g., numeric addition)\n    - Bug fixes: \n        - Fixed bug where inclusion of Thrust headers in a certain order prevented CUB device-wide primitives from working properly\n\n//-----------------------------------------------------------------------------\n\n1.2.0    02/25/2014\n    - New features:\n        - Added device-wide reduce-by-key (DeviceReduce::ReduceByKey, DeviceReduce::RunLengthEncode) \n    - Performance\n        - Improved DeviceScan, DeviceSelect, DevicePartition performance\n    - Documentation and testing:\n        - Compatible with CUDA 6.0\n        - Added performance-portability plots for many device-wide primitives to doc \n        - Update doc and tests to reflect iterator (in)compatibilities with CUDA 5.0 (and older) and Thrust 1.6 (and older).\n    - Bug fixes \n        - Revised the operation of temporary tile status bookkeeping for DeviceScan (and similar) to be safe for current code run on future platforms (now uses proper fences)  \n        - Fixed DeviceScan bug where Win32 alignment disagreements between host and device regarding user-defined data types would corrupt tile status\n        - Fixed BlockScan bug where certain exclusive scans on custom data types for the BLOCK_SCAN_WARP_SCANS variant would return incorrect results for the first thread in the block\n        - Added workaround for TexRefInputIteratorTto work with CUDA 6.0\n    \n//-----------------------------------------------------------------------------\n\n1.1.1    12/11/2013\n    - New features:\n        - Added TexObjInputIteratorT, TexRefInputIteratorT, CacheModifiedInputIteratorT, and CacheModifiedOutputIterator types for loading & storing arbitrary types through the cache hierarchy.  Compatible with Thrust API. \n        - Added descending sorting to DeviceRadixSort and BlockRadixSort\n        - Added min, max, arg-min, and arg-max to DeviceReduce\n        - Added DeviceSelect (select-unique, select-if, and select-flagged)\n        - Added DevicePartition (partition-if, partition-flagged)\n        - Added generic cub::ShuffleUp(), cub::ShuffleDown(), and cub::ShuffleIndex() for warp-wide communication of arbitrary data types (SM3x+)\n        - Added cub::MaxSmOccupancy() for accurately determining SM occupancy for any given kernel function pointer\n    - Performance\n        - Improved DeviceScan and DeviceRadixSort performance for older architectures (SM10-SM30)\n    - Interface changes:\n        - Refactored block-wide I/O (BlockLoad and BlockStore), removing cache-modifiers from their interfaces.  The CacheModifiedInputIteratorTand CacheModifiedOutputIterator should now be used with BlockLoad and BlockStore to effect that behavior.\n        - Rename device-wide \"stream_synchronous\" param to \"debug_synchronous\" to avoid confusion about usage\n    - Documentation and testing:\n        - Added simple examples of device-wide methods\n        - Improved doxygen documentation and example snippets\n        - Improved test coverege to include up to 21,000 kernel variants and 851,000 unit tests (per architecture, per platform)\n    - Bug fixes \n        - Fixed misc DeviceScan, BlockScan, DeviceReduce, and BlockReduce bugs when operating on non-primitive types for older architectures SM10-SM13\n        - Fixed DeviceScan / WarpReduction bug: SHFL-based segmented reduction producting incorrect results for multi-word types (size > 4B) on Linux \n        - Fixed BlockScan bug: For warpscan-based scans, not all threads in the first warp were entering the prefix callback functor\n        - Fixed DeviceRadixSort bug: race condition with key-value pairs for pre-SM35 architectures\n        - Fixed DeviceRadixSort bug: incorrect bitfield-extract behavior with long keys on 64bit Linux\n        - Fixed BlockDiscontinuity bug: complation error in for types other than int32/uint32\n        - CDP (device-callable) versions of device-wide methods now report the same temporary storage allocation size requirement as their host-callable counterparts\n     \n\n//-----------------------------------------------------------------------------\n\n1.0.2    08/23/2013\n    - Corrections to code snippet examples for BlockLoad, BlockStore, and BlockDiscontinuity\n    - Cleaned up unnecessary/missing header includes.  You can now safely #inlude a specific .cuh (instead of cub.cuh)\n    - Bug/compilation fixes for BlockHistogram \n\n//-----------------------------------------------------------------------------\n\n1.0.1    08/08/2013\n    - New collective interface idiom (specialize::construct::invoke).\n    - Added best-in-class DeviceRadixSort.  Implements short-circuiting for homogenous digit passes.\n    - Added best-in-class DeviceScan.  Implements single-pass \"adaptive-lookback\" strategy.\n    - Significantly improved documentation (with example code snippets) \n    - More extensive regression test suit for aggressively testing collective variants\n    - Allow non-trially-constructed types (previously unions had prevented aliasing temporary storage of those types)\n    - Improved support for Kepler SHFL (collective ops now use SHFL for types larger than 32b)\n    - Better code generation for 64-bit addressing within BlockLoad/BlockStore\n    - DeviceHistogram now supports histograms of arbitrary bins\n    - Misc. fixes\n      - Workarounds for SM10 codegen issues in uncommonly-used WarpScan/Reduce specializations\n      - Updates to accommodate CUDA 5.5 dynamic parallelism   \n\n\n//-----------------------------------------------------------------------------\n\n0.9.4    05/07/2013\n\n    - Fixed compilation errors for SM10-SM13\n    - Fixed compilation errors for some WarpScan entrypoints on SM30+\n    - Added block-wide histogram (BlockHistogram256)\n    - Added device-wide histogram (DeviceHistogram256)\n    - Added new BlockScan algorithm variant BLOCK_SCAN_RAKING_MEMOIZE, which \n      trades more register consumption for less shared memory I/O)\n    - Updates to BlockRadixRank to use BlockScan (which improves performance\n      on Kepler due to SHFL instruction)\n    - Allow types other than C++ primitives to be used in WarpScan::*Sum methods \n      if they only have operator + overloaded.  (Previously they also required \n      to support assignment from int(0).) \n    - Update BlockReduce's BLOCK_REDUCE_WARP_REDUCTIONS algorithm to work even \n      when block size is not an even multiple of warp size\n    - Added work management utility descriptors (GridQueue, GridEvenShare)\n    - Refactoring of DeviceAllocator interface and CachingDeviceAllocator \n      implementation \n    - Misc. documentation updates and corrections. \n     \n//-----------------------------------------------------------------------------\n\n0.9.2    04/04/2013\n\n    - Added WarpReduce.  WarpReduce uses the SHFL instruction when applicable. \n      BlockReduce now uses this WarpReduce instead of implementing its own.\n    - Misc. fixes for 64-bit Linux compilation warnings and errors.\n    - Misc. documentation updates and corrections. \n\n//-----------------------------------------------------------------------------\n\n0.9.1    03/09/2013\n\n    - Fix for ambiguity in BlockScan::Reduce() between generic reduction and \n      summation.  Summation entrypoints are now called ::Sum(), similar to the \n      convention in BlockScan.\n    - Small edits to mainpage documentation and download tracking\n    \n//-----------------------------------------------------------------------------\n\n0.9.0    03/07/2013    \n\n    - Intial \"preview\" release.    CUB is the first durable, high-performance library \n      of cooperative block-level, warp-level, and thread-level primitives for CUDA \n      kernel programming.  More primitives and examples coming soon!\n    "
  },
  {
    "path": "external/cub/LICENSE.TXT",
    "content": "Copyright (c) 2010-2011, Duane Merrill.  All rights reserved.\r\nCopyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\r\n\r\nRedistribution and use in source and binary forms, with or without\r\nmodification, are permitted provided that the following conditions are met:\r\n   *  Redistributions of source code must retain the above copyright\r\n      notice, this list of conditions and the following disclaimer.\r\n   *  Redistributions in binary form must reproduce the above copyright\r\n      notice, this list of conditions and the following disclaimer in the\r\n      documentation and/or other materials provided with the distribution.\r\n   *  Neither the name of the NVIDIA CORPORATION nor the\r\n      names of its contributors may be used to endorse or promote products\r\n      derived from this software without specific prior written permission.\r\n\r\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\r\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r\nDISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\r\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "external/cub/README.md",
    "content": "<hr>\n<h3>About CUB</h3>\n\nCurrent release: v1.7.4 (09/20/2017)\n\nWe recommend the [CUB Project Website](http://nvlabs.github.com/cub) and the [cub-users discussion forum](http://groups.google.com/group/cub-users) for further information and examples.\n\nCUB provides state-of-the-art, reusable software components for every layer \nof the CUDA programming model:\n- [<b><em>Device-wide primitives</em></b>] (https://nvlabs.github.com/cub/group___device_module.html) \n  - Sort, prefix scan, reduction, histogram, etc.  \n  - Compatible with CUDA dynamic parallelism\n- [<b><em>Block-wide \"collective\" primitives</em></b>] (https://nvlabs.github.com/cub/group___block_module.html)\n  - I/O, sort, prefix scan, reduction, histogram, etc.  \n  - Compatible with arbitrary thread block sizes and types \n- [<b><em>Warp-wide \"collective\" primitives</em></b>] (https://nvlabs.github.com/cub/group___warp_module.html)\n  - Warp-wide prefix scan, reduction, etc.\n  - Safe and architecture-specific\n- [<b><em>Thread and resource utilities</em></b>](https://nvlabs.github.com/cub/group___thread_module.html)\n  - PTX intrinsics, device reflection, texture-caching iterators, caching memory allocators, etc. \n\n![Orientation of collective primitives within the CUDA software stack](http://nvlabs.github.com/cub/cub_overview.png)\n\n<br><hr>\n<h3>A Simple Example</h3>\n\n```C++\n#include <cub/cub.cuh>\n \n// Block-sorting CUDA kernel\n__global__ void BlockSortKernel(int *d_in, int *d_out)\n{\n     using namespace cub;\n\n     // Specialize BlockRadixSort, BlockLoad, and BlockStore for 128 threads \n     // owning 16 integer items each\n     typedef BlockRadixSort<int, 128, 16>                     BlockRadixSort;\n     typedef BlockLoad<int, 128, 16, BLOCK_LOAD_TRANSPOSE>   BlockLoad;\n     typedef BlockStore<int, 128, 16, BLOCK_STORE_TRANSPOSE> BlockStore;\n \n     // Allocate shared memory\n     __shared__ union {\n         typename BlockRadixSort::TempStorage  sort;\n         typename BlockLoad::TempStorage       load; \n         typename BlockStore::TempStorage      store; \n     } temp_storage; \n\n     int block_offset = blockIdx.x * (128 * 16);\t  // OffsetT for this block's ment\n\n     // Obtain a segment of 2048 consecutive keys that are blocked across threads\n     int thread_keys[16];\n     BlockLoad(temp_storage.load).Load(d_in + block_offset, thread_keys);\n     __syncthreads();\n\n     // Collectively sort the keys\n     BlockRadixSort(temp_storage.sort).Sort(thread_keys);\n     __syncthreads();\n\n     // Store the sorted segment \n     BlockStore(temp_storage.store).Store(d_out + block_offset, thread_keys);\n}\n```\n\nEach thread block uses cub::BlockRadixSort to collectively sort \nits own input segment.  The class is specialized by the \ndata type being sorted, by the number of threads per block, by the number of \nkeys per thread, and implicitly by the targeted compilation architecture.  \n\nThe cub::BlockLoad and cub::BlockStore classes are similarly specialized.    \nFurthermore, to provide coalesced accesses to device memory, these primitives are \nconfigured to access memory using a striped access pattern (where consecutive threads \nsimultaneously access consecutive items) and then <em>transpose</em> the keys into \na [<em>blocked arrangement</em>](index.html#sec4sec3) of elements across threads. \n\nOnce specialized, these classes expose opaque \\p TempStorage member types.  \nThe thread block uses these storage types to statically allocate the union of \nshared memory needed by the thread block.  (Alternatively these storage types \ncould be aliased to global memory allocations).\n\n<br><hr>\n<h3>Stable Releases</h3>\n\nCUB releases are labeled using version identifiers having three fields: \n*epoch.feature.update*.  The *epoch* field corresponds to support for\na major change in the CUDA programming model.  The *feature* field \ncorresponds to a stable set of features, functionality, and interface.  The\n*update* field corresponds to a bug-fix or performance update for that\nfeature set.  At the moment, we do not publicly provide non-stable releases \nsuch as development snapshots, beta releases or rolling releases.  (Feel free\nto contact us if you would like such things.)  See the \n[CUB Project Website](http://nvlabs.github.com/cub) for more information.\n\n<br><hr>\n<h3>Contributors</h3>\n\nCUB is developed as an open-source project by [NVIDIA Research](http://research.nvidia.com).  The primary contributor is [Duane Merrill](http://github.com/dumerrill).\n\n<br><hr>\n<h3>Open Source License</h3>\n\nCUB is available under the \"New BSD\" open-source license:\n\n```\nCopyright (c) 2010-2011, Duane Merrill.  All rights reserved.\nCopyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n   *  Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n   *  Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n   *  Neither the name of the NVIDIA CORPORATION nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n```\n"
  },
  {
    "path": "external/cub/common.mk",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n\n\n#-------------------------------------------------------------------------------\n# Commandline Options\n#-------------------------------------------------------------------------------\n\n# [sm=<XXX,...>] Compute-capability to compile for, e.g., \"sm=200,300,350\" (SM20 by default).\n  \nCOMMA = ,\nifdef sm\n\tSM_ARCH = $(subst $(COMMA),-,$(sm))\nelse \n    SM_ARCH = 200\nendif\n\nifeq (700, $(findstring 700, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_70,code=\\\"sm_70,compute_70\\\" \n    SM_DEF \t\t+= -DSM700\n    TEST_ARCH \t= 700\nendif\nifeq (620, $(findstring 620, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_62,code=\\\"sm_62,compute_62\\\" \n    SM_DEF \t\t+= -DSM620\n    TEST_ARCH \t= 620\nendif\nifeq (610, $(findstring 610, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_61,code=\\\"sm_61,compute_61\\\" \n    SM_DEF \t\t+= -DSM610\n    TEST_ARCH \t= 610\nendif\nifeq (600, $(findstring 600, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_60,code=\\\"sm_60,compute_60\\\" \n    SM_DEF \t\t+= -DSM600\n    TEST_ARCH \t= 600\nendif\nifeq (520, $(findstring 520, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_52,code=\\\"sm_52,compute_52\\\" \n    SM_DEF \t\t+= -DSM520\n    TEST_ARCH \t= 520\nendif\nifeq (370, $(findstring 370, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_37,code=\\\"sm_37,compute_37\\\" \n    SM_DEF \t\t+= -DSM370\n    TEST_ARCH \t= 370\nendif\nifeq (350, $(findstring 350, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_35,code=\\\"sm_35,compute_35\\\" \n    SM_DEF \t\t+= -DSM350\n    TEST_ARCH \t= 350\nendif\nifeq (300, $(findstring 300, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_30,code=\\\"sm_30,compute_30\\\"\n    SM_DEF \t\t+= -DSM300\n    TEST_ARCH \t= 300\nendif\nifeq (210, $(findstring 210, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_20,code=\\\"sm_21,compute_20\\\"\n    SM_DEF \t\t+= -DSM210\n    TEST_ARCH \t= 210\nendif\nifeq (200, $(findstring 200, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_20,code=\\\"sm_20,compute_20\\\"\n    SM_DEF \t\t+= -DSM200\n    TEST_ARCH \t= 200\nendif\nifeq (130, $(findstring 130, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_13,code=\\\"sm_13,compute_13\\\" \n    SM_DEF \t\t+= -DSM130\n    TEST_ARCH \t= 130\nendif\nifeq (120, $(findstring 120, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_12,code=\\\"sm_12,compute_12\\\" \n    SM_DEF \t\t+= -DSM120\n    TEST_ARCH \t= 120\nendif\nifeq (110, $(findstring 110, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_11,code=\\\"sm_11,compute_11\\\" \n    SM_DEF \t\t+= -DSM110\n    TEST_ARCH \t= 110\nendif\nifeq (100, $(findstring 100, $(SM_ARCH)))\n    SM_TARGETS \t+= -gencode=arch=compute_10,code=\\\"sm_10,compute_10\\\" \n    SM_DEF \t\t+= -DSM100\n    TEST_ARCH \t= 100\nendif\n\n\n# [cdp=<0|1>] CDP enable option (default: no)\nifeq ($(cdp), 1)\n\tDEFINES += -DCUB_CDP\n\tCDP_SUFFIX = cdp\n    NVCCFLAGS += -rdc=true -lcudadevrt\nelse\n\tCDP_SUFFIX = nocdp\nendif\n\n\n# [force32=<0|1>] Device addressing mode option (64-bit device pointers by default) \nifeq ($(force32), 1)\n\tCPU_ARCH = -m32\n\tCPU_ARCH_SUFFIX = i386\nelse\n\tCPU_ARCH = -m64\n\tCPU_ARCH_SUFFIX = x86_64\n    NPPI = -lnppist\nendif\n\n\n# [abi=<0|1>] CUDA ABI option (enabled by default) \nifneq ($(abi), 0)\n\tABI_SUFFIX = abi\nelse \n\tNVCCFLAGS += -Xptxas -abi=no\n\tABI_SUFFIX = noabi\nendif\n\n\n# [open64=<0|1>] Middle-end compiler option (nvvm by default)\nifeq ($(open64), 1)\n\tNVCCFLAGS += -open64\n\tPTX_SUFFIX = open64\nelse \n\tPTX_SUFFIX = nvvm\nendif\n\n\n# [verbose=<0|1>] Verbose toolchain output from nvcc option\nifeq ($(verbose), 1)\n\tNVCCFLAGS += -v\nendif\n\n\n# [keep=<0|1>] Keep intermediate compilation artifacts option\nifeq ($(keep), 1)\n\tNVCCFLAGS += -keep\nendif\n\n# [debug=<0|1>] Generate debug mode code\nifeq ($(debug), 1)\n\tNVCCFLAGS += -G\nendif\n\n\n#-------------------------------------------------------------------------------\n# Compiler and compilation platform\n#-------------------------------------------------------------------------------\n\nCUB_DIR = $(dir $(lastword $(MAKEFILE_LIST)))\n\nNVCC = \"$(shell which nvcc)\"\nifdef nvccver\n    NVCC_VERSION = $(nvccver)\nelse\n    NVCC_VERSION = $(strip $(shell nvcc --version | grep release | sed 's/.*release //' |  sed 's/,.*//'))\nendif\n\n# detect OS\nOSUPPER = $(shell uname -s 2>/dev/null | tr [:lower:] [:upper:])\n\n# Default flags: verbose kernel properties (regs, smem, cmem, etc.); runtimes for compilation phases \nNVCCFLAGS += $(SM_DEF) -Xptxas -v -Xcudafe -\\# \n\nifeq (WIN_NT, $(findstring WIN_NT, $(OSUPPER)))\n    # For MSVC\n    # Enable more warnings and treat as errors\n    NVCCFLAGS += -Xcompiler /W3 -Xcompiler /WX\n    # Disable excess x86 floating point precision that can lead to results being labeled incorrectly\n    NVCCFLAGS += -Xcompiler /fp:strict\n    # Help the compiler/linker work with huge numbers of kernels on Windows\n\tNVCCFLAGS += -Xcompiler /bigobj -Xcompiler /Zm500\n\tCC = cl\n\t\n\t# Multithreaded runtime\n\tNVCCFLAGS += -Xcompiler /MT\n\t\nifneq ($(force32), 1)\n\tCUDART_CYG = \"$(shell dirname $(NVCC))/../lib/Win32/cudart.lib\"\nelse\n\tCUDART_CYG = \"$(shell dirname $(NVCC))/../lib/x64/cudart.lib\"\nendif\n\tCUDART = \"$(shell cygpath -w $(CUDART_CYG))\"\nelse\n    # For g++\n    # Disable excess x86 floating point precision that can lead to results being labeled incorrectly\n    NVCCFLAGS += -Xcompiler -ffloat-store\n    CC = g++\nifneq ($(force32), 1)\n    CUDART = \"$(shell dirname $(NVCC))/../lib/libcudart_static.a\"\nelse\n    CUDART = \"$(shell dirname $(NVCC))/../lib64/libcudart_static.a\"\nendif\nendif\n\n# Suffix to append to each binary\nBIN_SUFFIX = sm$(SM_ARCH)_$(PTX_SUFFIX)_$(NVCC_VERSION)_$(ABI_SUFFIX)_$(CDP_SUFFIX)_$(CPU_ARCH_SUFFIX)\n\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nrwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nCUB_DEPS = \t$(call rwildcard, $(CUB_DIR),*.cuh) \\\n\t\t\t$(CUB_DIR)common.mk\n\t\t\n"
  },
  {
    "path": "external/cub/cub/agent/agent_histogram.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentHistogram implements a stateful abstraction of CUDA thread blocks for participating in device-wide histogram .\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"../util_type.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../grid/grid_queue.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy\n ******************************************************************************/\n\n/**\n *\n */\nenum BlockHistogramMemoryPreference\n{\n    GMEM,\n    SMEM,\n    BLEND\n};\n\n\n/**\n * Parameterizable tuning policy type for AgentHistogram\n */\ntemplate <\n    int                             _BLOCK_THREADS,                 ///< Threads per thread block\n    int                             _PIXELS_PER_THREAD,             ///< Pixels per thread (per tile of input)\n    BlockLoadAlgorithm              _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier               _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    bool                            _RLE_COMPRESS,                  ///< Whether to perform localized RLE to compress samples before histogramming\n    BlockHistogramMemoryPreference  _MEM_PREFERENCE,                ///< Whether to prefer privatized shared-memory bins (versus privatized global-memory bins)\n    bool                            _WORK_STEALING>                 ///< Whether to dequeue tiles from a global work queue\nstruct AgentHistogramPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,                   ///< Threads per thread block\n        PIXELS_PER_THREAD       = _PIXELS_PER_THREAD,               ///< Pixels per thread (per tile of input)\n        IS_RLE_COMPRESS         = _RLE_COMPRESS,                    ///< Whether to perform localized RLE to compress samples before histogramming\n        MEM_PREFERENCE          = _MEM_PREFERENCE,                  ///< Whether to prefer privatized shared-memory bins (versus privatized global-memory bins)\n        IS_WORK_STEALING        = _WORK_STEALING,                   ///< Whether to dequeue tiles from a global work queue\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;          ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;           ///< Cache load modifier for reading input elements\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentHistogram implements a stateful abstraction of CUDA thread blocks for participating in device-wide histogram .\n */\ntemplate <\n    typename    AgentHistogramPolicyT,     ///< Parameterized AgentHistogramPolicy tuning policy type\n    int         PRIVATIZED_SMEM_BINS,           ///< Number of privatized shared-memory histogram bins of any channel.  Zero indicates privatized counters to be maintained in device-accessible memory.\n    int         NUM_CHANNELS,                   ///< Number of channels interleaved in the input data.  Supports up to four channels.\n    int         NUM_ACTIVE_CHANNELS,            ///< Number of channels actively being histogrammed\n    typename    SampleIteratorT,                ///< Random-access input iterator type for reading samples\n    typename    CounterT,                       ///< Integer type for counting sample occurrences per histogram bin\n    typename    PrivatizedDecodeOpT,            ///< The transform operator type for determining privatized counter indices from samples, one for each channel\n    typename    OutputDecodeOpT,                ///< The transform operator type for determining output bin-ids from privatized counter indices, one for each channel\n    typename    OffsetT,                        ///< Signed integer type for global offsets\n    int         PTX_ARCH = CUB_PTX_ARCH>        ///< PTX compute capability\nstruct AgentHistogram\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// The sample type of the input iterator\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    /// The pixel type of SampleT\n    typedef typename CubVector<SampleT, NUM_CHANNELS>::Type PixelT;\n\n    /// The quad type of SampleT\n    typedef typename CubVector<SampleT, 4>::Type QuadT;\n\n    /// Constants\n    enum\n    {\n        BLOCK_THREADS           = AgentHistogramPolicyT::BLOCK_THREADS,\n\n        PIXELS_PER_THREAD       = AgentHistogramPolicyT::PIXELS_PER_THREAD,\n        SAMPLES_PER_THREAD      = PIXELS_PER_THREAD * NUM_CHANNELS,\n        QUADS_PER_THREAD        = SAMPLES_PER_THREAD / 4,\n\n        TILE_PIXELS             = PIXELS_PER_THREAD * BLOCK_THREADS,\n        TILE_SAMPLES            = SAMPLES_PER_THREAD * BLOCK_THREADS,\n\n        IS_RLE_COMPRESS            = AgentHistogramPolicyT::IS_RLE_COMPRESS,\n\n        MEM_PREFERENCE          = (PRIVATIZED_SMEM_BINS > 0) ?\n                                        AgentHistogramPolicyT::MEM_PREFERENCE :\n                                        GMEM,\n\n        IS_WORK_STEALING           = AgentHistogramPolicyT::IS_WORK_STEALING,\n    };\n\n    /// Cache load modifier for reading input elements\n    static const CacheLoadModifier LOAD_MODIFIER = AgentHistogramPolicyT::LOAD_MODIFIER;\n\n\n    /// Input iterator wrapper type (for applying cache modifier)\n    typedef typename If<IsPointer<SampleIteratorT>::VALUE,\n            CacheModifiedInputIterator<LOAD_MODIFIER, SampleT, OffsetT>,     // Wrap the native input pointer with CacheModifiedInputIterator\n            SampleIteratorT>::Type                                           // Directly use the supplied input iterator type\n        WrappedSampleIteratorT;\n\n    /// Pixel input iterator type (for applying cache modifier)\n    typedef CacheModifiedInputIterator<LOAD_MODIFIER, PixelT, OffsetT>\n        WrappedPixelIteratorT;\n\n    /// Qaud input iterator type (for applying cache modifier)\n    typedef CacheModifiedInputIterator<LOAD_MODIFIER, QuadT, OffsetT>\n        WrappedQuadIteratorT;\n\n    /// Parameterized BlockLoad type for samples\n    typedef BlockLoad<\n            SampleT,\n            BLOCK_THREADS,\n            SAMPLES_PER_THREAD,\n            AgentHistogramPolicyT::LOAD_ALGORITHM>\n        BlockLoadSampleT;\n\n    /// Parameterized BlockLoad type for pixels\n    typedef BlockLoad<\n            PixelT,\n            BLOCK_THREADS,\n            PIXELS_PER_THREAD,\n            AgentHistogramPolicyT::LOAD_ALGORITHM>\n        BlockLoadPixelT;\n\n    /// Parameterized BlockLoad type for quads\n    typedef BlockLoad<\n            QuadT,\n            BLOCK_THREADS,\n            QUADS_PER_THREAD,\n            AgentHistogramPolicyT::LOAD_ALGORITHM>\n        BlockLoadQuadT;\n\n    /// Shared memory type required by this thread block\n    struct _TempStorage\n    {\n        CounterT histograms[NUM_ACTIVE_CHANNELS][PRIVATIZED_SMEM_BINS + 1];     // Smem needed for block-privatized smem histogram (with 1 word of padding)\n\n        int tile_idx;\n\n        // Aliasable storage layout\n        union Aliasable\n        {\n            typename BlockLoadSampleT::TempStorage sample_load;     // Smem needed for loading a tile of samples\n            typename BlockLoadPixelT::TempStorage pixel_load;       // Smem needed for loading a tile of pixels\n            typename BlockLoadQuadT::TempStorage quad_load;         // Smem needed for loading a tile of quads\n\n        } aliasable;\n    };\n\n\n    /// Temporary storage type (unionable)\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    /// Reference to temp_storage\n    _TempStorage &temp_storage;\n\n    /// Sample input iterator (with cache modifier applied, if possible)\n    WrappedSampleIteratorT d_wrapped_samples;\n\n    /// Native pointer for input samples (possibly NULL if unavailable)\n    SampleT* d_native_samples;\n\n    /// The number of output bins for each channel\n    int (&num_output_bins)[NUM_ACTIVE_CHANNELS];\n\n    /// The number of privatized bins for each channel\n    int (&num_privatized_bins)[NUM_ACTIVE_CHANNELS];\n\n    /// Reference to gmem privatized histograms for each channel\n    CounterT* d_privatized_histograms[NUM_ACTIVE_CHANNELS];\n\n    /// Reference to final output histograms (gmem)\n    CounterT* (&d_output_histograms)[NUM_ACTIVE_CHANNELS];\n\n    /// The transform operator for determining output bin-ids from privatized counter indices, one for each channel\n    OutputDecodeOpT (&output_decode_op)[NUM_ACTIVE_CHANNELS];\n\n    /// The transform operator for determining privatized counter indices from samples, one for each channel\n    PrivatizedDecodeOpT (&privatized_decode_op)[NUM_ACTIVE_CHANNELS];\n\n    /// Whether to prefer privatized smem counters vs privatized global counters\n    bool prefer_smem;\n\n\n    //---------------------------------------------------------------------\n    // Initialize privatized bin counters\n    //---------------------------------------------------------------------\n\n    // Initialize privatized bin counters\n    __device__ __forceinline__ void InitBinCounters(CounterT* privatized_histograms[NUM_ACTIVE_CHANNELS])\n    {\n        // Initialize histogram bin counts to zeros\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n        {\n            for (int privatized_bin = threadIdx.x; privatized_bin < num_privatized_bins[CHANNEL]; privatized_bin += BLOCK_THREADS)\n            {\n                privatized_histograms[CHANNEL][privatized_bin] = 0;\n            }\n        }\n\n        // Barrier to make sure all threads are done updating counters\n        CTA_SYNC();\n    }\n\n\n    // Initialize privatized bin counters.  Specialized for privatized shared-memory counters\n    __device__ __forceinline__ void InitSmemBinCounters()\n    {\n        CounterT* privatized_histograms[NUM_ACTIVE_CHANNELS];\n\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n            privatized_histograms[CHANNEL] = temp_storage.histograms[CHANNEL];\n\n        InitBinCounters(privatized_histograms);\n    }\n\n\n    // Initialize privatized bin counters.  Specialized for privatized global-memory counters\n    __device__ __forceinline__ void InitGmemBinCounters()\n    {\n        InitBinCounters(d_privatized_histograms);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Update final output histograms\n    //---------------------------------------------------------------------\n\n    // Update final output histograms from privatized histograms\n    __device__ __forceinline__ void StoreOutput(CounterT* privatized_histograms[NUM_ACTIVE_CHANNELS])\n    {\n        // Barrier to make sure all threads are done updating counters\n        CTA_SYNC();\n\n        // Apply privatized bin counts to output bin counts\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n        {\n            int channel_bins = num_privatized_bins[CHANNEL];\n            for (int privatized_bin = threadIdx.x; \n                    privatized_bin < channel_bins;  \n                    privatized_bin += BLOCK_THREADS)\n            {\n                int         output_bin  = -1;\n                CounterT    count       = privatized_histograms[CHANNEL][privatized_bin];\n                bool        is_valid    = count > 0;\n\n                output_decode_op[CHANNEL].template BinSelect<LOAD_MODIFIER>((SampleT) privatized_bin, output_bin, is_valid);\n\n                if (output_bin >= 0)\n                {\n                    atomicAdd(&d_output_histograms[CHANNEL][output_bin], count);\n                }\n\n            }\n        }\n    }\n\n\n    // Update final output histograms from privatized histograms.  Specialized for privatized shared-memory counters\n    __device__ __forceinline__ void StoreSmemOutput()\n    {\n        CounterT* privatized_histograms[NUM_ACTIVE_CHANNELS];\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n            privatized_histograms[CHANNEL] = temp_storage.histograms[CHANNEL];\n\n        StoreOutput(privatized_histograms);\n    }\n\n\n    // Update final output histograms from privatized histograms.  Specialized for privatized global-memory counters\n    __device__ __forceinline__ void StoreGmemOutput()\n    {\n        StoreOutput(d_privatized_histograms);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Tile accumulation\n    //---------------------------------------------------------------------\n\n    // Accumulate pixels.  Specialized for RLE compression.\n    __device__ __forceinline__ void AccumulatePixels(\n        SampleT             samples[PIXELS_PER_THREAD][NUM_CHANNELS],\n        bool                is_valid[PIXELS_PER_THREAD],\n        CounterT*           privatized_histograms[NUM_ACTIVE_CHANNELS],\n        Int2Type<true>      is_rle_compress)\n    {\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n        {\n            // Bin pixels\n            int bins[PIXELS_PER_THREAD];\n\n            #pragma unroll\n            for (int PIXEL = 0; PIXEL < PIXELS_PER_THREAD; ++PIXEL)\n            {\n                bins[PIXEL] = -1;\n                privatized_decode_op[CHANNEL].template BinSelect<LOAD_MODIFIER>(samples[PIXEL][CHANNEL], bins[PIXEL], is_valid[PIXEL]);\n            }\n\n            CounterT accumulator = 1;\n\n            #pragma unroll\n            for (int PIXEL = 0; PIXEL < PIXELS_PER_THREAD - 1; ++PIXEL)\n            {\n                if (bins[PIXEL] != bins[PIXEL + 1])\n                {\n                    if (bins[PIXEL] >= 0)\n                        atomicAdd(privatized_histograms[CHANNEL] + bins[PIXEL], accumulator);\n\n                     accumulator = 0;\n                }\n                accumulator++;\n            }\n\n            // Last pixel\n            if (bins[PIXELS_PER_THREAD - 1] >= 0)\n                atomicAdd(privatized_histograms[CHANNEL] + bins[PIXELS_PER_THREAD - 1], accumulator);\n        }\n    }\n\n\n    // Accumulate pixels.  Specialized for individual accumulation of each pixel.\n    __device__ __forceinline__ void AccumulatePixels(\n        SampleT             samples[PIXELS_PER_THREAD][NUM_CHANNELS],\n        bool                is_valid[PIXELS_PER_THREAD],\n        CounterT*           privatized_histograms[NUM_ACTIVE_CHANNELS],\n        Int2Type<false>     is_rle_compress)\n    {\n        #pragma unroll\n        for (int PIXEL = 0; PIXEL < PIXELS_PER_THREAD; ++PIXEL)\n        {\n            #pragma unroll\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n            {\n                int bin = -1;\n                privatized_decode_op[CHANNEL].template BinSelect<LOAD_MODIFIER>(samples[PIXEL][CHANNEL], bin, is_valid[PIXEL]);\n                if (bin >= 0)\n                    atomicAdd(privatized_histograms[CHANNEL] + bin, 1);\n            }\n        }\n    }\n\n\n    /**\n     * Accumulate pixel, specialized for smem privatized histogram\n     */\n    __device__ __forceinline__ void AccumulateSmemPixels(\n        SampleT             samples[PIXELS_PER_THREAD][NUM_CHANNELS],\n        bool                is_valid[PIXELS_PER_THREAD])\n    {\n        CounterT* privatized_histograms[NUM_ACTIVE_CHANNELS];\n\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n            privatized_histograms[CHANNEL] = temp_storage.histograms[CHANNEL];\n\n        AccumulatePixels(samples, is_valid, privatized_histograms, Int2Type<IS_RLE_COMPRESS>());\n    }\n\n\n    /**\n     * Accumulate pixel, specialized for gmem privatized histogram\n     */\n    __device__ __forceinline__ void AccumulateGmemPixels(\n        SampleT             samples[PIXELS_PER_THREAD][NUM_CHANNELS],\n        bool                is_valid[PIXELS_PER_THREAD])\n    {\n        AccumulatePixels(samples, is_valid, d_privatized_histograms, Int2Type<IS_RLE_COMPRESS>());\n    }\n\n\n\n    //---------------------------------------------------------------------\n    // Tile loading\n    //---------------------------------------------------------------------\n\n    // Load full, aligned tile using pixel iterator (multi-channel)\n    template <int _NUM_ACTIVE_CHANNELS>\n    __device__ __forceinline__ void LoadFullAlignedTile(\n        OffsetT                         block_offset,\n        int                             valid_samples,\n        SampleT                         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<_NUM_ACTIVE_CHANNELS>  num_active_channels)\n    {\n        typedef PixelT AliasedPixels[PIXELS_PER_THREAD];\n\n        WrappedPixelIteratorT d_wrapped_pixels((PixelT*) (d_native_samples + block_offset));\n\n        // Load using a wrapped pixel iterator\n        BlockLoadPixelT(temp_storage.aliasable.pixel_load).Load(\n            d_wrapped_pixels,\n            reinterpret_cast<AliasedPixels&>(samples));\n    }\n\n    // Load full, aligned tile using quad iterator (single-channel)\n    __device__ __forceinline__ void LoadFullAlignedTile(\n        OffsetT                         block_offset,\n        int                             valid_samples,\n        SampleT                         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<1>                     num_active_channels)\n    {\n        typedef QuadT AliasedQuads[QUADS_PER_THREAD];\n\n        WrappedQuadIteratorT d_wrapped_quads((QuadT*) (d_native_samples + block_offset));\n\n        // Load using a wrapped quad iterator\n        BlockLoadQuadT(temp_storage.aliasable.quad_load).Load(\n            d_wrapped_quads,\n            reinterpret_cast<AliasedQuads&>(samples));\n    }\n\n    // Load full, aligned tile\n    __device__ __forceinline__ void LoadTile(\n        OffsetT         block_offset,\n        int             valid_samples,\n        SampleT         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<true>  is_full_tile,\n        Int2Type<true>  is_aligned)\n    {\n        LoadFullAlignedTile(block_offset, valid_samples, samples, Int2Type<NUM_ACTIVE_CHANNELS>());\n    }\n\n    // Load full, mis-aligned tile using sample iterator\n    __device__ __forceinline__ void LoadTile(\n        OffsetT         block_offset,\n        int             valid_samples,\n        SampleT         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<true>  is_full_tile,\n        Int2Type<false> is_aligned)\n    {\n        typedef SampleT AliasedSamples[SAMPLES_PER_THREAD];\n\n        // Load using sample iterator\n        BlockLoadSampleT(temp_storage.aliasable.sample_load).Load(\n            d_wrapped_samples + block_offset,\n            reinterpret_cast<AliasedSamples&>(samples));\n    }\n\n    // Load partially-full, aligned tile using the pixel iterator\n    __device__ __forceinline__ void LoadTile(\n        OffsetT         block_offset,\n        int             valid_samples,\n        SampleT         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<false> is_full_tile,\n        Int2Type<true>  is_aligned)\n    {\n        typedef PixelT AliasedPixels[PIXELS_PER_THREAD];\n\n        WrappedPixelIteratorT d_wrapped_pixels((PixelT*) (d_native_samples + block_offset));\n\n        int valid_pixels = valid_samples / NUM_CHANNELS;\n\n        // Load using a wrapped pixel iterator\n        BlockLoadPixelT(temp_storage.aliasable.pixel_load).Load(\n            d_wrapped_pixels,\n            reinterpret_cast<AliasedPixels&>(samples),\n            valid_pixels);\n    }\n\n    // Load partially-full, mis-aligned tile using sample iterator\n    __device__ __forceinline__ void LoadTile(\n        OffsetT         block_offset,\n        int             valid_samples,\n        SampleT         (&samples)[PIXELS_PER_THREAD][NUM_CHANNELS],\n        Int2Type<false> is_full_tile,\n        Int2Type<false> is_aligned)\n    {\n        typedef SampleT AliasedSamples[SAMPLES_PER_THREAD];\n\n        BlockLoadSampleT(temp_storage.aliasable.sample_load).Load(\n            d_wrapped_samples + block_offset,\n            reinterpret_cast<AliasedSamples&>(samples),\n            valid_samples);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Tile processing\n    //---------------------------------------------------------------------\n\n    // Consume a tile of data samples\n    template <\n        bool IS_ALIGNED,        // Whether the tile offset is aligned (quad-aligned for single-channel, pixel-aligned for multi-channel)\n        bool IS_FULL_TILE>      // Whether the tile is full\n    __device__ __forceinline__ void ConsumeTile(OffsetT block_offset, int valid_samples)\n    {\n        SampleT     samples[PIXELS_PER_THREAD][NUM_CHANNELS];\n        bool        is_valid[PIXELS_PER_THREAD];\n\n        // Load tile\n        LoadTile(\n            block_offset,\n            valid_samples,\n            samples,\n            Int2Type<IS_FULL_TILE>(),\n            Int2Type<IS_ALIGNED>());\n\n        // Set valid flags\n        #pragma unroll\n        for (int PIXEL = 0; PIXEL < PIXELS_PER_THREAD; ++PIXEL)\n            is_valid[PIXEL] = IS_FULL_TILE || (((threadIdx.x * PIXELS_PER_THREAD + PIXEL) * NUM_CHANNELS) < valid_samples);\n\n        // Accumulate samples\n#if CUB_PTX_ARCH >= 120\n        if (prefer_smem)\n            AccumulateSmemPixels(samples, is_valid);\n        else\n            AccumulateGmemPixels(samples, is_valid);\n#else\n        AccumulateGmemPixels(samples, is_valid);\n#endif\n\n    }\n\n\n    // Consume row tiles.  Specialized for work-stealing from queue\n    template <bool IS_ALIGNED>\n    __device__ __forceinline__ void ConsumeTiles(\n        OffsetT             num_row_pixels,             ///< The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                   ///< The number of rows in the region of interest\n        OffsetT             row_stride_samples,         ///< The number of samples between starts of consecutive rows in the region of interest\n        int                 tiles_per_row,              ///< Number of image tiles per row\n        GridQueue<int>      tile_queue,\n        Int2Type<true>      is_work_stealing)\n    {\n\n        int         num_tiles                   = num_rows * tiles_per_row;\n        int         tile_idx                    = (blockIdx.y  * gridDim.x) + blockIdx.x;\n        OffsetT     num_even_share_tiles        = gridDim.x * gridDim.y;\n\n        while (tile_idx < num_tiles)\n        {\n            int     row             = tile_idx / tiles_per_row;\n            int     col             = tile_idx - (row * tiles_per_row);\n            OffsetT row_offset      = row * row_stride_samples;\n            OffsetT col_offset      = (col * TILE_SAMPLES);\n            OffsetT tile_offset     = row_offset + col_offset;\n\n            if (col == tiles_per_row - 1)\n            {\n                // Consume a partially-full tile at the end of the row\n                OffsetT num_remaining = (num_row_pixels * NUM_CHANNELS) - col_offset;\n                ConsumeTile<IS_ALIGNED, false>(tile_offset, num_remaining);\n            } \n            else\n            {\n                // Consume full tile\n                ConsumeTile<IS_ALIGNED, true>(tile_offset, TILE_SAMPLES);\n            }\n\n            CTA_SYNC();\n\n            // Get next tile\n            if (threadIdx.x == 0)\n                temp_storage.tile_idx = tile_queue.Drain(1) + num_even_share_tiles;\n\n            CTA_SYNC();\n\n            tile_idx = temp_storage.tile_idx;\n        }\n    }\n\n\n    // Consume row tiles.  Specialized for even-share (striped across thread blocks)\n    template <bool IS_ALIGNED>\n    __device__ __forceinline__ void ConsumeTiles(\n        OffsetT             num_row_pixels,             ///< The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                   ///< The number of rows in the region of interest\n        OffsetT             row_stride_samples,         ///< The number of samples between starts of consecutive rows in the region of interest\n        int                 tiles_per_row,              ///< Number of image tiles per row\n        GridQueue<int>      tile_queue,\n        Int2Type<false>     is_work_stealing)\n    {\n        for (int row = blockIdx.y; row < num_rows; row += gridDim.y)\n        {\n            OffsetT row_begin   = row * row_stride_samples;\n            OffsetT row_end     = row_begin + (num_row_pixels * NUM_CHANNELS);\n            OffsetT tile_offset = row_begin + (blockIdx.x * TILE_SAMPLES);\n\n            while (tile_offset < row_end)\n            {\n                OffsetT num_remaining = row_end - tile_offset;\n\n                if (num_remaining < TILE_SAMPLES)\n                {\n                    // Consume partial tile\n                    ConsumeTile<IS_ALIGNED, false>(tile_offset, num_remaining);\n                    break;\n                }\n\n                // Consume full tile\n                ConsumeTile<IS_ALIGNED, true>(tile_offset, TILE_SAMPLES);\n                tile_offset += gridDim.x * TILE_SAMPLES;\n            }\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Parameter extraction\n    //---------------------------------------------------------------------\n\n    // Return a native pixel pointer (specialized for CacheModifiedInputIterator types)\n    template <\n        CacheLoadModifier   _MODIFIER,\n        typename            _ValueT,\n        typename            _OffsetT>\n    __device__ __forceinline__ SampleT* NativePointer(CacheModifiedInputIterator<_MODIFIER, _ValueT, _OffsetT> itr)\n    {\n        return itr.ptr;\n    }\n\n    // Return a native pixel pointer (specialized for other types)\n    template <typename IteratorT>\n    __device__ __forceinline__ SampleT* NativePointer(IteratorT itr)\n    {\n        return NULL;\n    }\n\n\n\n    //---------------------------------------------------------------------\n    // Interface\n    //---------------------------------------------------------------------\n\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentHistogram(\n        TempStorage         &temp_storage,                                      ///< Reference to temp_storage\n        SampleIteratorT     d_samples,                                          ///< Input data to reduce\n        int                 (&num_output_bins)[NUM_ACTIVE_CHANNELS],            ///< The number bins per final output histogram\n        int                 (&num_privatized_bins)[NUM_ACTIVE_CHANNELS],        ///< The number bins per privatized histogram\n        CounterT*           (&d_output_histograms)[NUM_ACTIVE_CHANNELS],        ///< Reference to final output histograms\n        CounterT*           (&d_privatized_histograms)[NUM_ACTIVE_CHANNELS],    ///< Reference to privatized histograms\n        OutputDecodeOpT     (&output_decode_op)[NUM_ACTIVE_CHANNELS],           ///< The transform operator for determining output bin-ids from privatized counter indices, one for each channel\n        PrivatizedDecodeOpT (&privatized_decode_op)[NUM_ACTIVE_CHANNELS])       ///< The transform operator for determining privatized counter indices from samples, one for each channel\n    :\n        temp_storage(temp_storage.Alias()),\n        d_wrapped_samples(d_samples),\n        num_output_bins(num_output_bins),\n        num_privatized_bins(num_privatized_bins),\n        d_output_histograms(d_output_histograms),\n        privatized_decode_op(privatized_decode_op),\n        output_decode_op(output_decode_op),\n        d_native_samples(NativePointer(d_wrapped_samples)),\n        prefer_smem((MEM_PREFERENCE == SMEM) ?\n            true :                              // prefer smem privatized histograms\n            (MEM_PREFERENCE == GMEM) ?\n                false :                         // prefer gmem privatized histograms\n                blockIdx.x & 1)                 // prefer blended privatized histograms\n    {\n        int blockId = (blockIdx.y * gridDim.x) + blockIdx.x;\n\n        // Initialize the locations of this block's privatized histograms\n        for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n            this->d_privatized_histograms[CHANNEL] = d_privatized_histograms[CHANNEL] + (blockId * num_privatized_bins[CHANNEL]);\n    }\n\n\n    /**\n     * Consume image\n     */\n    __device__ __forceinline__ void ConsumeTiles(\n        OffsetT             num_row_pixels,             ///< The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                   ///< The number of rows in the region of interest\n        OffsetT             row_stride_samples,         ///< The number of samples between starts of consecutive rows in the region of interest\n        int                 tiles_per_row,              ///< Number of image tiles per row\n        GridQueue<int>      tile_queue)                 ///< Queue descriptor for assigning tiles of work to thread blocks\n    {\n        // Check whether all row starting offsets are quad-aligned (in single-channel) or pixel-aligned (in multi-channel)\n        int     quad_mask           = AlignBytes<QuadT>::ALIGN_BYTES - 1;\n        int     pixel_mask          = AlignBytes<PixelT>::ALIGN_BYTES - 1;\n        size_t  row_bytes           = sizeof(SampleT) * row_stride_samples;\n\n        bool quad_aligned_rows      = (NUM_CHANNELS == 1) && (SAMPLES_PER_THREAD % 4 == 0) &&     // Single channel\n                                        ((size_t(d_native_samples) & quad_mask) == 0) &&        // ptr is quad-aligned\n                                        ((num_rows == 1) || ((row_bytes & quad_mask) == 0));    // number of row-samples is a multiple of the alignment of the quad\n\n        bool pixel_aligned_rows     = (NUM_CHANNELS > 1) &&                                     // Multi channel\n                                        ((size_t(d_native_samples) & pixel_mask) == 0) &&       // ptr is pixel-aligned\n                                        ((row_bytes & pixel_mask) == 0);                        // number of row-samples is a multiple of the alignment of the pixel\n\n        // Whether rows are aligned and can be vectorized\n        if ((d_native_samples != NULL) && (quad_aligned_rows || pixel_aligned_rows))\n            ConsumeTiles<true>(num_row_pixels, num_rows, row_stride_samples, tiles_per_row, tile_queue, Int2Type<IS_WORK_STEALING>());\n        else\n            ConsumeTiles<false>(num_row_pixels, num_rows, row_stride_samples, tiles_per_row, tile_queue, Int2Type<IS_WORK_STEALING>());\n    }\n\n\n    /**\n     * Initialize privatized bin counters.  Specialized for privatized shared-memory counters\n     */\n    __device__ __forceinline__ void InitBinCounters()\n    {\n        if (prefer_smem)\n            InitSmemBinCounters();\n        else\n            InitGmemBinCounters();\n    }\n\n\n    /**\n     * Store privatized histogram to device-accessible memory.  Specialized for privatized shared-memory counters\n     */\n    __device__ __forceinline__ void StoreOutput()\n    {\n        if (prefer_smem)\n            StoreSmemOutput();\n        else\n            StoreGmemOutput();\n    }\n\n\n};\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_radix_sort_downsweep.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * AgentRadixSortDownsweep implements a stateful abstraction of CUDA thread blocks for participating in device-wide radix sort downsweep .\n */\n\n\n#pragma once\n\n#include <stdint.h>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_radix_rank.cuh\"\n#include \"../block/block_exchange.cuh\"\n#include \"../util_type.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Radix ranking algorithm\n */\nenum RadixRankAlgorithm\n{\n    RADIX_RANK_BASIC,\n    RADIX_RANK_MEMOIZE,\n    RADIX_RANK_MATCH\n};\n\n/**\n * Parameterizable tuning policy type for AgentRadixSortDownsweep\n */\ntemplate <\n    int                         _BLOCK_THREADS,         ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,      ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,        ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,         ///< Cache load modifier for reading keys (and values)\n    RadixRankAlgorithm          _RANK_ALGORITHM,        ///< The radix ranking algorithm to use\n    BlockScanAlgorithm          _SCAN_ALGORITHM,        ///< The block scan algorithm to use\n    int                         _RADIX_BITS>            ///< The number of radix bits, i.e., log2(bins)\nstruct AgentRadixSortDownsweepPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,           ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,        ///< Items per thread (per tile of input)\n        RADIX_BITS              = _RADIX_BITS,              ///< The number of radix bits, i.e., log2(bins)\n    };\n\n    static const BlockLoadAlgorithm  LOAD_ALGORITHM     = _LOAD_ALGORITHM;    ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier   LOAD_MODIFIER      = _LOAD_MODIFIER;     ///< Cache load modifier for reading keys (and values)\n    static const RadixRankAlgorithm  RANK_ALGORITHM     = _RANK_ALGORITHM;    ///< The radix ranking algorithm to use\n    static const BlockScanAlgorithm  SCAN_ALGORITHM     = _SCAN_ALGORITHM;    ///< The BlockScan algorithm to use\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n\n\n\n\n/**\n * \\brief AgentRadixSortDownsweep implements a stateful abstraction of CUDA thread blocks for participating in device-wide radix sort downsweep .\n */\ntemplate <\n    typename AgentRadixSortDownsweepPolicy,     ///< Parameterized AgentRadixSortDownsweepPolicy tuning policy type\n    bool     IS_DESCENDING,                     ///< Whether or not the sorted-order is high-to-low\n    typename KeyT,                              ///< KeyT type\n    typename ValueT,                            ///< ValueT type\n    typename OffsetT>                           ///< Signed integer type for global offsets\nstruct AgentRadixSortDownsweep\n{\n    //---------------------------------------------------------------------\n    // Type definitions and constants\n    //---------------------------------------------------------------------\n\n    // Appropriate unsigned-bits representation of KeyT\n    typedef typename Traits<KeyT>::UnsignedBits UnsignedBits;\n\n    static const UnsignedBits           LOWEST_KEY  = Traits<KeyT>::LOWEST_KEY;\n    static const UnsignedBits           MAX_KEY     = Traits<KeyT>::MAX_KEY;\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM  = AgentRadixSortDownsweepPolicy::LOAD_ALGORITHM;\n    static const CacheLoadModifier      LOAD_MODIFIER   = AgentRadixSortDownsweepPolicy::LOAD_MODIFIER;\n    static const RadixRankAlgorithm     RANK_ALGORITHM  = AgentRadixSortDownsweepPolicy::RANK_ALGORITHM;\n    static const BlockScanAlgorithm     SCAN_ALGORITHM  = AgentRadixSortDownsweepPolicy::SCAN_ALGORITHM;\n\n    enum\n    {\n        BLOCK_THREADS           = AgentRadixSortDownsweepPolicy::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = AgentRadixSortDownsweepPolicy::ITEMS_PER_THREAD,\n        RADIX_BITS              = AgentRadixSortDownsweepPolicy::RADIX_BITS,\n        TILE_ITEMS              = BLOCK_THREADS * ITEMS_PER_THREAD,\n\n        RADIX_DIGITS            = 1 << RADIX_BITS,\n        KEYS_ONLY               = Equals<ValueT, NullType>::VALUE,\n    };\n\n    // Input iterator wrapper type (for applying cache modifier)s\n    typedef CacheModifiedInputIterator<LOAD_MODIFIER, UnsignedBits, OffsetT>    KeysItr;\n    typedef CacheModifiedInputIterator<LOAD_MODIFIER, ValueT, OffsetT>          ValuesItr;\n\n    // Radix ranking type to use\n    typedef typename If<(RANK_ALGORITHM == RADIX_RANK_BASIC),\n            BlockRadixRank<BLOCK_THREADS, RADIX_BITS, IS_DESCENDING, false, SCAN_ALGORITHM>,\n            typename If<(RANK_ALGORITHM == RADIX_RANK_MEMOIZE),\n                BlockRadixRank<BLOCK_THREADS, RADIX_BITS, IS_DESCENDING, true, SCAN_ALGORITHM>,\n                BlockRadixRankMatch<BLOCK_THREADS, RADIX_BITS, IS_DESCENDING, SCAN_ALGORITHM>\n            >::Type\n        >::Type BlockRadixRankT;\n\n    enum\n    {\n        /// Number of bin-starting offsets tracked per thread\n        BINS_TRACKED_PER_THREAD = BlockRadixRankT::BINS_TRACKED_PER_THREAD\n    };\n\n    // BlockLoad type (keys)\n    typedef BlockLoad<\n        UnsignedBits,\n        BLOCK_THREADS,\n        ITEMS_PER_THREAD,\n        LOAD_ALGORITHM> BlockLoadKeysT;\n\n    // BlockLoad type (values)\n    typedef BlockLoad<\n        ValueT,\n        BLOCK_THREADS,\n        ITEMS_PER_THREAD,\n        LOAD_ALGORITHM> BlockLoadValuesT;\n\n    // Value exchange array type\n    typedef ValueT ValueExchangeT[TILE_ITEMS];\n\n    /**\n     * Shared memory storage layout\n     */\n    union __align__(16) _TempStorage\n    {\n        typename BlockLoadKeysT::TempStorage    load_keys;\n        typename BlockLoadValuesT::TempStorage  load_values;\n        typename BlockRadixRankT::TempStorage   radix_rank;\n\n        struct\n        {\n            UnsignedBits                        exchange_keys[TILE_ITEMS];\n            OffsetT                             relative_bin_offsets[RADIX_DIGITS];\n        };\n\n        Uninitialized<ValueExchangeT>           exchange_values;\n\n        OffsetT                                 exclusive_digit_prefix[RADIX_DIGITS];\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    // Shared storage for this CTA\n    _TempStorage    &temp_storage;\n\n    // Input and output device pointers\n    KeysItr         d_keys_in;\n    ValuesItr       d_values_in;\n    UnsignedBits    *d_keys_out;\n    ValueT          *d_values_out;\n\n    // The global scatter base offset for each digit (valid in the first RADIX_DIGITS threads)\n    OffsetT         bin_offset[BINS_TRACKED_PER_THREAD];\n\n    // The least-significant bit position of the current digit to extract\n    int             current_bit;\n\n    // Number of bits in current digit\n    int             num_bits;\n\n    // Whether to short-cirucit\n    int             short_circuit;\n\n    //---------------------------------------------------------------------\n    // Utility methods\n    //---------------------------------------------------------------------\n\n\n    /**\n     * Scatter ranked keys through shared memory, then to device-accessible memory\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void ScatterKeys(\n        UnsignedBits    (&twiddled_keys)[ITEMS_PER_THREAD],\n        OffsetT         (&relative_bin_offsets)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        OffsetT         valid_items)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            temp_storage.exchange_keys[ranks[ITEM]] = twiddled_keys[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            UnsignedBits key            = temp_storage.exchange_keys[threadIdx.x + (ITEM * BLOCK_THREADS)];\n            UnsignedBits digit          = BFE(key, current_bit, num_bits);\n            relative_bin_offsets[ITEM]  = temp_storage.relative_bin_offsets[digit];\n\n            // Un-twiddle\n            key = Traits<KeyT>::TwiddleOut(key);\n\n            if (FULL_TILE || \n                (static_cast<OffsetT>(threadIdx.x + (ITEM * BLOCK_THREADS)) < valid_items))\n            {\n                d_keys_out[relative_bin_offsets[ITEM] + threadIdx.x + (ITEM * BLOCK_THREADS)] = key;\n            }\n        }\n    }\n\n\n    /**\n     * Scatter ranked values through shared memory, then to device-accessible memory\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void ScatterValues(\n        ValueT      (&values)[ITEMS_PER_THREAD],\n        OffsetT     (&relative_bin_offsets)[ITEMS_PER_THREAD],\n        int         (&ranks)[ITEMS_PER_THREAD],\n        OffsetT     valid_items)\n    {\n        CTA_SYNC();\n\n        ValueExchangeT &exchange_values = temp_storage.exchange_values.Alias();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            exchange_values[ranks[ITEM]] = values[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            ValueT value = exchange_values[threadIdx.x + (ITEM * BLOCK_THREADS)];\n\n            if (FULL_TILE || \n                (static_cast<OffsetT>(threadIdx.x + (ITEM * BLOCK_THREADS)) < valid_items))\n            {\n                d_values_out[relative_bin_offsets[ITEM] + threadIdx.x + (ITEM * BLOCK_THREADS)] = value;\n            }\n        }\n    }\n\n    /**\n     * Load a tile of keys (specialized for full tile, any ranking algorithm)\n     */\n    template <int _RANK_ALGORITHM>\n    __device__ __forceinline__ void LoadKeys(\n        UnsignedBits                (&keys)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        UnsignedBits                oob_item,\n        Int2Type<true>              is_full_tile,\n        Int2Type<_RANK_ALGORITHM>   rank_algorithm)\n    {\n        BlockLoadKeysT(temp_storage.load_keys).Load(\n            d_keys_in + block_offset, keys);\n\n        CTA_SYNC();\n    }\n\n\n    /**\n     * Load a tile of keys (specialized for partial tile, any ranking algorithm)\n     */\n    template <int _RANK_ALGORITHM>\n    __device__ __forceinline__ void LoadKeys(\n        UnsignedBits                (&keys)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        UnsignedBits                oob_item,\n        Int2Type<false>             is_full_tile,\n        Int2Type<_RANK_ALGORITHM>   rank_algorithm)\n    {\n        BlockLoadKeysT(temp_storage.load_keys).Load(\n            d_keys_in + block_offset, keys, valid_items, oob_item);\n\n        CTA_SYNC();\n    }\n\n\n    /**\n     * Load a tile of keys (specialized for full tile, match ranking algorithm)\n     */\n    __device__ __forceinline__ void LoadKeys(\n        UnsignedBits                (&keys)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        UnsignedBits                oob_item,\n        Int2Type<true>              is_full_tile,\n        Int2Type<RADIX_RANK_MATCH>  rank_algorithm)\n    {\n        LoadDirectWarpStriped(threadIdx.x, d_keys_in + block_offset, keys);\n    }\n\n\n    /**\n     * Load a tile of keys (specialized for partial tile, match ranking algorithm)\n     */\n    __device__ __forceinline__ void LoadKeys(\n        UnsignedBits                (&keys)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        UnsignedBits                oob_item,\n        Int2Type<false>             is_full_tile,\n        Int2Type<RADIX_RANK_MATCH>  rank_algorithm)\n    {\n        LoadDirectWarpStriped(threadIdx.x, d_keys_in + block_offset, keys, valid_items, oob_item);\n    }\n\n\n    /**\n     * Load a tile of values (specialized for full tile, any ranking algorithm)\n     */\n    template <int _RANK_ALGORITHM>\n    __device__ __forceinline__ void LoadValues(\n        ValueT                      (&values)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        Int2Type<true>              is_full_tile,\n        Int2Type<_RANK_ALGORITHM>   rank_algorithm)\n    {\n        BlockLoadValuesT(temp_storage.load_values).Load(\n            d_values_in + block_offset, values);\n\n        CTA_SYNC();\n    }\n\n\n    /**\n     * Load a tile of values (specialized for partial tile, any ranking algorithm)\n     */\n    template <int _RANK_ALGORITHM>\n    __device__ __forceinline__ void LoadValues(\n        ValueT                      (&values)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        OffsetT                     valid_items,\n        Int2Type<false>             is_full_tile,\n        Int2Type<_RANK_ALGORITHM>   rank_algorithm)\n    {\n        BlockLoadValuesT(temp_storage.load_values).Load(\n            d_values_in + block_offset, values, valid_items);\n\n        CTA_SYNC();\n    }\n\n\n    /**\n     * Load a tile of items (specialized for full tile, match ranking algorithm)\n     */\n    __device__ __forceinline__ void LoadValues(\n        ValueT                      (&values)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        volatile OffsetT                     valid_items,\n        Int2Type<true>              is_full_tile,\n        Int2Type<RADIX_RANK_MATCH>  rank_algorithm)\n    {\n        LoadDirectWarpStriped(threadIdx.x, d_values_in + block_offset, values);\n    }\n\n\n    /**\n     * Load a tile of items (specialized for partial tile, match ranking algorithm)\n     */\n    __device__ __forceinline__ void LoadValues(\n        ValueT                      (&values)[ITEMS_PER_THREAD],\n        OffsetT                     block_offset,\n        volatile OffsetT                     valid_items,\n        Int2Type<false>             is_full_tile,\n        Int2Type<RADIX_RANK_MATCH>  rank_algorithm)\n    {\n        LoadDirectWarpStriped(threadIdx.x, d_values_in + block_offset, values, valid_items);\n    }\n\n\n    /**\n     * Truck along associated values\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void GatherScatterValues(\n        OffsetT         (&relative_bin_offsets)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        OffsetT         block_offset,\n        OffsetT         valid_items,\n        Int2Type<false> /*is_keys_only*/)\n    {\n        CTA_SYNC();\n\n        ValueT values[ITEMS_PER_THREAD];\n\n        LoadValues(\n            values,\n            block_offset,\n            valid_items,\n            Int2Type<FULL_TILE>(),\n            Int2Type<RANK_ALGORITHM>());\n\n        ScatterValues<FULL_TILE>(\n            values,\n            relative_bin_offsets,\n            ranks,\n            valid_items);\n    }\n\n\n    /**\n     * Truck along associated values (specialized for key-only sorting)\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void GatherScatterValues(\n        OffsetT         (&/*relative_bin_offsets*/)[ITEMS_PER_THREAD],\n        int             (&/*ranks*/)[ITEMS_PER_THREAD],\n        OffsetT         /*block_offset*/,\n        OffsetT         /*valid_items*/,\n        Int2Type<true>  /*is_keys_only*/)\n    {}\n\n\n    /**\n     * Process tile\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void ProcessTile(\n        OffsetT block_offset,\n        const OffsetT &valid_items = TILE_ITEMS)\n    {\n        UnsignedBits    keys[ITEMS_PER_THREAD];\n        int             ranks[ITEMS_PER_THREAD];\n        OffsetT         relative_bin_offsets[ITEMS_PER_THREAD];\n\n        // Assign default (min/max) value to all keys\n        UnsignedBits default_key = (IS_DESCENDING) ? LOWEST_KEY : MAX_KEY;\n\n        // Load tile of keys\n        LoadKeys(\n            keys,\n            block_offset,\n            valid_items, \n            default_key,\n            Int2Type<FULL_TILE>(),\n            Int2Type<RANK_ALGORITHM>());\n\n        // Twiddle key bits if necessary\n        #pragma unroll\n        for (int KEY = 0; KEY < ITEMS_PER_THREAD; KEY++)\n        {\n            keys[KEY] = Traits<KeyT>::TwiddleIn(keys[KEY]);\n        }\n\n        // Rank the twiddled keys\n        int exclusive_digit_prefix[BINS_TRACKED_PER_THREAD];\n        BlockRadixRankT(temp_storage.radix_rank).RankKeys(\n            keys,\n            ranks,\n            current_bit,\n            num_bits,\n            exclusive_digit_prefix);\n\n        CTA_SYNC();\n\n        // Share exclusive digit prefix\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                // Store exclusive prefix\n                temp_storage.exclusive_digit_prefix[bin_idx] =\n                    exclusive_digit_prefix[track];\n            }\n        }\n\n        CTA_SYNC();\n\n        // Get inclusive digit prefix\n        int inclusive_digit_prefix[BINS_TRACKED_PER_THREAD];\n\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                if (IS_DESCENDING)\n                {\n                    // Get inclusive digit prefix from exclusive prefix (higher bins come first)\n                    inclusive_digit_prefix[track] = (bin_idx == 0) ?\n                        (BLOCK_THREADS * ITEMS_PER_THREAD) :\n                        temp_storage.exclusive_digit_prefix[bin_idx - 1];\n                }\n                else\n                {\n                    // Get inclusive digit prefix from exclusive prefix (lower bins come first)\n                    inclusive_digit_prefix[track] = (bin_idx == RADIX_DIGITS - 1) ?\n                        (BLOCK_THREADS * ITEMS_PER_THREAD) :\n                        temp_storage.exclusive_digit_prefix[bin_idx + 1];\n                }\n            }\n        }\n\n        CTA_SYNC();\n\n        // Update global scatter base offsets for each digit\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                bin_offset[track] -= exclusive_digit_prefix[track];\n                temp_storage.relative_bin_offsets[bin_idx] = bin_offset[track];\n                bin_offset[track] += inclusive_digit_prefix[track];\n            }\n        }\n\n        CTA_SYNC();\n\n        // Scatter keys\n        ScatterKeys<FULL_TILE>(keys, relative_bin_offsets, ranks, valid_items);\n\n        // Gather/scatter values\n        GatherScatterValues<FULL_TILE>(relative_bin_offsets , ranks, block_offset, valid_items, Int2Type<KEYS_ONLY>());\n    }\n\n    //---------------------------------------------------------------------\n    // Copy shortcut\n    //---------------------------------------------------------------------\n\n    /**\n     * Copy tiles within the range of input\n     */\n    template <\n        typename InputIteratorT,\n        typename T>\n    __device__ __forceinline__ void Copy(\n        InputIteratorT  d_in,\n        T               *d_out,\n        OffsetT         block_offset,\n        OffsetT         block_end)\n    {\n        // Simply copy the input\n        while (block_offset + TILE_ITEMS <= block_end)\n        {\n            T items[ITEMS_PER_THREAD];\n\n            LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_in + block_offset, items);\n            CTA_SYNC();\n            StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_out + block_offset, items);\n\n            block_offset += TILE_ITEMS;\n        }\n\n        // Clean up last partial tile with guarded-I/O\n        if (block_offset < block_end)\n        {\n            OffsetT valid_items = block_end - block_offset;\n\n            T items[ITEMS_PER_THREAD];\n\n            LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_in + block_offset, items, valid_items);\n            CTA_SYNC();\n            StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_out + block_offset, items, valid_items);\n        }\n    }\n\n\n    /**\n     * Copy tiles within the range of input (specialized for NullType)\n     */\n    template <typename InputIteratorT>\n    __device__ __forceinline__ void Copy(\n        InputIteratorT  /*d_in*/,\n        NullType        * /*d_out*/,\n        OffsetT         /*block_offset*/,\n        OffsetT         /*block_end*/)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Interface\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentRadixSortDownsweep(\n        TempStorage     &temp_storage,\n        OffsetT         (&bin_offset)[BINS_TRACKED_PER_THREAD],\n        OffsetT         num_items,\n        const KeyT      *d_keys_in,\n        KeyT            *d_keys_out,\n        const ValueT    *d_values_in,\n        ValueT          *d_values_out,\n        int             current_bit,\n        int             num_bits)\n    :\n        temp_storage(temp_storage.Alias()),\n        d_keys_in(reinterpret_cast<const UnsignedBits*>(d_keys_in)),\n        d_values_in(d_values_in),\n        d_keys_out(reinterpret_cast<UnsignedBits*>(d_keys_out)),\n        d_values_out(d_values_out),\n        current_bit(current_bit),\n        num_bits(num_bits),\n        short_circuit(1)\n    {\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            this->bin_offset[track] = bin_offset[track];\n\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                // Short circuit if the histogram has only bin counts of only zeros or problem-size\n                short_circuit = short_circuit && ((bin_offset[track] == 0) || (bin_offset[track] == num_items));\n            }\n        }\n\n        short_circuit = CTA_SYNC_AND(short_circuit);\n    }\n\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentRadixSortDownsweep(\n        TempStorage     &temp_storage,\n        OffsetT         num_items,\n        OffsetT         *d_spine,\n        const KeyT      *d_keys_in,\n        KeyT            *d_keys_out,\n        const ValueT    *d_values_in,\n        ValueT          *d_values_out,\n        int             current_bit,\n        int             num_bits)\n    :\n        temp_storage(temp_storage.Alias()),\n        d_keys_in(reinterpret_cast<const UnsignedBits*>(d_keys_in)),\n        d_values_in(d_values_in),\n        d_keys_out(reinterpret_cast<UnsignedBits*>(d_keys_out)),\n        d_values_out(d_values_out),\n        current_bit(current_bit),\n        num_bits(num_bits),\n        short_circuit(1)\n    {\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            // Load digit bin offsets (each of the first RADIX_DIGITS threads will load an offset for that digit)\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                if (IS_DESCENDING)\n                    bin_idx = RADIX_DIGITS - bin_idx - 1;\n\n                // Short circuit if the first block's histogram has only bin counts of only zeros or problem-size\n                OffsetT first_block_bin_offset = d_spine[gridDim.x * bin_idx];\n                short_circuit = short_circuit && ((first_block_bin_offset == 0) || (first_block_bin_offset == num_items));\n\n                // Load my block's bin offset for my bin\n                bin_offset[track] = d_spine[(gridDim.x * bin_idx) + blockIdx.x];\n            }\n        }\n\n        short_circuit = CTA_SYNC_AND(short_circuit);\n    }\n\n\n    /**\n     * Distribute keys from a segment of input tiles.\n     */\n    __device__ __forceinline__ void ProcessRegion(\n        OffsetT   block_offset,\n        OffsetT   block_end)\n    {\n        if (short_circuit)\n        {\n            // Copy keys\n            Copy(d_keys_in, d_keys_out, block_offset, block_end);\n\n            // Copy values\n            Copy(d_values_in, d_values_out, block_offset, block_end);\n        }\n        else\n        {\n            // Process full tiles of tile_items\n            while (block_offset + TILE_ITEMS <= block_end)\n            {\n                ProcessTile<true>(block_offset);\n                block_offset += TILE_ITEMS;\n\n                CTA_SYNC();\n            }\n\n            // Clean up last partial tile with guarded-I/O\n            if (block_offset < block_end)\n            {\n                ProcessTile<false>(block_offset, block_end - block_offset);\n            }\n\n        }\n    }\n\n};\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_radix_sort_upsweep.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * AgentRadixSortUpsweep implements a stateful abstraction of CUDA thread blocks for participating in device-wide radix sort upsweep .\n */\n\n#pragma once\n\n#include \"../thread/thread_reduce.cuh\"\n#include \"../thread/thread_load.cuh\"\n#include \"../warp/warp_reduce.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../util_type.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentRadixSortUpsweep\n */\ntemplate <\n    int                 _BLOCK_THREADS,     ///< Threads per thread block\n    int                 _ITEMS_PER_THREAD,  ///< Items per thread (per tile of input)\n    CacheLoadModifier   _LOAD_MODIFIER,     ///< Cache load modifier for reading keys\n    int                 _RADIX_BITS>        ///< The number of radix bits, i.e., log2(bins)\nstruct AgentRadixSortUpsweepPolicy\n{\n    enum\n    {\n        BLOCK_THREADS       = _BLOCK_THREADS,       ///< Threads per thread block\n        ITEMS_PER_THREAD    = _ITEMS_PER_THREAD,    ///< Items per thread (per tile of input)\n        RADIX_BITS          = _RADIX_BITS,          ///< The number of radix bits, i.e., log2(bins)\n    };\n\n    static const CacheLoadModifier LOAD_MODIFIER = _LOAD_MODIFIER;      ///< Cache load modifier for reading keys\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentRadixSortUpsweep implements a stateful abstraction of CUDA thread blocks for participating in device-wide radix sort upsweep .\n */\ntemplate <\n    typename AgentRadixSortUpsweepPolicy,   ///< Parameterized AgentRadixSortUpsweepPolicy tuning policy type\n    typename KeyT,                          ///< KeyT type\n    typename OffsetT>                       ///< Signed integer type for global offsets\nstruct AgentRadixSortUpsweep\n{\n\n    //---------------------------------------------------------------------\n    // Type definitions and constants\n    //---------------------------------------------------------------------\n\n    typedef typename Traits<KeyT>::UnsignedBits UnsignedBits;\n\n    // Integer type for digit counters (to be packed into words of PackedCounters)\n    typedef unsigned char DigitCounter;\n\n    // Integer type for packing DigitCounters into columns of shared memory banks\n    typedef unsigned int PackedCounter;\n\n    static const CacheLoadModifier LOAD_MODIFIER = AgentRadixSortUpsweepPolicy::LOAD_MODIFIER;\n\n    enum\n    {\n        RADIX_BITS              = AgentRadixSortUpsweepPolicy::RADIX_BITS,\n        BLOCK_THREADS           = AgentRadixSortUpsweepPolicy::BLOCK_THREADS,\n        KEYS_PER_THREAD         = AgentRadixSortUpsweepPolicy::ITEMS_PER_THREAD,\n\n        RADIX_DIGITS            = 1 << RADIX_BITS,\n\n        LOG_WARP_THREADS        = CUB_PTX_LOG_WARP_THREADS,\n        WARP_THREADS            = 1 << LOG_WARP_THREADS,\n        WARPS                   = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        TILE_ITEMS              = BLOCK_THREADS * KEYS_PER_THREAD,\n\n        BYTES_PER_COUNTER       = sizeof(DigitCounter),\n        LOG_BYTES_PER_COUNTER   = Log2<BYTES_PER_COUNTER>::VALUE,\n\n        PACKING_RATIO           = sizeof(PackedCounter) / sizeof(DigitCounter),\n        LOG_PACKING_RATIO       = Log2<PACKING_RATIO>::VALUE,\n\n        LOG_COUNTER_LANES       = CUB_MAX(0, RADIX_BITS - LOG_PACKING_RATIO),\n        COUNTER_LANES           = 1 << LOG_COUNTER_LANES,\n\n        // To prevent counter overflow, we must periodically unpack and aggregate the\n        // digit counters back into registers.  Each counter lane is assigned to a\n        // warp for aggregation.\n\n        LANES_PER_WARP          = CUB_MAX(1, (COUNTER_LANES + WARPS - 1) / WARPS),\n\n        // Unroll tiles in batches without risk of counter overflow\n        UNROLL_COUNT            = CUB_MIN(64, 255 / KEYS_PER_THREAD),\n        UNROLLED_ELEMENTS       = UNROLL_COUNT * TILE_ITEMS,\n    };\n\n\n    // Input iterator wrapper type (for applying cache modifier)s\n    typedef CacheModifiedInputIterator<LOAD_MODIFIER, UnsignedBits, OffsetT> KeysItr;\n\n    /**\n     * Shared memory storage layout\n     */\n    union __align__(16) _TempStorage\n    {\n        DigitCounter    thread_counters[COUNTER_LANES][BLOCK_THREADS][PACKING_RATIO];\n        PackedCounter   packed_thread_counters[COUNTER_LANES][BLOCK_THREADS];\n        OffsetT         block_counters[WARP_THREADS][RADIX_DIGITS];\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Thread fields (aggregate state bundle)\n    //---------------------------------------------------------------------\n\n    // Shared storage for this CTA\n    _TempStorage    &temp_storage;\n\n    // Thread-local counters for periodically aggregating composite-counter lanes\n    OffsetT         local_counts[LANES_PER_WARP][PACKING_RATIO];\n\n    // Input and output device pointers\n    KeysItr         d_keys_in;\n\n    // The least-significant bit position of the current digit to extract\n    int             current_bit;\n\n    // Number of bits in current digit\n    int             num_bits;\n\n\n\n    //---------------------------------------------------------------------\n    // Helper structure for templated iteration\n    //---------------------------------------------------------------------\n\n    // Iterate\n    template <int COUNT, int MAX>\n    struct Iterate\n    {\n        // BucketKeys\n        static __device__ __forceinline__ void BucketKeys(\n            AgentRadixSortUpsweep       &cta,\n            UnsignedBits                keys[KEYS_PER_THREAD])\n        {\n            cta.Bucket(keys[COUNT]);\n\n            // Next\n            Iterate<COUNT + 1, MAX>::BucketKeys(cta, keys);\n        }\n    };\n\n    // Terminate\n    template <int MAX>\n    struct Iterate<MAX, MAX>\n    {\n        // BucketKeys\n        static __device__ __forceinline__ void BucketKeys(AgentRadixSortUpsweep &/*cta*/, UnsignedBits /*keys*/[KEYS_PER_THREAD]) {}\n    };\n\n\n    //---------------------------------------------------------------------\n    // Utility methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Decode a key and increment corresponding smem digit counter\n     */\n    __device__ __forceinline__ void Bucket(UnsignedBits key)\n    {\n        // Perform transform op\n        UnsignedBits converted_key = Traits<KeyT>::TwiddleIn(key);\n\n        // Extract current digit bits\n        UnsignedBits digit = BFE(converted_key, current_bit, num_bits);\n\n        // Get sub-counter offset\n        UnsignedBits sub_counter = digit & (PACKING_RATIO - 1);\n\n        // Get row offset\n        UnsignedBits row_offset = digit >> LOG_PACKING_RATIO;\n\n        // Increment counter\n        temp_storage.thread_counters[row_offset][threadIdx.x][sub_counter]++;\n    }\n\n\n    /**\n     * Reset composite counters\n     */\n    __device__ __forceinline__ void ResetDigitCounters()\n    {\n        #pragma unroll\n        for (int LANE = 0; LANE < COUNTER_LANES; LANE++)\n        {\n            temp_storage.packed_thread_counters[LANE][threadIdx.x] = 0;\n        }\n    }\n\n\n    /**\n     * Reset the unpacked counters in each thread\n     */\n    __device__ __forceinline__ void ResetUnpackedCounters()\n    {\n        #pragma unroll\n        for (int LANE = 0; LANE < LANES_PER_WARP; LANE++)\n        {\n            #pragma unroll\n            for (int UNPACKED_COUNTER = 0; UNPACKED_COUNTER < PACKING_RATIO; UNPACKED_COUNTER++)\n            {\n                local_counts[LANE][UNPACKED_COUNTER] = 0;\n            }\n        }\n    }\n\n\n    /**\n     * Extracts and aggregates the digit counters for each counter lane\n     * owned by this warp\n     */\n    __device__ __forceinline__ void UnpackDigitCounts()\n    {\n        unsigned int warp_id = threadIdx.x >> LOG_WARP_THREADS;\n        unsigned int warp_tid = LaneId();\n\n        #pragma unroll\n        for (int LANE = 0; LANE < LANES_PER_WARP; LANE++)\n        {\n            const int counter_lane = (LANE * WARPS) + warp_id;\n            if (counter_lane < COUNTER_LANES)\n            {\n                #pragma unroll\n                for (int PACKED_COUNTER = 0; PACKED_COUNTER < BLOCK_THREADS; PACKED_COUNTER += WARP_THREADS)\n                {\n                    #pragma unroll\n                    for (int UNPACKED_COUNTER = 0; UNPACKED_COUNTER < PACKING_RATIO; UNPACKED_COUNTER++)\n                    {\n                        OffsetT counter = temp_storage.thread_counters[counter_lane][warp_tid + PACKED_COUNTER][UNPACKED_COUNTER];\n                        local_counts[LANE][UNPACKED_COUNTER] += counter;\n                    }\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Processes a single, full tile\n     */\n    __device__ __forceinline__ void ProcessFullTile(OffsetT block_offset)\n    {\n        // Tile of keys\n        UnsignedBits keys[KEYS_PER_THREAD];\n\n        LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_keys_in + block_offset, keys);\n\n        // Prevent hoisting\n        CTA_SYNC();\n\n        // Bucket tile of keys\n        Iterate<0, KEYS_PER_THREAD>::BucketKeys(*this, keys);\n    }\n\n\n    /**\n     * Processes a single load (may have some threads masked off)\n     */\n    __device__ __forceinline__ void ProcessPartialTile(\n        OffsetT block_offset,\n        const OffsetT &block_end)\n    {\n        // Process partial tile if necessary using single loads\n        block_offset += threadIdx.x;\n        while (block_offset < block_end)\n        {\n            // Load and bucket key\n            UnsignedBits key = d_keys_in[block_offset];\n            Bucket(key);\n            block_offset += BLOCK_THREADS;\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Interface\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentRadixSortUpsweep(\n        TempStorage &temp_storage,\n        const KeyT  *d_keys_in,\n        int         current_bit,\n        int         num_bits)\n    :\n        temp_storage(temp_storage.Alias()),\n        d_keys_in(reinterpret_cast<const UnsignedBits*>(d_keys_in)),\n        current_bit(current_bit),\n        num_bits(num_bits)\n    {}\n\n\n    /**\n     * Compute radix digit histograms from a segment of input tiles.\n     */\n    __device__ __forceinline__ void ProcessRegion(\n        OffsetT          block_offset,\n        const OffsetT    &block_end)\n    {\n        // Reset digit counters in smem and unpacked counters in registers\n        ResetDigitCounters();\n        ResetUnpackedCounters();\n\n        // Unroll batches of full tiles\n        while (block_offset + UNROLLED_ELEMENTS <= block_end)\n        {\n            for (int i = 0; i < UNROLL_COUNT; ++i)\n            {\n                ProcessFullTile(block_offset);\n                block_offset += TILE_ITEMS;\n            }\n\n            CTA_SYNC();\n\n            // Aggregate back into local_count registers to prevent overflow\n            UnpackDigitCounts();\n\n            CTA_SYNC();\n\n            // Reset composite counters in lanes\n            ResetDigitCounters();\n        }\n\n        // Unroll single full tiles\n        while (block_offset + TILE_ITEMS <= block_end)\n        {\n            ProcessFullTile(block_offset);\n            block_offset += TILE_ITEMS;\n        }\n\n        // Process partial tile if necessary\n        ProcessPartialTile(\n            block_offset,\n            block_end);\n\n        CTA_SYNC();\n\n        // Aggregate back into local_count registers\n        UnpackDigitCounts();\n    }\n\n\n    /**\n     * Extract counts (saving them to the external array)\n     */\n    template <bool IS_DESCENDING>\n    __device__ __forceinline__ void ExtractCounts(\n        OffsetT     *counters,\n        int         bin_stride = 1,\n        int         bin_offset = 0)\n    {\n        unsigned int warp_id    = threadIdx.x >> LOG_WARP_THREADS;\n        unsigned int warp_tid   = LaneId();\n\n        // Place unpacked digit counters in shared memory\n        #pragma unroll\n        for (int LANE = 0; LANE < LANES_PER_WARP; LANE++)\n        {\n            int counter_lane = (LANE * WARPS) + warp_id;\n            if (counter_lane < COUNTER_LANES)\n            {\n                int digit_row = counter_lane << LOG_PACKING_RATIO;\n\n                #pragma unroll\n                for (int UNPACKED_COUNTER = 0; UNPACKED_COUNTER < PACKING_RATIO; UNPACKED_COUNTER++)\n                {\n                    int bin_idx = digit_row + UNPACKED_COUNTER;\n\n                    temp_storage.block_counters[warp_tid][bin_idx] =\n                        local_counts[LANE][UNPACKED_COUNTER];\n                }\n            }\n        }\n\n        CTA_SYNC();\n\n        // Rake-reduce bin_count reductions\n\n        // Whole blocks\n        #pragma unroll\n        for (int BIN_BASE   = RADIX_DIGITS % BLOCK_THREADS;\n            (BIN_BASE + BLOCK_THREADS) <= RADIX_DIGITS;\n            BIN_BASE += BLOCK_THREADS)\n        {\n            int bin_idx = BIN_BASE + threadIdx.x;\n\n            OffsetT bin_count = 0;\n            #pragma unroll\n            for (int i = 0; i < WARP_THREADS; ++i)\n                bin_count += temp_storage.block_counters[i][bin_idx];\n\n            if (IS_DESCENDING)\n                bin_idx = RADIX_DIGITS - bin_idx - 1;\n\n            counters[(bin_stride * bin_idx) + bin_offset] = bin_count;\n        }\n\n        // Remainder\n        if ((RADIX_DIGITS % BLOCK_THREADS != 0) && (threadIdx.x < RADIX_DIGITS))\n        {\n            int bin_idx = threadIdx.x;\n\n            OffsetT bin_count = 0;\n            #pragma unroll\n            for (int i = 0; i < WARP_THREADS; ++i)\n                bin_count += temp_storage.block_counters[i][bin_idx];\n\n            if (IS_DESCENDING)\n                bin_idx = RADIX_DIGITS - bin_idx - 1;\n\n            counters[(bin_stride * bin_idx) + bin_offset] = bin_count;\n        }\n    }\n\n\n    /**\n     * Extract counts\n     */\n    template <int BINS_TRACKED_PER_THREAD>\n    __device__ __forceinline__ void ExtractCounts(\n        OffsetT (&bin_count)[BINS_TRACKED_PER_THREAD])  ///< [out] The exclusive prefix sum for the digits [(threadIdx.x * BINS_TRACKED_PER_THREAD) ... (threadIdx.x * BINS_TRACKED_PER_THREAD) + BINS_TRACKED_PER_THREAD - 1]\n    {\n        unsigned int warp_id    = threadIdx.x >> LOG_WARP_THREADS;\n        unsigned int warp_tid   = LaneId();\n\n        // Place unpacked digit counters in shared memory\n        #pragma unroll\n        for (int LANE = 0; LANE < LANES_PER_WARP; LANE++)\n        {\n            int counter_lane = (LANE * WARPS) + warp_id;\n            if (counter_lane < COUNTER_LANES)\n            {\n                int digit_row = counter_lane << LOG_PACKING_RATIO;\n\n                #pragma unroll\n                for (int UNPACKED_COUNTER = 0; UNPACKED_COUNTER < PACKING_RATIO; UNPACKED_COUNTER++)\n                {\n                    int bin_idx = digit_row + UNPACKED_COUNTER;\n\n                    temp_storage.block_counters[warp_tid][bin_idx] =\n                        local_counts[LANE][UNPACKED_COUNTER];\n                }\n            }\n        }\n\n        CTA_SYNC();\n\n        // Rake-reduce bin_count reductions\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                bin_count[track] = 0;\n\n                #pragma unroll\n                for (int i = 0; i < WARP_THREADS; ++i)\n                    bin_count[track] += temp_storage.block_counters[i][bin_idx];\n            }\n        }\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_reduce.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentReduce implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduction .\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"../block/block_load.cuh\"\n#include \"../block/block_reduce.cuh\"\n#include \"../grid/grid_mapping.cuh\"\n#include \"../grid/grid_even_share.cuh\"\n#include \"../util_type.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentReduce\n */\ntemplate <\n    int                     _BLOCK_THREADS,         ///< Threads per thread block\n    int                     _ITEMS_PER_THREAD,      ///< Items per thread (per tile of input)\n    int                     _VECTOR_LOAD_LENGTH,    ///< Number of items per vectorized load\n    BlockReduceAlgorithm    _BLOCK_ALGORITHM,       ///< Cooperative block-wide reduction algorithm to use\n    CacheLoadModifier       _LOAD_MODIFIER>         ///< Cache load modifier for reading input elements\nstruct AgentReducePolicy\n{\n    enum\n    {\n        BLOCK_THREADS       = _BLOCK_THREADS,       ///< Threads per thread block\n        ITEMS_PER_THREAD    = _ITEMS_PER_THREAD,    ///< Items per thread (per tile of input)\n        VECTOR_LOAD_LENGTH  = _VECTOR_LOAD_LENGTH,  ///< Number of items per vectorized load\n    };\n\n    static const BlockReduceAlgorithm  BLOCK_ALGORITHM      = _BLOCK_ALGORITHM;     ///< Cooperative block-wide reduction algorithm to use\n    static const CacheLoadModifier     LOAD_MODIFIER        = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n};\n\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentReduce implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduction .\n *\n * Each thread reduces only the values it loads. If \\p FIRST_TILE, this\n * partial reduction is stored into \\p thread_aggregate.  Otherwise it is\n * accumulated into \\p thread_aggregate.\n */\ntemplate <\n    typename AgentReducePolicy,        ///< Parameterized AgentReducePolicy tuning policy type\n    typename InputIteratorT,           ///< Random-access iterator type for input\n    typename OutputIteratorT,          ///< Random-access iterator type for output\n    typename OffsetT,                  ///< Signed integer type for global offsets\n    typename ReductionOp>              ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\nstruct AgentReduce\n{\n\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    /// The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    /// Vector type of InputT for data movement\n    typedef typename CubVector<InputT, AgentReducePolicy::VECTOR_LOAD_LENGTH>::Type VectorT;\n\n    /// Input iterator wrapper type (for applying cache modifier)\n    typedef typename If<IsPointer<InputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentReducePolicy::LOAD_MODIFIER, InputT, OffsetT>,      // Wrap the native input pointer with CacheModifiedInputIterator\n            InputIteratorT>::Type                                                               // Directly use the supplied input iterator type\n        WrappedInputIteratorT;\n\n    /// Constants\n    enum\n    {\n        BLOCK_THREADS       = AgentReducePolicy::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = AgentReducePolicy::ITEMS_PER_THREAD,\n        VECTOR_LOAD_LENGTH  = CUB_MIN(ITEMS_PER_THREAD, AgentReducePolicy::VECTOR_LOAD_LENGTH),\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n\n        // Can vectorize according to the policy if the input iterator is a native pointer to a primitive type\n        ATTEMPT_VECTORIZATION   = (VECTOR_LOAD_LENGTH > 1) &&\n                                    (ITEMS_PER_THREAD % VECTOR_LOAD_LENGTH == 0) &&\n                                    (IsPointer<InputIteratorT>::VALUE) && Traits<InputT>::PRIMITIVE,\n\n    };\n\n    static const CacheLoadModifier    LOAD_MODIFIER   = AgentReducePolicy::LOAD_MODIFIER;\n    static const BlockReduceAlgorithm BLOCK_ALGORITHM = AgentReducePolicy::BLOCK_ALGORITHM;\n\n    /// Parameterized BlockReduce primitive\n    typedef BlockReduce<OutputT, BLOCK_THREADS, AgentReducePolicy::BLOCK_ALGORITHM> BlockReduceT;\n\n    /// Shared memory type required by this thread block\n    struct _TempStorage\n    {\n        typename BlockReduceT::TempStorage  reduce;\n    };\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&           temp_storage;       ///< Reference to temp_storage\n    InputIteratorT          d_in;               ///< Input data to reduce\n    WrappedInputIteratorT   d_wrapped_in;       ///< Wrapped input data to reduce\n    ReductionOp             reduction_op;       ///< Binary reduction operator\n\n\n    //---------------------------------------------------------------------\n    // Utility\n    //---------------------------------------------------------------------\n\n\n    // Whether or not the input is aligned with the vector type (specialized for types we can vectorize)\n    template <typename Iterator>\n    static __device__ __forceinline__ bool IsAligned(\n        Iterator        d_in,\n        Int2Type<true>  /*can_vectorize*/)\n    {\n        return (size_t(d_in) & (sizeof(VectorT) - 1)) == 0;\n    }\n\n    // Whether or not the input is aligned with the vector type (specialized for types we cannot vectorize)\n    template <typename Iterator>\n    static __device__ __forceinline__ bool IsAligned(\n        Iterator        /*d_in*/,\n        Int2Type<false> /*can_vectorize*/)\n    {\n        return false;\n    }\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentReduce(\n        TempStorage&            temp_storage,       ///< Reference to temp_storage\n        InputIteratorT          d_in,               ///< Input data to reduce\n        ReductionOp             reduction_op)       ///< Binary reduction operator\n    :\n        temp_storage(temp_storage.Alias()),\n        d_in(d_in),\n        d_wrapped_in(d_in),\n        reduction_op(reduction_op)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Tile consumption\n    //---------------------------------------------------------------------\n\n    /**\n     * Consume a full tile of input (non-vectorized)\n     */\n    template <int IS_FIRST_TILE>\n    __device__ __forceinline__ void ConsumeTile(\n        OutputT                 &thread_aggregate,\n        OffsetT                 block_offset,       ///< The offset the tile to consume\n        int                     /*valid_items*/,    ///< The number of valid items in the tile\n        Int2Type<true>          /*is_full_tile*/,   ///< Whether or not this is a full tile\n        Int2Type<false>         /*can_vectorize*/)  ///< Whether or not we can vectorize loads\n    {\n        OutputT items[ITEMS_PER_THREAD];\n\n        // Load items in striped fashion\n        LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_wrapped_in + block_offset, items);\n\n        // Reduce items within each thread stripe\n        thread_aggregate = (IS_FIRST_TILE) ?\n            internal::ThreadReduce(items, reduction_op) :\n            internal::ThreadReduce(items, reduction_op, thread_aggregate);\n    }\n\n\n    /**\n     * Consume a full tile of input (vectorized)\n     */\n    template <int IS_FIRST_TILE>\n    __device__ __forceinline__ void ConsumeTile(\n        OutputT                 &thread_aggregate,\n        OffsetT                 block_offset,       ///< The offset the tile to consume\n        int                     /*valid_items*/,    ///< The number of valid items in the tile\n        Int2Type<true>          /*is_full_tile*/,   ///< Whether or not this is a full tile\n        Int2Type<true>          /*can_vectorize*/)  ///< Whether or not we can vectorize loads\n    {\n        // Alias items as an array of VectorT and load it in striped fashion\n        enum { WORDS =  ITEMS_PER_THREAD / VECTOR_LOAD_LENGTH };\n\n        // Fabricate a vectorized input iterator\n        InputT *d_in_unqualified = const_cast<InputT*>(d_in) + block_offset + (threadIdx.x * VECTOR_LOAD_LENGTH);\n        CacheModifiedInputIterator<AgentReducePolicy::LOAD_MODIFIER, VectorT, OffsetT> d_vec_in(\n            reinterpret_cast<VectorT*>(d_in_unqualified));\n\n        // Load items as vector items\n        InputT input_items[ITEMS_PER_THREAD];\n        VectorT *vec_items = reinterpret_cast<VectorT*>(input_items);\n        #pragma unroll\n        for (int i = 0; i < WORDS; ++i)\n            vec_items[i] = d_vec_in[BLOCK_THREADS * i];\n\n        // Convert from input type to output type\n        OutputT items[ITEMS_PER_THREAD];\n        #pragma unroll\n        for (int i = 0; i < ITEMS_PER_THREAD; ++i)\n            items[i] = input_items[i];\n\n        // Reduce items within each thread stripe\n        thread_aggregate = (IS_FIRST_TILE) ?\n            internal::ThreadReduce(items, reduction_op) :\n            internal::ThreadReduce(items, reduction_op, thread_aggregate);\n    }\n\n\n    /**\n     * Consume a partial tile of input\n     */\n    template <int IS_FIRST_TILE, int CAN_VECTORIZE>\n    __device__ __forceinline__ void ConsumeTile(\n        OutputT                 &thread_aggregate,\n        OffsetT                 block_offset,       ///< The offset the tile to consume\n        int                     valid_items,        ///< The number of valid items in the tile\n        Int2Type<false>         /*is_full_tile*/,   ///< Whether or not this is a full tile\n        Int2Type<CAN_VECTORIZE> /*can_vectorize*/)  ///< Whether or not we can vectorize loads\n    {\n        // Partial tile\n        int thread_offset = threadIdx.x;\n\n        // Read first item\n        if ((IS_FIRST_TILE) && (thread_offset < valid_items))\n        {\n            thread_aggregate = d_wrapped_in[block_offset + thread_offset];\n            thread_offset += BLOCK_THREADS;\n        }\n\n        // Continue reading items (block-striped)\n        while (thread_offset < valid_items)\n        {\n            OutputT item        = d_wrapped_in[block_offset + thread_offset];\n            thread_aggregate    = reduction_op(thread_aggregate, item);\n            thread_offset       += BLOCK_THREADS;\n        }\n    }\n\n\n    //---------------------------------------------------------------\n    // Consume a contiguous segment of tiles\n    //---------------------------------------------------------------------\n\n    /**\n     * \\brief Reduce a contiguous segment of input tiles\n     */\n    template <int CAN_VECTORIZE>\n    __device__ __forceinline__ OutputT ConsumeRange(\n        GridEvenShare<OffsetT> &even_share,          ///< GridEvenShare descriptor\n        Int2Type<CAN_VECTORIZE> can_vectorize)      ///< Whether or not we can vectorize loads\n    {\n        OutputT thread_aggregate;\n\n        if (even_share.block_offset + TILE_ITEMS > even_share.block_end)\n        {\n            // First tile isn't full (not all threads have valid items)\n            int valid_items = even_share.block_end - even_share.block_offset;\n            ConsumeTile<true>(thread_aggregate, even_share.block_offset, valid_items, Int2Type<false>(), can_vectorize);\n            return BlockReduceT(temp_storage.reduce).Reduce(thread_aggregate, reduction_op, valid_items);\n        }\n\n        // At least one full block\n        ConsumeTile<true>(thread_aggregate, even_share.block_offset, TILE_ITEMS, Int2Type<true>(), can_vectorize);\n        even_share.block_offset += even_share.block_stride;\n\n        // Consume subsequent full tiles of input\n        while (even_share.block_offset + TILE_ITEMS <= even_share.block_end)\n        {\n            ConsumeTile<false>(thread_aggregate, even_share.block_offset, TILE_ITEMS, Int2Type<true>(), can_vectorize);\n            even_share.block_offset += even_share.block_stride;\n        }\n\n        // Consume a partially-full tile\n        if (even_share.block_offset < even_share.block_end)\n        {\n            int valid_items = even_share.block_end - even_share.block_offset;\n            ConsumeTile<false>(thread_aggregate, even_share.block_offset, valid_items, Int2Type<false>(), can_vectorize);\n        }\n\n        // Compute block-wide reduction (all threads have valid items)\n        return BlockReduceT(temp_storage.reduce).Reduce(thread_aggregate, reduction_op);\n    }\n\n\n    /**\n     * \\brief Reduce a contiguous segment of input tiles\n     */\n    __device__ __forceinline__ OutputT ConsumeRange(\n        OffsetT block_offset,                       ///< [in] Threadblock begin offset (inclusive)\n        OffsetT block_end)                          ///< [in] Threadblock end offset (exclusive)\n    {\n        GridEvenShare<OffsetT> even_share;\n        even_share.template BlockInit<TILE_ITEMS>(block_offset, block_end);\n\n        return (IsAligned(d_in + block_offset, Int2Type<ATTEMPT_VECTORIZATION>())) ?\n            ConsumeRange(even_share, Int2Type<true && ATTEMPT_VECTORIZATION>()) :\n            ConsumeRange(even_share, Int2Type<false && ATTEMPT_VECTORIZATION>());\n    }\n\n\n    /**\n     * Reduce a contiguous segment of input tiles\n     */\n    __device__ __forceinline__ OutputT ConsumeTiles(\n        GridEvenShare<OffsetT> &even_share)        ///< [in] GridEvenShare descriptor\n    {\n        // Initialize GRID_MAPPING_STRIP_MINE even-share descriptor for this thread block\n        even_share.template BlockInit<TILE_ITEMS, GRID_MAPPING_STRIP_MINE>();\n\n        return (IsAligned(d_in, Int2Type<ATTEMPT_VECTORIZATION>())) ?\n            ConsumeRange(even_share, Int2Type<true && ATTEMPT_VECTORIZATION>()) :\n            ConsumeRange(even_share, Int2Type<false && ATTEMPT_VECTORIZATION>());\n\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_reduce_by_key.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentReduceByKey implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduce-value-by-key.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"single_pass_scan_operators.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../block/block_discontinuity.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../iterator/constant_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentReduceByKey\n */\ntemplate <\n    int                         _BLOCK_THREADS,                 ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,              ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    BlockScanAlgorithm          _SCAN_ALGORITHM>                ///< The BlockScan algorithm to use\nstruct AgentReduceByKeyPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;      ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;      ///< The BlockScan algorithm to use\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentReduceByKey implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduce-value-by-key\n */\ntemplate <\n    typename    AgentReduceByKeyPolicyT,        ///< Parameterized AgentReduceByKeyPolicy tuning policy type\n    typename    KeysInputIteratorT,             ///< Random-access input iterator type for keys\n    typename    UniqueOutputIteratorT,          ///< Random-access output iterator type for keys\n    typename    ValuesInputIteratorT,           ///< Random-access input iterator type for values\n    typename    AggregatesOutputIteratorT,      ///< Random-access output iterator type for values\n    typename    NumRunsOutputIteratorT,         ///< Output iterator type for recording number of items selected\n    typename    EqualityOpT,                    ///< KeyT equality operator type\n    typename    ReductionOpT,                   ///< ValueT reduction operator type\n    typename    OffsetT>                        ///< Signed integer type for global offsets\nstruct AgentReduceByKey\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // The input keys type\n    typedef typename std::iterator_traits<KeysInputIteratorT>::value_type KeyInputT;\n\n    // The output keys type\n    typedef typename If<(Equals<typename std::iterator_traits<UniqueOutputIteratorT>::value_type, void>::VALUE),    // KeyOutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<KeysInputIteratorT>::value_type,                                              // ... then the input iterator's value type,\n        typename std::iterator_traits<UniqueOutputIteratorT>::value_type>::Type KeyOutputT;                         // ... else the output iterator's value type\n\n    // The input values type\n    typedef typename std::iterator_traits<ValuesInputIteratorT>::value_type ValueInputT;\n\n    // The output values type\n    typedef typename If<(Equals<typename std::iterator_traits<AggregatesOutputIteratorT>::value_type, void>::VALUE),    // ValueOutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<ValuesInputIteratorT>::value_type,                                                // ... then the input iterator's value type,\n        typename std::iterator_traits<AggregatesOutputIteratorT>::value_type>::Type ValueOutputT;                       // ... else the output iterator's value type\n\n    // Tuple type for scanning (pairs accumulated segment-value with segment-index)\n    typedef KeyValuePair<OffsetT, ValueOutputT> OffsetValuePairT;\n\n    // Tuple type for pairing keys and values\n    typedef KeyValuePair<KeyOutputT, ValueOutputT> KeyValuePairT;\n\n    // Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<ValueOutputT, OffsetT> ScanTileStateT;\n\n    // Guarded inequality functor\n    template <typename _EqualityOpT>\n    struct GuardedInequalityWrapper\n    {\n        _EqualityOpT     op;             ///< Wrapped equality operator\n        int             num_remaining;  ///< Items remaining\n\n        /// Constructor\n        __host__ __device__ __forceinline__\n        GuardedInequalityWrapper(_EqualityOpT op, int num_remaining) : op(op), num_remaining(num_remaining) {}\n\n        /// Boolean inequality operator, returns <tt>(a != b)</tt>\n        template <typename T>\n        __host__ __device__ __forceinline__ bool operator()(const T &a, const T &b, int idx) const\n        {\n            if (idx < num_remaining)\n                return !op(a, b);   // In bounds\n\n            // Return true if first out-of-bounds item, false otherwise\n            return (idx == num_remaining);\n       }\n    };\n\n\n    // Constants\n    enum\n    {\n        BLOCK_THREADS       = AgentReduceByKeyPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = AgentReduceByKeyPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n        TWO_PHASE_SCATTER   = (ITEMS_PER_THREAD > 1),\n\n        // Whether or not the scan operation has a zero-valued identity value (true if we're performing addition on a primitive type)\n        HAS_IDENTITY_ZERO   = (Equals<ReductionOpT, cub::Sum>::VALUE) && (Traits<ValueOutputT>::PRIMITIVE),\n    };\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for keys\n    typedef typename If<IsPointer<KeysInputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentReduceByKeyPolicyT::LOAD_MODIFIER, KeyInputT, OffsetT>,     // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            KeysInputIteratorT>::Type                                                                   // Directly use the supplied input iterator type\n        WrappedKeysInputIteratorT;\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for values\n    typedef typename If<IsPointer<ValuesInputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentReduceByKeyPolicyT::LOAD_MODIFIER, ValueInputT, OffsetT>,   // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            ValuesInputIteratorT>::Type                                                                 // Directly use the supplied input iterator type\n        WrappedValuesInputIteratorT;\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for fixup values\n    typedef typename If<IsPointer<AggregatesOutputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentReduceByKeyPolicyT::LOAD_MODIFIER, ValueInputT, OffsetT>,   // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            AggregatesOutputIteratorT>::Type                                                            // Directly use the supplied input iterator type\n        WrappedFixupInputIteratorT;\n\n    // Reduce-value-by-segment scan operator\n    typedef ReduceBySegmentOp<ReductionOpT> ReduceBySegmentOpT;\n\n    // Parameterized BlockLoad type for keys\n    typedef BlockLoad<\n            KeyOutputT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            AgentReduceByKeyPolicyT::LOAD_ALGORITHM>\n        BlockLoadKeysT;\n\n    // Parameterized BlockLoad type for values\n    typedef BlockLoad<\n            ValueOutputT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            AgentReduceByKeyPolicyT::LOAD_ALGORITHM>\n        BlockLoadValuesT;\n\n    // Parameterized BlockDiscontinuity type for keys\n    typedef BlockDiscontinuity<\n            KeyOutputT,\n            BLOCK_THREADS>\n        BlockDiscontinuityKeys;\n\n    // Parameterized BlockScan type\n    typedef BlockScan<\n            OffsetValuePairT,\n            BLOCK_THREADS,\n            AgentReduceByKeyPolicyT::SCAN_ALGORITHM>\n        BlockScanT;\n\n    // Callback type for obtaining tile prefix during block scan\n    typedef TilePrefixCallbackOp<\n            OffsetValuePairT,\n            ReduceBySegmentOpT,\n            ScanTileStateT>\n        TilePrefixCallbackOpT;\n\n    // Key and value exchange types\n    typedef KeyOutputT    KeyExchangeT[TILE_ITEMS + 1];\n    typedef ValueOutputT  ValueExchangeT[TILE_ITEMS + 1];\n\n    // Shared memory type for this thread block\n    union _TempStorage\n    {\n        struct\n        {\n            typename BlockScanT::TempStorage                scan;           // Smem needed for tile scanning\n            typename TilePrefixCallbackOpT::TempStorage     prefix;         // Smem needed for cooperative prefix callback\n            typename BlockDiscontinuityKeys::TempStorage    discontinuity;  // Smem needed for discontinuity detection\n        };\n\n        // Smem needed for loading keys\n        typename BlockLoadKeysT::TempStorage load_keys;\n\n        // Smem needed for loading values\n        typename BlockLoadValuesT::TempStorage load_values;\n\n        // Smem needed for compacting key value pairs(allows non POD items in this union)\n        Uninitialized<KeyValuePairT[TILE_ITEMS + 1]> raw_exchange;\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&                   temp_storage;       ///< Reference to temp_storage\n    WrappedKeysInputIteratorT       d_keys_in;          ///< Input keys\n    UniqueOutputIteratorT           d_unique_out;       ///< Unique output keys\n    WrappedValuesInputIteratorT     d_values_in;        ///< Input values\n    AggregatesOutputIteratorT       d_aggregates_out;   ///< Output value aggregates\n    NumRunsOutputIteratorT          d_num_runs_out;     ///< Output pointer for total number of segments identified\n    EqualityOpT                     equality_op;        ///< KeyT equality operator\n    ReductionOpT                    reduction_op;       ///< Reduction operator\n    ReduceBySegmentOpT              scan_op;            ///< Reduce-by-segment scan operator\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    // Constructor\n    __device__ __forceinline__\n    AgentReduceByKey(\n        TempStorage&                temp_storage,       ///< Reference to temp_storage\n        KeysInputIteratorT          d_keys_in,          ///< Input keys\n        UniqueOutputIteratorT       d_unique_out,       ///< Unique output keys\n        ValuesInputIteratorT        d_values_in,        ///< Input values\n        AggregatesOutputIteratorT   d_aggregates_out,   ///< Output value aggregates\n        NumRunsOutputIteratorT      d_num_runs_out,     ///< Output pointer for total number of segments identified\n        EqualityOpT                 equality_op,        ///< KeyT equality operator\n        ReductionOpT                reduction_op)       ///< ValueT reduction operator\n    :\n        temp_storage(temp_storage.Alias()),\n        d_keys_in(d_keys_in),\n        d_unique_out(d_unique_out),\n        d_values_in(d_values_in),\n        d_aggregates_out(d_aggregates_out),\n        d_num_runs_out(d_num_runs_out),\n        equality_op(equality_op),\n        reduction_op(reduction_op),\n        scan_op(reduction_op)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Scatter utility methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Directly scatter flagged items to output offsets\n     */\n    __device__ __forceinline__ void ScatterDirect(\n        KeyValuePairT   (&scatter_items)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_indices)[ITEMS_PER_THREAD])\n    {\n        // Scatter flagged keys and values\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (segment_flags[ITEM])\n            {\n                d_unique_out[segment_indices[ITEM]]     = scatter_items[ITEM].key;\n                d_aggregates_out[segment_indices[ITEM]] = scatter_items[ITEM].value;\n            }\n        }\n    }\n\n\n    /**\n     * 2-phase scatter flagged items to output offsets\n     *\n     * The exclusive scan causes each head flag to be paired with the previous\n     * value aggregate: the scatter offsets must be decremented for value aggregates\n     */\n    __device__ __forceinline__ void ScatterTwoPhase(\n        KeyValuePairT   (&scatter_items)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_indices)[ITEMS_PER_THREAD],\n        OffsetT         num_tile_segments,\n        OffsetT         num_tile_segments_prefix)\n    {\n        CTA_SYNC();\n\n        // Compact and scatter pairs\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (segment_flags[ITEM])\n            {\n                temp_storage.raw_exchange.Alias()[segment_indices[ITEM] - num_tile_segments_prefix] = scatter_items[ITEM];\n            }\n        }\n\n        CTA_SYNC();\n\n        for (int item = threadIdx.x; item < num_tile_segments; item += BLOCK_THREADS)\n        {\n            KeyValuePairT pair                                  = temp_storage.raw_exchange.Alias()[item];\n            d_unique_out[num_tile_segments_prefix + item]       = pair.key;\n            d_aggregates_out[num_tile_segments_prefix + item]   = pair.value;\n        }\n    }\n\n\n    /**\n     * Scatter flagged items\n     */\n    __device__ __forceinline__ void Scatter(\n        KeyValuePairT   (&scatter_items)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&segment_indices)[ITEMS_PER_THREAD],\n        OffsetT         num_tile_segments,\n        OffsetT         num_tile_segments_prefix)\n    {\n        // Do a one-phase scatter if (a) two-phase is disabled or (b) the average number of selected items per thread is less than one\n        if (TWO_PHASE_SCATTER && (num_tile_segments > BLOCK_THREADS))\n        {\n            ScatterTwoPhase(\n                scatter_items,\n                segment_flags,\n                segment_indices,\n                num_tile_segments,\n                num_tile_segments_prefix);\n        }\n        else\n        {\n            ScatterDirect(\n                scatter_items,\n                segment_flags,\n                segment_indices);\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Cooperatively scan a device-wide sequence of tiles with other CTAs\n    //---------------------------------------------------------------------\n\n    /**\n     * Process a tile of input (dynamic chained scan)\n     */\n    template <bool IS_LAST_TILE>                ///< Whether the current tile is the last tile\n    __device__ __forceinline__ void ConsumeTile(\n        OffsetT             num_remaining,      ///< Number of global input items remaining (including this tile)\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        KeyOutputT          keys[ITEMS_PER_THREAD];             // Tile keys\n        KeyOutputT          prev_keys[ITEMS_PER_THREAD];        // Tile keys shuffled up\n        ValueOutputT        values[ITEMS_PER_THREAD];           // Tile values\n        OffsetT             head_flags[ITEMS_PER_THREAD];       // Segment head flags\n        OffsetT             segment_indices[ITEMS_PER_THREAD];  // Segment indices\n        OffsetValuePairT    scan_items[ITEMS_PER_THREAD];       // Zipped values and segment flags|indices\n        KeyValuePairT       scatter_items[ITEMS_PER_THREAD];    // Zipped key value pairs for scattering\n\n        // Load keys\n        if (IS_LAST_TILE)\n            BlockLoadKeysT(temp_storage.load_keys).Load(d_keys_in + tile_offset, keys, num_remaining);\n        else\n            BlockLoadKeysT(temp_storage.load_keys).Load(d_keys_in + tile_offset, keys);\n\n        // Load tile predecessor key in first thread\n        KeyOutputT tile_predecessor;\n        if (threadIdx.x == 0)\n        {\n            tile_predecessor = (tile_idx == 0) ?\n                keys[0] :                       // First tile gets repeat of first item (thus first item will not be flagged as a head)\n                d_keys_in[tile_offset - 1];     // Subsequent tiles get last key from previous tile\n        }\n\n        CTA_SYNC();\n\n        // Load values\n        if (IS_LAST_TILE)\n            BlockLoadValuesT(temp_storage.load_values).Load(d_values_in + tile_offset, values, num_remaining);\n        else\n            BlockLoadValuesT(temp_storage.load_values).Load(d_values_in + tile_offset, values);\n\n        CTA_SYNC();\n\n        // Initialize head-flags and shuffle up the previous keys\n        if (IS_LAST_TILE)\n        {\n            // Use custom flag operator to additionally flag the first out-of-bounds item\n            GuardedInequalityWrapper<EqualityOpT> flag_op(equality_op, num_remaining);\n            BlockDiscontinuityKeys(temp_storage.discontinuity).FlagHeads(\n                head_flags, keys, prev_keys, flag_op, tile_predecessor);\n        }\n        else\n        {\n            InequalityWrapper<EqualityOpT> flag_op(equality_op);\n            BlockDiscontinuityKeys(temp_storage.discontinuity).FlagHeads(\n                head_flags, keys, prev_keys, flag_op, tile_predecessor);\n        }\n\n        // Zip values and head flags\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            scan_items[ITEM].value  = values[ITEM];\n            scan_items[ITEM].key    = head_flags[ITEM];\n        }\n\n        // Perform exclusive tile scan\n        OffsetValuePairT    block_aggregate;        // Inclusive block-wide scan aggregate\n        OffsetT             num_segments_prefix;    // Number of segments prior to this tile\n        ValueOutputT        total_aggregate;        // The tile prefix folded with block_aggregate\n        if (tile_idx == 0)\n        {\n            // Scan first tile\n            BlockScanT(temp_storage.scan).ExclusiveScan(scan_items, scan_items, scan_op, block_aggregate);\n            num_segments_prefix     = 0;\n            total_aggregate         = block_aggregate.value;\n\n            // Update tile status if there are successor tiles\n            if ((!IS_LAST_TILE) && (threadIdx.x == 0))\n                tile_state.SetInclusive(0, block_aggregate);\n        }\n        else\n        {\n            // Scan non-first tile\n            TilePrefixCallbackOpT prefix_op(tile_state, temp_storage.prefix, scan_op, tile_idx);\n            BlockScanT(temp_storage.scan).ExclusiveScan(scan_items, scan_items, scan_op, prefix_op);\n\n            block_aggregate         = prefix_op.GetBlockAggregate();\n            num_segments_prefix     = prefix_op.GetExclusivePrefix().key;\n            total_aggregate         = reduction_op(\n                                        prefix_op.GetExclusivePrefix().value,\n                                        block_aggregate.value);\n        }\n\n        // Rezip scatter items and segment indices\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            scatter_items[ITEM].key     = prev_keys[ITEM];\n            scatter_items[ITEM].value   = scan_items[ITEM].value;\n            segment_indices[ITEM]       = scan_items[ITEM].key;\n        }\n\n        // At this point, each flagged segment head has:\n        //  - The key for the previous segment\n        //  - The reduced value from the previous segment\n        //  - The segment index for the reduced value\n\n        // Scatter flagged keys and values\n        OffsetT num_tile_segments = block_aggregate.key;\n        Scatter(scatter_items, head_flags, segment_indices, num_tile_segments, num_segments_prefix);\n\n        // Last thread in last tile will output final count (and last pair, if necessary)\n        if ((IS_LAST_TILE) && (threadIdx.x == BLOCK_THREADS - 1))\n        {\n            OffsetT num_segments = num_segments_prefix + num_tile_segments;\n\n            // If the last tile is a whole tile, output the final_value\n            if (num_remaining == TILE_ITEMS)\n            {\n                d_unique_out[num_segments]      = keys[ITEMS_PER_THREAD - 1];\n                d_aggregates_out[num_segments]  = total_aggregate;\n                num_segments++;\n            }\n\n            // Output the total number of items selected\n            *d_num_runs_out = num_segments;\n        }\n    }\n\n\n    /**\n     * Scan tiles of items as part of a dynamic chained scan\n     */\n    __device__ __forceinline__ void ConsumeRange(\n        int                 num_items,          ///< Total number of input items\n        ScanTileStateT&     tile_state,         ///< Global tile state descriptor\n        int                 start_tile)         ///< The starting tile for the current grid\n    {\n        // Blocks are launched in increasing order, so just assign one tile per block\n        int     tile_idx        = start_tile + blockIdx.x;          // Current tile index\n        OffsetT tile_offset     = OffsetT(TILE_ITEMS) * tile_idx;   // Global offset for the current tile\n        OffsetT num_remaining   = num_items - tile_offset;          // Remaining items (including this tile)\n\n        if (num_remaining > TILE_ITEMS)\n        {\n            // Not last tile\n            ConsumeTile<false>(num_remaining, tile_idx, tile_offset, tile_state);\n        }\n        else if (num_remaining > 0)\n        {\n            // Last tile\n            ConsumeTile<true>(num_remaining, tile_idx, tile_offset, tile_state);\n        }\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_rle.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentRle implements a stateful abstraction of CUDA thread blocks for participating in device-wide run-length-encode.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"single_pass_scan_operators.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../block/block_exchange.cuh\"\n#include \"../block/block_discontinuity.cuh\"\n#include \"../grid/grid_queue.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../iterator/constant_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentRle\n */\ntemplate <\n    int                         _BLOCK_THREADS,                 ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,              ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    bool                        _STORE_WARP_TIME_SLICING,       ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any store-related data transpositions (versus each warp having its own storage)\n    BlockScanAlgorithm          _SCAN_ALGORITHM>                ///< The BlockScan algorithm to use\nstruct AgentRlePolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n        STORE_WARP_TIME_SLICING = _STORE_WARP_TIME_SLICING,     ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any store-related data transpositions (versus each warp having its own storage)\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;      ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;      ///< The BlockScan algorithm to use\n};\n\n\n\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentRle implements a stateful abstraction of CUDA thread blocks for participating in device-wide run-length-encode \n */\ntemplate <\n    typename    AgentRlePolicyT,        ///< Parameterized AgentRlePolicyT tuning policy type\n    typename    InputIteratorT,         ///< Random-access input iterator type for data\n    typename    OffsetsOutputIteratorT, ///< Random-access output iterator type for offset values\n    typename    LengthsOutputIteratorT, ///< Random-access output iterator type for length values\n    typename    EqualityOpT,            ///< T equality operator type\n    typename    OffsetT>                ///< Signed integer type for global offsets\nstruct AgentRle\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type T;\n\n    /// The lengths output value type\n    typedef typename If<(Equals<typename std::iterator_traits<LengthsOutputIteratorT>::value_type, void>::VALUE),   // LengthT =  (if output iterator's value type is void) ?\n        OffsetT,                                                                                                    // ... then the OffsetT type,\n        typename std::iterator_traits<LengthsOutputIteratorT>::value_type>::Type LengthT;                           // ... else the output iterator's value type\n\n    /// Tuple type for scanning (pairs run-length and run-index)\n    typedef KeyValuePair<OffsetT, LengthT> LengthOffsetPair;\n\n    /// Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<LengthT, OffsetT> ScanTileStateT;\n\n    // Constants\n    enum\n    {\n        WARP_THREADS            = CUB_WARP_THREADS(PTX_ARCH),\n        BLOCK_THREADS           = AgentRlePolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = AgentRlePolicyT::ITEMS_PER_THREAD,\n        WARP_ITEMS              = WARP_THREADS * ITEMS_PER_THREAD,\n        TILE_ITEMS              = BLOCK_THREADS * ITEMS_PER_THREAD,\n        WARPS                   = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        /// Whether or not to sync after loading data\n        SYNC_AFTER_LOAD         = (AgentRlePolicyT::LOAD_ALGORITHM != BLOCK_LOAD_DIRECT),\n\n        /// Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any store-related data transpositions (versus each warp having its own storage)\n        STORE_WARP_TIME_SLICING = AgentRlePolicyT::STORE_WARP_TIME_SLICING,\n        ACTIVE_EXCHANGE_WARPS   = (STORE_WARP_TIME_SLICING) ? 1 : WARPS,\n    };\n\n\n    /**\n     * Special operator that signals all out-of-bounds items are not equal to everything else,\n     * forcing both (1) the last item to be tail-flagged and (2) all oob items to be marked\n     * trivial.\n     */\n    template <bool LAST_TILE>\n    struct OobInequalityOp\n    {\n        OffsetT         num_remaining;\n        EqualityOpT      equality_op;\n\n        __device__ __forceinline__ OobInequalityOp(\n            OffsetT     num_remaining,\n            EqualityOpT  equality_op)\n        :\n            num_remaining(num_remaining),\n            equality_op(equality_op)\n        {}\n\n        template <typename Index>\n        __host__ __device__ __forceinline__ bool operator()(T first, T second, Index idx)\n        {\n            if (!LAST_TILE || (idx < num_remaining))\n                return !equality_op(first, second);\n            else\n                return true;\n        }\n    };\n\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for data\n    typedef typename If<IsPointer<InputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentRlePolicyT::LOAD_MODIFIER, T, OffsetT>,      // Wrap the native input pointer with CacheModifiedVLengthnputIterator\n            InputIteratorT>::Type                                                       // Directly use the supplied input iterator type\n        WrappedInputIteratorT;\n\n    // Parameterized BlockLoad type for data\n    typedef BlockLoad<\n            T,\n            AgentRlePolicyT::BLOCK_THREADS,\n            AgentRlePolicyT::ITEMS_PER_THREAD,\n            AgentRlePolicyT::LOAD_ALGORITHM>\n        BlockLoadT;\n\n    // Parameterized BlockDiscontinuity type for data\n    typedef BlockDiscontinuity<T, BLOCK_THREADS> BlockDiscontinuityT;\n\n    // Parameterized WarpScan type\n    typedef WarpScan<LengthOffsetPair> WarpScanPairs;\n\n    // Reduce-length-by-run scan operator\n    typedef ReduceBySegmentOp<cub::Sum> ReduceBySegmentOpT;\n\n    // Callback type for obtaining tile prefix during block scan\n    typedef TilePrefixCallbackOp<\n            LengthOffsetPair,\n            ReduceBySegmentOpT,\n            ScanTileStateT>\n        TilePrefixCallbackOpT;\n\n    // Warp exchange types\n    typedef WarpExchange<LengthOffsetPair, ITEMS_PER_THREAD>        WarpExchangePairs;\n\n    typedef typename If<STORE_WARP_TIME_SLICING, typename WarpExchangePairs::TempStorage, NullType>::Type WarpExchangePairsStorage;\n\n    typedef WarpExchange<OffsetT, ITEMS_PER_THREAD>                 WarpExchangeOffsets;\n    typedef WarpExchange<LengthT, ITEMS_PER_THREAD>                 WarpExchangeLengths;\n\n    typedef LengthOffsetPair WarpAggregates[WARPS];\n\n    // Shared memory type for this thread block\n    struct _TempStorage\n    {\n        // Aliasable storage layout\n        union Aliasable\n        {\n            struct\n            {\n                typename BlockDiscontinuityT::TempStorage       discontinuity;              // Smem needed for discontinuity detection\n                typename WarpScanPairs::TempStorage             warp_scan[WARPS];           // Smem needed for warp-synchronous scans\n                Uninitialized<LengthOffsetPair[WARPS]>          warp_aggregates;            // Smem needed for sharing warp-wide aggregates\n                typename TilePrefixCallbackOpT::TempStorage     prefix;                     // Smem needed for cooperative prefix callback\n            };\n\n            // Smem needed for input loading\n            typename BlockLoadT::TempStorage                    load;\n\n            // Aliasable layout needed for two-phase scatter\n            union ScatterAliasable\n            {\n                unsigned long long                              align;\n                WarpExchangePairsStorage                        exchange_pairs[ACTIVE_EXCHANGE_WARPS];\n                typename WarpExchangeOffsets::TempStorage       exchange_offsets[ACTIVE_EXCHANGE_WARPS];\n                typename WarpExchangeLengths::TempStorage       exchange_lengths[ACTIVE_EXCHANGE_WARPS];\n\n            } scatter_aliasable;\n\n        } aliasable;\n\n        OffsetT             tile_idx;                   // Shared tile index\n        LengthOffsetPair    tile_inclusive;             // Inclusive tile prefix\n        LengthOffsetPair    tile_exclusive;             // Exclusive tile prefix\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&                   temp_storage;       ///< Reference to temp_storage\n\n    WrappedInputIteratorT           d_in;               ///< Pointer to input sequence of data items\n    OffsetsOutputIteratorT          d_offsets_out;      ///< Input run offsets\n    LengthsOutputIteratorT          d_lengths_out;      ///< Output run lengths\n\n    EqualityOpT                     equality_op;        ///< T equality operator\n    ReduceBySegmentOpT              scan_op;            ///< Reduce-length-by-flag scan operator\n    OffsetT                         num_items;          ///< Total number of input items\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    // Constructor\n    __device__ __forceinline__\n    AgentRle(\n        TempStorage                 &temp_storage,      ///< [in] Reference to temp_storage\n        InputIteratorT              d_in,               ///< [in] Pointer to input sequence of data items\n        OffsetsOutputIteratorT      d_offsets_out,      ///< [out] Pointer to output sequence of run offsets\n        LengthsOutputIteratorT      d_lengths_out,      ///< [out] Pointer to output sequence of run lengths\n        EqualityOpT                 equality_op,        ///< [in] T equality operator\n        OffsetT                     num_items)          ///< [in] Total number of input items\n    :\n        temp_storage(temp_storage.Alias()),\n        d_in(d_in),\n        d_offsets_out(d_offsets_out),\n        d_lengths_out(d_lengths_out),\n        equality_op(equality_op),\n        scan_op(cub::Sum()),\n        num_items(num_items)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Utility methods for initializing the selections\n    //---------------------------------------------------------------------\n\n    template <bool FIRST_TILE, bool LAST_TILE>\n    __device__ __forceinline__ void InitializeSelections(\n        OffsetT             tile_offset,\n        OffsetT             num_remaining,\n        T                   (&items)[ITEMS_PER_THREAD],\n        LengthOffsetPair    (&lengths_and_num_runs)[ITEMS_PER_THREAD])\n    {\n        bool                head_flags[ITEMS_PER_THREAD];\n        bool                tail_flags[ITEMS_PER_THREAD];\n\n        OobInequalityOp<LAST_TILE> inequality_op(num_remaining, equality_op);\n\n        if (FIRST_TILE && LAST_TILE)\n        {\n            // First-and-last-tile always head-flags the first item and tail-flags the last item\n\n            BlockDiscontinuityT(temp_storage.aliasable.discontinuity).FlagHeadsAndTails(\n                head_flags, tail_flags, items, inequality_op);\n        }\n        else if (FIRST_TILE)\n        {\n            // First-tile always head-flags the first item\n\n            // Get the first item from the next tile\n            T tile_successor_item;\n            if (threadIdx.x == BLOCK_THREADS - 1)\n                tile_successor_item = d_in[tile_offset + TILE_ITEMS];\n\n            BlockDiscontinuityT(temp_storage.aliasable.discontinuity).FlagHeadsAndTails(\n                head_flags, tail_flags, tile_successor_item, items, inequality_op);\n        }\n        else if (LAST_TILE)\n        {\n            // Last-tile always flags the last item\n\n            // Get the last item from the previous tile\n            T tile_predecessor_item;\n            if (threadIdx.x == 0)\n                tile_predecessor_item = d_in[tile_offset - 1];\n\n            BlockDiscontinuityT(temp_storage.aliasable.discontinuity).FlagHeadsAndTails(\n                head_flags, tile_predecessor_item, tail_flags, items, inequality_op);\n        }\n        else\n        {\n            // Get the first item from the next tile\n            T tile_successor_item;\n            if (threadIdx.x == BLOCK_THREADS - 1)\n                tile_successor_item = d_in[tile_offset + TILE_ITEMS];\n\n            // Get the last item from the previous tile\n            T tile_predecessor_item;\n            if (threadIdx.x == 0)\n                tile_predecessor_item = d_in[tile_offset - 1];\n\n            BlockDiscontinuityT(temp_storage.aliasable.discontinuity).FlagHeadsAndTails(\n                head_flags, tile_predecessor_item, tail_flags, tile_successor_item, items, inequality_op);\n        }\n\n        // Zip counts and runs\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            lengths_and_num_runs[ITEM].key      = head_flags[ITEM] && (!tail_flags[ITEM]);\n            lengths_and_num_runs[ITEM].value    = ((!head_flags[ITEM]) || (!tail_flags[ITEM]));\n        }\n    }\n\n    //---------------------------------------------------------------------\n    // Scan utility methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Scan of allocations\n     */\n    __device__ __forceinline__ void WarpScanAllocations(\n        LengthOffsetPair    &tile_aggregate,\n        LengthOffsetPair    &warp_aggregate,\n        LengthOffsetPair    &warp_exclusive_in_tile,\n        LengthOffsetPair    &thread_exclusive_in_warp,\n        LengthOffsetPair    (&lengths_and_num_runs)[ITEMS_PER_THREAD])\n    {\n        // Perform warpscans\n        unsigned int warp_id = ((WARPS == 1) ? 0 : threadIdx.x / WARP_THREADS);\n        int lane_id = LaneId();\n\n        LengthOffsetPair identity;\n        identity.key = 0;\n        identity.value = 0;\n\n        LengthOffsetPair thread_inclusive;\n        LengthOffsetPair thread_aggregate = internal::ThreadReduce(lengths_and_num_runs, scan_op);\n        WarpScanPairs(temp_storage.aliasable.warp_scan[warp_id]).Scan(\n            thread_aggregate,\n            thread_inclusive,\n            thread_exclusive_in_warp,\n            identity,\n            scan_op);\n\n        // Last lane in each warp shares its warp-aggregate\n        if (lane_id == WARP_THREADS - 1)\n            temp_storage.aliasable.warp_aggregates.Alias()[warp_id] = thread_inclusive;\n\n        CTA_SYNC();\n\n        // Accumulate total selected and the warp-wide prefix\n        warp_exclusive_in_tile          = identity;\n        warp_aggregate                  = temp_storage.aliasable.warp_aggregates.Alias()[warp_id];\n        tile_aggregate                  = temp_storage.aliasable.warp_aggregates.Alias()[0];\n\n        #pragma unroll\n        for (int WARP = 1; WARP < WARPS; ++WARP)\n        {\n            if (warp_id == WARP)\n                warp_exclusive_in_tile = tile_aggregate;\n\n            tile_aggregate = scan_op(tile_aggregate, temp_storage.aliasable.warp_aggregates.Alias()[WARP]);\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Utility methods for scattering selections\n    //---------------------------------------------------------------------\n\n    /**\n     * Two-phase scatter, specialized for warp time-slicing\n     */\n    template <bool FIRST_TILE>\n    __device__ __forceinline__ void ScatterTwoPhase(\n        OffsetT             tile_num_runs_exclusive_in_global,\n        OffsetT             warp_num_runs_aggregate,\n        OffsetT             warp_num_runs_exclusive_in_tile,\n        OffsetT             (&thread_num_runs_exclusive_in_warp)[ITEMS_PER_THREAD],\n        LengthOffsetPair    (&lengths_and_offsets)[ITEMS_PER_THREAD],\n        Int2Type<true>      is_warp_time_slice)\n    {\n        unsigned int warp_id = ((WARPS == 1) ? 0 : threadIdx.x / WARP_THREADS);\n        int lane_id = LaneId();\n\n        // Locally compact items within the warp (first warp)\n        if (warp_id == 0)\n        {\n            WarpExchangePairs(temp_storage.aliasable.scatter_aliasable.exchange_pairs[0]).ScatterToStriped(\n                lengths_and_offsets, thread_num_runs_exclusive_in_warp);\n        }\n\n        // Locally compact items within the warp (remaining warps)\n        #pragma unroll\n        for (int SLICE = 1; SLICE < WARPS; ++SLICE)\n        {\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                WarpExchangePairs(temp_storage.aliasable.scatter_aliasable.exchange_pairs[0]).ScatterToStriped(\n                    lengths_and_offsets, thread_num_runs_exclusive_in_warp);\n            }\n        }\n\n        // Global scatter\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if ((ITEM * WARP_THREADS) < warp_num_runs_aggregate - lane_id)\n            {\n                OffsetT item_offset =\n                    tile_num_runs_exclusive_in_global +\n                    warp_num_runs_exclusive_in_tile +\n                    (ITEM * WARP_THREADS) + lane_id;\n\n                // Scatter offset\n                d_offsets_out[item_offset] = lengths_and_offsets[ITEM].key;\n\n                // Scatter length if not the first (global) length\n                if ((!FIRST_TILE) || (ITEM != 0) || (threadIdx.x > 0))\n                {\n                    d_lengths_out[item_offset - 1] = lengths_and_offsets[ITEM].value;\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Two-phase scatter\n     */\n    template <bool FIRST_TILE>\n    __device__ __forceinline__ void ScatterTwoPhase(\n        OffsetT             tile_num_runs_exclusive_in_global,\n        OffsetT             warp_num_runs_aggregate,\n        OffsetT             warp_num_runs_exclusive_in_tile,\n        OffsetT             (&thread_num_runs_exclusive_in_warp)[ITEMS_PER_THREAD],\n        LengthOffsetPair    (&lengths_and_offsets)[ITEMS_PER_THREAD],\n        Int2Type<false>     is_warp_time_slice)\n    {\n        unsigned int warp_id = ((WARPS == 1) ? 0 : threadIdx.x / WARP_THREADS);\n        int lane_id = LaneId();\n\n        // Unzip\n        OffsetT run_offsets[ITEMS_PER_THREAD];\n        LengthT run_lengths[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            run_offsets[ITEM] = lengths_and_offsets[ITEM].key;\n            run_lengths[ITEM] = lengths_and_offsets[ITEM].value;\n        }\n\n        WarpExchangeOffsets(temp_storage.aliasable.scatter_aliasable.exchange_offsets[warp_id]).ScatterToStriped(\n            run_offsets, thread_num_runs_exclusive_in_warp);\n\n        WARP_SYNC(0xffffffff);\n\n        WarpExchangeLengths(temp_storage.aliasable.scatter_aliasable.exchange_lengths[warp_id]).ScatterToStriped(\n            run_lengths, thread_num_runs_exclusive_in_warp);\n\n        // Global scatter\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if ((ITEM * WARP_THREADS) + lane_id < warp_num_runs_aggregate)\n            {\n                OffsetT item_offset =\n                    tile_num_runs_exclusive_in_global +\n                    warp_num_runs_exclusive_in_tile +\n                    (ITEM * WARP_THREADS) + lane_id;\n\n                // Scatter offset\n                d_offsets_out[item_offset] = run_offsets[ITEM];\n\n                // Scatter length if not the first (global) length\n                if ((!FIRST_TILE) || (ITEM != 0) || (threadIdx.x > 0))\n                {\n                    d_lengths_out[item_offset - 1] = run_lengths[ITEM];\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Direct scatter\n     */\n    template <bool FIRST_TILE>\n    __device__ __forceinline__ void ScatterDirect(\n        OffsetT             tile_num_runs_exclusive_in_global,\n        OffsetT             warp_num_runs_aggregate,\n        OffsetT             warp_num_runs_exclusive_in_tile,\n        OffsetT             (&thread_num_runs_exclusive_in_warp)[ITEMS_PER_THREAD],\n        LengthOffsetPair    (&lengths_and_offsets)[ITEMS_PER_THREAD])\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (thread_num_runs_exclusive_in_warp[ITEM] < warp_num_runs_aggregate)\n            {\n                OffsetT item_offset =\n                    tile_num_runs_exclusive_in_global +\n                    warp_num_runs_exclusive_in_tile +\n                    thread_num_runs_exclusive_in_warp[ITEM];\n\n                // Scatter offset\n                d_offsets_out[item_offset] = lengths_and_offsets[ITEM].key;\n\n                // Scatter length if not the first (global) length\n                if (item_offset >= 1)\n                {\n                    d_lengths_out[item_offset - 1] = lengths_and_offsets[ITEM].value;\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Scatter\n     */\n    template <bool FIRST_TILE>\n    __device__ __forceinline__ void Scatter(\n        OffsetT             tile_num_runs_aggregate,\n        OffsetT             tile_num_runs_exclusive_in_global,\n        OffsetT             warp_num_runs_aggregate,\n        OffsetT             warp_num_runs_exclusive_in_tile,\n        OffsetT             (&thread_num_runs_exclusive_in_warp)[ITEMS_PER_THREAD],\n        LengthOffsetPair    (&lengths_and_offsets)[ITEMS_PER_THREAD])\n    {\n        if ((ITEMS_PER_THREAD == 1) || (tile_num_runs_aggregate < BLOCK_THREADS))\n        {\n            // Direct scatter if the warp has any items\n            if (warp_num_runs_aggregate)\n            {\n                ScatterDirect<FIRST_TILE>(\n                    tile_num_runs_exclusive_in_global,\n                    warp_num_runs_aggregate,\n                    warp_num_runs_exclusive_in_tile,\n                    thread_num_runs_exclusive_in_warp,\n                    lengths_and_offsets);\n            }\n        }\n        else\n        {\n            // Scatter two phase\n            ScatterTwoPhase<FIRST_TILE>(\n                tile_num_runs_exclusive_in_global,\n                warp_num_runs_aggregate,\n                warp_num_runs_exclusive_in_tile,\n                thread_num_runs_exclusive_in_warp,\n                lengths_and_offsets,\n                Int2Type<STORE_WARP_TIME_SLICING>());\n        }\n    }\n\n\n\n    //---------------------------------------------------------------------\n    // Cooperatively scan a device-wide sequence of tiles with other CTAs\n    //---------------------------------------------------------------------\n\n    /**\n     * Process a tile of input (dynamic chained scan)\n     */\n    template <\n        bool                LAST_TILE>\n    __device__ __forceinline__ LengthOffsetPair ConsumeTile(\n        OffsetT             num_items,          ///< Total number of global input items\n        OffsetT             num_remaining,      ///< Number of global input items remaining (including this tile)\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,       ///< Tile offset\n        ScanTileStateT       &tile_status)       ///< Global list of tile status\n    {\n        if (tile_idx == 0)\n        {\n            // First tile\n\n            // Load items\n            T items[ITEMS_PER_THREAD];\n            if (LAST_TILE)\n                BlockLoadT(temp_storage.aliasable.load).Load(d_in + tile_offset, items, num_remaining, T());\n            else\n                BlockLoadT(temp_storage.aliasable.load).Load(d_in + tile_offset, items);\n\n            if (SYNC_AFTER_LOAD)\n                CTA_SYNC();\n\n            // Set flags\n            LengthOffsetPair    lengths_and_num_runs[ITEMS_PER_THREAD];\n\n            InitializeSelections<true, LAST_TILE>(\n                tile_offset,\n                num_remaining,\n                items,\n                lengths_and_num_runs);\n\n            // Exclusive scan of lengths and runs\n            LengthOffsetPair tile_aggregate;\n            LengthOffsetPair warp_aggregate;\n            LengthOffsetPair warp_exclusive_in_tile;\n            LengthOffsetPair thread_exclusive_in_warp;\n\n            WarpScanAllocations(\n                tile_aggregate,\n                warp_aggregate,\n                warp_exclusive_in_tile,\n                thread_exclusive_in_warp,\n                lengths_and_num_runs);\n\n            // Update tile status if this is not the last tile\n            if (!LAST_TILE && (threadIdx.x == 0))\n                tile_status.SetInclusive(0, tile_aggregate);\n\n            // Update thread_exclusive_in_warp to fold in warp run-length\n            if (thread_exclusive_in_warp.key == 0)\n                thread_exclusive_in_warp.value += warp_exclusive_in_tile.value;\n\n            LengthOffsetPair    lengths_and_offsets[ITEMS_PER_THREAD];\n            OffsetT             thread_num_runs_exclusive_in_warp[ITEMS_PER_THREAD];\n            LengthOffsetPair    lengths_and_num_runs2[ITEMS_PER_THREAD];\n\n            // Downsweep scan through lengths_and_num_runs\n            internal::ThreadScanExclusive(lengths_and_num_runs, lengths_and_num_runs2, scan_op, thread_exclusive_in_warp);\n\n            // Zip\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                lengths_and_offsets[ITEM].value         = lengths_and_num_runs2[ITEM].value;\n                lengths_and_offsets[ITEM].key        = tile_offset + (threadIdx.x * ITEMS_PER_THREAD) + ITEM;\n                thread_num_runs_exclusive_in_warp[ITEM] = (lengths_and_num_runs[ITEM].key) ?\n                                                                lengths_and_num_runs2[ITEM].key :         // keep\n                                                                WARP_THREADS * ITEMS_PER_THREAD;            // discard\n            }\n\n            OffsetT tile_num_runs_aggregate              = tile_aggregate.key;\n            OffsetT tile_num_runs_exclusive_in_global    = 0;\n            OffsetT warp_num_runs_aggregate              = warp_aggregate.key;\n            OffsetT warp_num_runs_exclusive_in_tile      = warp_exclusive_in_tile.key;\n\n            // Scatter\n            Scatter<true>(\n                tile_num_runs_aggregate,\n                tile_num_runs_exclusive_in_global,\n                warp_num_runs_aggregate,\n                warp_num_runs_exclusive_in_tile,\n                thread_num_runs_exclusive_in_warp,\n                lengths_and_offsets);\n\n            // Return running total (inclusive of this tile)\n            return tile_aggregate;\n        }\n        else\n        {\n            // Not first tile\n\n            // Load items\n            T items[ITEMS_PER_THREAD];\n            if (LAST_TILE)\n                BlockLoadT(temp_storage.aliasable.load).Load(d_in + tile_offset, items, num_remaining, T());\n            else\n                BlockLoadT(temp_storage.aliasable.load).Load(d_in + tile_offset, items);\n\n            if (SYNC_AFTER_LOAD)\n                CTA_SYNC();\n\n            // Set flags\n            LengthOffsetPair    lengths_and_num_runs[ITEMS_PER_THREAD];\n\n            InitializeSelections<false, LAST_TILE>(\n                tile_offset,\n                num_remaining,\n                items,\n                lengths_and_num_runs);\n\n            // Exclusive scan of lengths and runs\n            LengthOffsetPair tile_aggregate;\n            LengthOffsetPair warp_aggregate;\n            LengthOffsetPair warp_exclusive_in_tile;\n            LengthOffsetPair thread_exclusive_in_warp;\n\n            WarpScanAllocations(\n                tile_aggregate,\n                warp_aggregate,\n                warp_exclusive_in_tile,\n                thread_exclusive_in_warp,\n                lengths_and_num_runs);\n\n            // First warp computes tile prefix in lane 0\n            TilePrefixCallbackOpT prefix_op(tile_status, temp_storage.aliasable.prefix, Sum(), tile_idx);\n            unsigned int warp_id = ((WARPS == 1) ? 0 : threadIdx.x / WARP_THREADS);\n            if (warp_id == 0)\n            {\n                prefix_op(tile_aggregate);\n                if (threadIdx.x == 0)\n                    temp_storage.tile_exclusive = prefix_op.exclusive_prefix;\n            }\n\n            CTA_SYNC();\n\n            LengthOffsetPair tile_exclusive_in_global = temp_storage.tile_exclusive;\n\n            // Update thread_exclusive_in_warp to fold in warp and tile run-lengths\n            LengthOffsetPair thread_exclusive = scan_op(tile_exclusive_in_global, warp_exclusive_in_tile);\n            if (thread_exclusive_in_warp.key == 0)\n                thread_exclusive_in_warp.value += thread_exclusive.value;\n\n            // Downsweep scan through lengths_and_num_runs\n            LengthOffsetPair    lengths_and_num_runs2[ITEMS_PER_THREAD];\n            LengthOffsetPair    lengths_and_offsets[ITEMS_PER_THREAD];\n            OffsetT             thread_num_runs_exclusive_in_warp[ITEMS_PER_THREAD];\n\n            internal::ThreadScanExclusive(lengths_and_num_runs, lengths_and_num_runs2, scan_op, thread_exclusive_in_warp);\n\n            // Zip\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                lengths_and_offsets[ITEM].value         = lengths_and_num_runs2[ITEM].value;\n                lengths_and_offsets[ITEM].key        = tile_offset + (threadIdx.x * ITEMS_PER_THREAD) + ITEM;\n                thread_num_runs_exclusive_in_warp[ITEM] = (lengths_and_num_runs[ITEM].key) ?\n                                                                lengths_and_num_runs2[ITEM].key :         // keep\n                                                                WARP_THREADS * ITEMS_PER_THREAD;            // discard\n            }\n\n            OffsetT tile_num_runs_aggregate              = tile_aggregate.key;\n            OffsetT tile_num_runs_exclusive_in_global    = tile_exclusive_in_global.key;\n            OffsetT warp_num_runs_aggregate              = warp_aggregate.key;\n            OffsetT warp_num_runs_exclusive_in_tile      = warp_exclusive_in_tile.key;\n\n            // Scatter\n            Scatter<false>(\n                tile_num_runs_aggregate,\n                tile_num_runs_exclusive_in_global,\n                warp_num_runs_aggregate,\n                warp_num_runs_exclusive_in_tile,\n                thread_num_runs_exclusive_in_warp,\n                lengths_and_offsets);\n\n            // Return running total (inclusive of this tile)\n            return prefix_op.inclusive_prefix;\n        }\n    }\n\n\n    /**\n     * Scan tiles of items as part of a dynamic chained scan\n     */\n    template <typename NumRunsIteratorT>            ///< Output iterator type for recording number of items selected\n    __device__ __forceinline__ void ConsumeRange(\n        int                 num_tiles,              ///< Total number of input tiles\n        ScanTileStateT&     tile_status,            ///< Global list of tile status\n        NumRunsIteratorT    d_num_runs_out)         ///< Output pointer for total number of runs identified\n    {\n        // Blocks are launched in increasing order, so just assign one tile per block\n        int     tile_idx        = (blockIdx.x * gridDim.y) + blockIdx.y;    // Current tile index\n        OffsetT tile_offset     = tile_idx * TILE_ITEMS;                  // Global offset for the current tile\n        OffsetT num_remaining   = num_items - tile_offset;                  // Remaining items (including this tile)\n\n        if (tile_idx < num_tiles - 1)\n        {\n            // Not the last tile (full)\n            ConsumeTile<false>(num_items, num_remaining, tile_idx, tile_offset, tile_status);\n        }\n        else if (num_remaining > 0)\n        {\n            // The last tile (possibly partially-full)\n            LengthOffsetPair running_total = ConsumeTile<true>(num_items, num_remaining, tile_idx, tile_offset, tile_status);\n\n            if (threadIdx.x == 0)\n            {\n                // Output the total number of items selected\n                *d_num_runs_out = running_total.key;\n\n                // The inclusive prefix contains accumulated length reduction for the last run\n                if (running_total.key > 0)\n                    d_lengths_out[running_total.key - 1] = running_total.value;\n            }\n        }\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_scan.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentScan implements a stateful abstraction of CUDA thread blocks for participating in device-wide prefix scan .\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"single_pass_scan_operators.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../grid/grid_queue.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentScan\n */\ntemplate <\n    int                         _BLOCK_THREADS,                 ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,              ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    BlockStoreAlgorithm         _STORE_ALGORITHM,               ///< The BlockStore algorithm to use\n    BlockScanAlgorithm          _SCAN_ALGORITHM>                ///< The BlockScan algorithm to use\nstruct AgentScanPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;          ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;           ///< Cache load modifier for reading input elements\n    static const BlockStoreAlgorithm    STORE_ALGORITHM         = _STORE_ALGORITHM;         ///< The BlockStore algorithm to use\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;          ///< The BlockScan algorithm to use\n};\n\n\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentScan implements a stateful abstraction of CUDA thread blocks for participating in device-wide prefix scan .\n */\ntemplate <\n    typename AgentScanPolicyT,      ///< Parameterized AgentScanPolicyT tuning policy type\n    typename InputIteratorT,        ///< Random-access input iterator type\n    typename OutputIteratorT,       ///< Random-access output iterator type\n    typename ScanOpT,               ///< Scan functor type\n    typename InitValueT,            ///< The init_value element for ScanOpT type (cub::NullType for inclusive scan)\n    typename OffsetT>               ///< Signed integer type for global offsets\nstruct AgentScan\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Tile status descriptor interface type\n    typedef ScanTileState<OutputT> ScanTileStateT;\n\n    // Input iterator wrapper type (for applying cache modifier)\n    typedef typename If<IsPointer<InputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentScanPolicyT::LOAD_MODIFIER, InputT, OffsetT>,   // Wrap the native input pointer with CacheModifiedInputIterator\n            InputIteratorT>::Type                                                           // Directly use the supplied input iterator type\n        WrappedInputIteratorT;\n\n    // Constants\n    enum\n    {\n        IS_INCLUSIVE        = Equals<InitValueT, NullType>::VALUE,            // Inclusive scan if no init_value type is provided\n        BLOCK_THREADS       = AgentScanPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = AgentScanPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    // Parameterized BlockLoad type\n    typedef BlockLoad<\n            OutputT,\n            AgentScanPolicyT::BLOCK_THREADS,\n            AgentScanPolicyT::ITEMS_PER_THREAD,\n            AgentScanPolicyT::LOAD_ALGORITHM>\n        BlockLoadT;\n\n    // Parameterized BlockStore type\n    typedef BlockStore<\n            OutputT,\n            AgentScanPolicyT::BLOCK_THREADS,\n            AgentScanPolicyT::ITEMS_PER_THREAD,\n            AgentScanPolicyT::STORE_ALGORITHM>\n        BlockStoreT;\n\n    // Parameterized BlockScan type\n    typedef BlockScan<\n            OutputT,\n            AgentScanPolicyT::BLOCK_THREADS,\n            AgentScanPolicyT::SCAN_ALGORITHM>\n        BlockScanT;\n\n    // Callback type for obtaining tile prefix during block scan\n    typedef TilePrefixCallbackOp<\n            OutputT,\n            ScanOpT,\n            ScanTileStateT>\n        TilePrefixCallbackOpT;\n\n    // Stateful BlockScan prefix callback type for managing a running total while scanning consecutive tiles\n    typedef BlockScanRunningPrefixOp<\n            OutputT,\n            ScanOpT>\n        RunningPrefixCallbackOp;\n\n    // Shared memory type for this thread block\n    union _TempStorage\n    {\n        typename BlockLoadT::TempStorage    load;       // Smem needed for tile loading\n        typename BlockStoreT::TempStorage   store;      // Smem needed for tile storing\n\n        struct\n        {\n            typename TilePrefixCallbackOpT::TempStorage  prefix;     // Smem needed for cooperative prefix callback\n            typename BlockScanT::TempStorage             scan;       // Smem needed for tile scanning\n        };\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&               temp_storage;       ///< Reference to temp_storage\n    WrappedInputIteratorT       d_in;               ///< Input data\n    OutputIteratorT             d_out;              ///< Output data\n    ScanOpT                     scan_op;            ///< Binary scan operator\n    InitValueT                  init_value;         ///< The init_value element for ScanOpT\n\n\n    //---------------------------------------------------------------------\n    // Block scan utility methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Exclusive scan specialization (first tile)\n     */\n    __device__ __forceinline__\n    void ScanTile(\n        OutputT             (&items)[ITEMS_PER_THREAD],\n        OutputT             init_value,\n        ScanOpT             scan_op,\n        OutputT             &block_aggregate,\n        Int2Type<false>     /*is_inclusive*/)\n    {\n        BlockScanT(temp_storage.scan).ExclusiveScan(items, items, init_value, scan_op, block_aggregate);\n        block_aggregate = scan_op(init_value, block_aggregate);\n    }\n\n\n    /**\n     * Inclusive scan specialization (first tile)\n     */\n    __device__ __forceinline__\n    void ScanTile(\n        OutputT             (&items)[ITEMS_PER_THREAD],\n        InitValueT          /*init_value*/,\n        ScanOpT             scan_op,\n        OutputT             &block_aggregate,\n        Int2Type<true>      /*is_inclusive*/)\n    {\n        BlockScanT(temp_storage.scan).InclusiveScan(items, items, scan_op, block_aggregate);\n    }\n\n\n    /**\n     * Exclusive scan specialization (subsequent tiles)\n     */\n    template <typename PrefixCallback>\n    __device__ __forceinline__\n    void ScanTile(\n        OutputT             (&items)[ITEMS_PER_THREAD],\n        ScanOpT             scan_op,\n        PrefixCallback      &prefix_op,\n        Int2Type<false>     /*is_inclusive*/)\n    {\n        BlockScanT(temp_storage.scan).ExclusiveScan(items, items, scan_op, prefix_op);\n    }\n\n\n    /**\n     * Inclusive scan specialization (subsequent tiles)\n     */\n    template <typename PrefixCallback>\n    __device__ __forceinline__\n    void ScanTile(\n        OutputT             (&items)[ITEMS_PER_THREAD],\n        ScanOpT             scan_op,\n        PrefixCallback      &prefix_op,\n        Int2Type<true>      /*is_inclusive*/)\n    {\n        BlockScanT(temp_storage.scan).InclusiveScan(items, items, scan_op, prefix_op);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    // Constructor\n    __device__ __forceinline__\n    AgentScan(\n        TempStorage&    temp_storage,       ///< Reference to temp_storage\n        InputIteratorT  d_in,               ///< Input data\n        OutputIteratorT d_out,              ///< Output data\n        ScanOpT         scan_op,            ///< Binary scan operator\n        InitValueT      init_value)         ///< Initial value to seed the exclusive scan\n    :\n        temp_storage(temp_storage.Alias()),\n        d_in(d_in),\n        d_out(d_out),\n        scan_op(scan_op),\n        init_value(init_value)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Cooperatively scan a device-wide sequence of tiles with other CTAs\n    //---------------------------------------------------------------------\n\n    /**\n     * Process a tile of input (dynamic chained scan)\n     */\n    template <bool IS_LAST_TILE>                ///< Whether the current tile is the last tile\n    __device__ __forceinline__ void ConsumeTile(\n        OffsetT             num_remaining,      ///< Number of global input items remaining (including this tile)\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        // Load items\n        OutputT items[ITEMS_PER_THREAD];\n\n        if (IS_LAST_TILE)\n            BlockLoadT(temp_storage.load).Load(d_in + tile_offset, items, num_remaining);\n        else\n            BlockLoadT(temp_storage.load).Load(d_in + tile_offset, items);\n\n        CTA_SYNC();\n\n        // Perform tile scan\n        if (tile_idx == 0)\n        {\n            // Scan first tile\n            OutputT block_aggregate;\n            ScanTile(items, init_value, scan_op, block_aggregate, Int2Type<IS_INCLUSIVE>());\n            if ((!IS_LAST_TILE) && (threadIdx.x == 0))\n                tile_state.SetInclusive(0, block_aggregate);\n        }\n        else\n        {\n            // Scan non-first tile\n            TilePrefixCallbackOpT prefix_op(tile_state, temp_storage.prefix, scan_op, tile_idx);\n            ScanTile(items, scan_op, prefix_op, Int2Type<IS_INCLUSIVE>());\n        }\n\n        CTA_SYNC();\n\n        // Store items\n        if (IS_LAST_TILE)\n            BlockStoreT(temp_storage.store).Store(d_out + tile_offset, items, num_remaining);\n        else\n            BlockStoreT(temp_storage.store).Store(d_out + tile_offset, items);\n    }\n\n\n    /**\n     * Scan tiles of items as part of a dynamic chained scan\n     */\n    __device__ __forceinline__ void ConsumeRange(\n        int                 num_items,          ///< Total number of input items\n        ScanTileStateT&     tile_state,         ///< Global tile state descriptor\n        int                 start_tile)         ///< The starting tile for the current grid\n    {\n        // Blocks are launched in increasing order, so just assign one tile per block\n        int     tile_idx        = start_tile + blockIdx.x;          // Current tile index\n        OffsetT tile_offset     = OffsetT(TILE_ITEMS) * tile_idx;   // Global offset for the current tile\n        OffsetT num_remaining   = num_items - tile_offset;          // Remaining items (including this tile)\n\n        if (num_remaining > TILE_ITEMS)\n        {\n            // Not last tile\n            ConsumeTile<false>(num_remaining, tile_idx, tile_offset, tile_state);\n        }\n        else if (num_remaining > 0)\n        {\n            // Last tile\n            ConsumeTile<true>(num_remaining, tile_idx, tile_offset, tile_state);\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Scan an sequence of consecutive tiles (independent of other thread blocks)\n    //---------------------------------------------------------------------\n\n    /**\n     * Process a tile of input\n     */\n    template <\n        bool                        IS_FIRST_TILE,\n        bool                        IS_LAST_TILE>\n    __device__ __forceinline__ void ConsumeTile(\n        OffsetT                     tile_offset,                ///< Tile offset\n        RunningPrefixCallbackOp&    prefix_op,                  ///< Running prefix operator\n        int                         valid_items = TILE_ITEMS)   ///< Number of valid items in the tile\n    {\n        // Load items\n        OutputT items[ITEMS_PER_THREAD];\n\n        if (IS_LAST_TILE)\n            BlockLoadT(temp_storage.load).Load(d_in + tile_offset, items, valid_items);\n        else\n            BlockLoadT(temp_storage.load).Load(d_in + tile_offset, items);\n\n        CTA_SYNC();\n\n        // Block scan\n        if (IS_FIRST_TILE)\n        {\n            OutputT block_aggregate;\n            ScanTile(items, init_value, scan_op, block_aggregate, Int2Type<IS_INCLUSIVE>());\n            prefix_op.running_total = block_aggregate;\n        }\n        else\n        {\n            ScanTile(items, scan_op, prefix_op, Int2Type<IS_INCLUSIVE>());\n        }\n\n        CTA_SYNC();\n\n        // Store items\n        if (IS_LAST_TILE)\n            BlockStoreT(temp_storage.store).Store(d_out + tile_offset, items, valid_items);\n        else\n            BlockStoreT(temp_storage.store).Store(d_out + tile_offset, items);\n    }\n\n\n    /**\n     * Scan a consecutive share of input tiles\n     */\n    __device__ __forceinline__ void ConsumeRange(\n        OffsetT  range_offset,      ///< [in] Threadblock begin offset (inclusive)\n        OffsetT  range_end)         ///< [in] Threadblock end offset (exclusive)\n    {\n        BlockScanRunningPrefixOp<OutputT, ScanOpT> prefix_op(scan_op);\n\n        if (range_offset + TILE_ITEMS <= range_end)\n        {\n            // Consume first tile of input (full)\n            ConsumeTile<true, true>(range_offset, prefix_op);\n            range_offset += TILE_ITEMS;\n\n            // Consume subsequent full tiles of input\n            while (range_offset + TILE_ITEMS <= range_end)\n            {\n                ConsumeTile<false, true>(range_offset, prefix_op);\n                range_offset += TILE_ITEMS;\n            }\n\n            // Consume a partially-full tile\n            if (range_offset < range_end)\n            {\n                int valid_items = range_end - range_offset;\n                ConsumeTile<false, false>(range_offset, prefix_op, valid_items);\n            }\n        }\n        else\n        {\n            // Consume the first tile of input (partially-full)\n            int valid_items = range_end - range_offset;\n            ConsumeTile<true, false>(range_offset, prefix_op, valid_items);\n        }\n    }\n\n\n    /**\n     * Scan a consecutive share of input tiles, seeded with the specified prefix value\n     */\n    __device__ __forceinline__ void ConsumeRange(\n        OffsetT range_offset,                       ///< [in] Threadblock begin offset (inclusive)\n        OffsetT range_end,                          ///< [in] Threadblock end offset (exclusive)\n        OutputT prefix)                             ///< [in] The prefix to apply to the scan segment\n    {\n        BlockScanRunningPrefixOp<OutputT, ScanOpT> prefix_op(prefix, scan_op);\n\n        // Consume full tiles of input\n        while (range_offset + TILE_ITEMS <= range_end)\n        {\n            ConsumeTile<true, false>(range_offset, prefix_op);\n            range_offset += TILE_ITEMS;\n        }\n\n        // Consume a partially-full tile\n        if (range_offset < range_end)\n        {\n            int valid_items = range_end - range_offset;\n            ConsumeTile<false, false>(range_offset, prefix_op, valid_items);\n        }\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_segment_fixup.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentSegmentFixup implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduce-value-by-key.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"single_pass_scan_operators.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../block/block_discontinuity.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../iterator/constant_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentSegmentFixup\n */\ntemplate <\n    int                         _BLOCK_THREADS,                 ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,              ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    BlockScanAlgorithm          _SCAN_ALGORITHM>                ///< The BlockScan algorithm to use\nstruct AgentSegmentFixupPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;      ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;      ///< The BlockScan algorithm to use\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n/**\n * \\brief AgentSegmentFixup implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduce-value-by-key\n */\ntemplate <\n    typename    AgentSegmentFixupPolicyT,       ///< Parameterized AgentSegmentFixupPolicy tuning policy type\n    typename    PairsInputIteratorT,            ///< Random-access input iterator type for keys\n    typename    AggregatesOutputIteratorT,      ///< Random-access output iterator type for values\n    typename    EqualityOpT,                    ///< KeyT equality operator type\n    typename    ReductionOpT,                   ///< ValueT reduction operator type\n    typename    OffsetT>                        ///< Signed integer type for global offsets\nstruct AgentSegmentFixup\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // Data type of key-value input iterator\n    typedef typename std::iterator_traits<PairsInputIteratorT>::value_type KeyValuePairT;\n\n    // Value type\n    typedef typename KeyValuePairT::Value ValueT;\n\n    // Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<ValueT, OffsetT> ScanTileStateT;\n\n    // Constants\n    enum\n    {\n        BLOCK_THREADS       = AgentSegmentFixupPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = AgentSegmentFixupPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n\n        // Whether or not do fixup using RLE + global atomics\n        USE_ATOMIC_FIXUP    = (CUB_PTX_ARCH >= 350) && \n                                (Equals<ValueT, float>::VALUE || \n                                 Equals<ValueT, int>::VALUE ||\n                                 Equals<ValueT, unsigned int>::VALUE ||\n                                 Equals<ValueT, unsigned long long>::VALUE),\n\n        // Whether or not the scan operation has a zero-valued identity value (true if we're performing addition on a primitive type)\n        HAS_IDENTITY_ZERO   = (Equals<ReductionOpT, cub::Sum>::VALUE) && (Traits<ValueT>::PRIMITIVE),\n    };\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for keys\n    typedef typename If<IsPointer<PairsInputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentSegmentFixupPolicyT::LOAD_MODIFIER, KeyValuePairT, OffsetT>,    // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            PairsInputIteratorT>::Type                                                                      // Directly use the supplied input iterator type\n        WrappedPairsInputIteratorT;\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for fixup values\n    typedef typename If<IsPointer<AggregatesOutputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentSegmentFixupPolicyT::LOAD_MODIFIER, ValueT, OffsetT>,    // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            AggregatesOutputIteratorT>::Type                                                        // Directly use the supplied input iterator type\n        WrappedFixupInputIteratorT;\n\n    // Reduce-value-by-segment scan operator\n    typedef ReduceByKeyOp<cub::Sum> ReduceBySegmentOpT;\n\n    // Parameterized BlockLoad type for pairs\n    typedef BlockLoad<\n            KeyValuePairT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            AgentSegmentFixupPolicyT::LOAD_ALGORITHM>\n        BlockLoadPairs;\n\n    // Parameterized BlockScan type\n    typedef BlockScan<\n            KeyValuePairT,\n            BLOCK_THREADS,\n            AgentSegmentFixupPolicyT::SCAN_ALGORITHM>\n        BlockScanT;\n\n    // Callback type for obtaining tile prefix during block scan\n    typedef TilePrefixCallbackOp<\n            KeyValuePairT,\n            ReduceBySegmentOpT,\n            ScanTileStateT>\n        TilePrefixCallbackOpT;\n\n    // Shared memory type for this thread block\n    union _TempStorage\n    {\n        struct\n        {\n            typename BlockScanT::TempStorage                scan;           // Smem needed for tile scanning\n            typename TilePrefixCallbackOpT::TempStorage     prefix;         // Smem needed for cooperative prefix callback\n        };\n\n        // Smem needed for loading keys\n        typename BlockLoadPairs::TempStorage load_pairs;\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&                   temp_storage;       ///< Reference to temp_storage\n    WrappedPairsInputIteratorT      d_pairs_in;          ///< Input keys\n    AggregatesOutputIteratorT       d_aggregates_out;   ///< Output value aggregates\n    WrappedFixupInputIteratorT      d_fixup_in;         ///< Fixup input values\n    InequalityWrapper<EqualityOpT>  inequality_op;      ///< KeyT inequality operator\n    ReductionOpT                    reduction_op;       ///< Reduction operator\n    ReduceBySegmentOpT              scan_op;            ///< Reduce-by-segment scan operator\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    // Constructor\n    __device__ __forceinline__\n    AgentSegmentFixup(\n        TempStorage&                temp_storage,       ///< Reference to temp_storage\n        PairsInputIteratorT         d_pairs_in,          ///< Input keys\n        AggregatesOutputIteratorT   d_aggregates_out,   ///< Output value aggregates\n        EqualityOpT                 equality_op,        ///< KeyT equality operator\n        ReductionOpT                reduction_op)       ///< ValueT reduction operator\n    :\n        temp_storage(temp_storage.Alias()),\n        d_pairs_in(d_pairs_in),\n        d_aggregates_out(d_aggregates_out),\n        d_fixup_in(d_aggregates_out),\n        inequality_op(equality_op),\n        reduction_op(reduction_op),\n        scan_op(reduction_op)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Cooperatively scan a device-wide sequence of tiles with other CTAs\n    //---------------------------------------------------------------------\n\n\n    /**\n     * Process input tile.  Specialized for atomic-fixup\n     */\n    template <bool IS_LAST_TILE>\n    __device__ __forceinline__ void ConsumeTile(\n        OffsetT             num_remaining,      ///< Number of global input items remaining (including this tile)\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state,         ///< Global tile state descriptor\n        Int2Type<true>      use_atomic_fixup)   ///< Marker whether to use atomicAdd (instead of reduce-by-key)\n    {\n        KeyValuePairT   pairs[ITEMS_PER_THREAD];\n\n        // Load pairs\n        KeyValuePairT oob_pair;\n        oob_pair.key = -1;\n\n        if (IS_LAST_TILE)\n            BlockLoadPairs(temp_storage.load_pairs).Load(d_pairs_in + tile_offset, pairs, num_remaining, oob_pair);\n        else\n            BlockLoadPairs(temp_storage.load_pairs).Load(d_pairs_in + tile_offset, pairs);\n\n        // RLE \n        #pragma unroll\n        for (int ITEM = 1; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            ValueT* d_scatter = d_aggregates_out + pairs[ITEM - 1].key;\n            if (pairs[ITEM].key != pairs[ITEM - 1].key)\n                atomicAdd(d_scatter, pairs[ITEM - 1].value);\n            else\n                pairs[ITEM].value = reduction_op(pairs[ITEM - 1].value, pairs[ITEM].value);\n        }\n\n        // Flush last item if valid\n        ValueT* d_scatter = d_aggregates_out + pairs[ITEMS_PER_THREAD - 1].key;\n        if ((!IS_LAST_TILE) || (pairs[ITEMS_PER_THREAD - 1].key >= 0))\n            atomicAdd(d_scatter, pairs[ITEMS_PER_THREAD - 1].value);\n    }\n\n\n    /**\n     * Process input tile.  Specialized for reduce-by-key fixup\n     */\n    template <bool IS_LAST_TILE>\n    __device__ __forceinline__ void ConsumeTile(\n        OffsetT             num_remaining,      ///< Number of global input items remaining (including this tile)\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state,         ///< Global tile state descriptor\n        Int2Type<false>     use_atomic_fixup)   ///< Marker whether to use atomicAdd (instead of reduce-by-key)\n    {\n        KeyValuePairT   pairs[ITEMS_PER_THREAD];\n        KeyValuePairT   scatter_pairs[ITEMS_PER_THREAD];\n\n        // Load pairs\n        KeyValuePairT oob_pair;\n        oob_pair.key = -1;\n\n        if (IS_LAST_TILE)\n            BlockLoadPairs(temp_storage.load_pairs).Load(d_pairs_in + tile_offset, pairs, num_remaining, oob_pair);\n        else\n            BlockLoadPairs(temp_storage.load_pairs).Load(d_pairs_in + tile_offset, pairs);\n\n        CTA_SYNC();\n\n        KeyValuePairT tile_aggregate;\n        if (tile_idx == 0)\n        {\n            // Exclusive scan of values and segment_flags\n            BlockScanT(temp_storage.scan).ExclusiveScan(pairs, scatter_pairs, scan_op, tile_aggregate);\n\n            // Update tile status if this is not the last tile\n            if (threadIdx.x == 0)\n            {\n                // Set first segment id to not trigger a flush (invalid from exclusive scan)\n                scatter_pairs[0].key = pairs[0].key;\n\n                if (!IS_LAST_TILE)\n                    tile_state.SetInclusive(0, tile_aggregate);\n\n            }\n        }\n        else\n        {\n            // Exclusive scan of values and segment_flags\n            TilePrefixCallbackOpT prefix_op(tile_state, temp_storage.prefix, scan_op, tile_idx);\n            BlockScanT(temp_storage.scan).ExclusiveScan(pairs, scatter_pairs, scan_op, prefix_op);\n            tile_aggregate = prefix_op.GetBlockAggregate();\n        }\n\n        // Scatter updated values\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (scatter_pairs[ITEM].key != pairs[ITEM].key)\n            {\n                // Update the value at the key location\n                ValueT value    = d_fixup_in[scatter_pairs[ITEM].key];\n                value           = reduction_op(value, scatter_pairs[ITEM].value);\n\n                d_aggregates_out[scatter_pairs[ITEM].key] = value;\n            }\n        }\n\n        // Finalize the last item\n        if (IS_LAST_TILE)\n        {\n            // Last thread will output final count and last item, if necessary\n            if (threadIdx.x == BLOCK_THREADS - 1)\n            {\n                // If the last tile is a whole tile, the inclusive prefix contains accumulated value reduction for the last segment\n                if (num_remaining == TILE_ITEMS)\n                {\n                    // Update the value at the key location\n                    OffsetT last_key = pairs[ITEMS_PER_THREAD - 1].key;\n                    d_aggregates_out[last_key] = reduction_op(tile_aggregate.value, d_fixup_in[last_key]);\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Scan tiles of items as part of a dynamic chained scan\n     */\n    __device__ __forceinline__ void ConsumeRange(\n        int                 num_items,          ///< Total number of input items\n        int                 num_tiles,          ///< Total number of input tiles\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        // Blocks are launched in increasing order, so just assign one tile per block\n        int     tile_idx        = (blockIdx.x * gridDim.y) + blockIdx.y;    // Current tile index\n        OffsetT tile_offset     = tile_idx * TILE_ITEMS;                    // Global offset for the current tile\n        OffsetT num_remaining   = num_items - tile_offset;                  // Remaining items (including this tile)\n\n        if (num_remaining > TILE_ITEMS)\n        {\n            // Not the last tile (full)\n            ConsumeTile<false>(num_remaining, tile_idx, tile_offset, tile_state, Int2Type<USE_ATOMIC_FIXUP>());\n        }\n        else if (num_remaining > 0)\n        {\n            // The last tile (possibly partially-full)\n            ConsumeTile<true>(num_remaining, tile_idx, tile_offset, tile_state, Int2Type<USE_ATOMIC_FIXUP>());\n        }\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_select_if.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentSelectIf implements a stateful abstraction of CUDA thread blocks for participating in device-wide select.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"single_pass_scan_operators.cuh\"\n#include \"../block/block_load.cuh\"\n#include \"../block/block_store.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../block/block_exchange.cuh\"\n#include \"../block/block_discontinuity.cuh\"\n#include \"../grid/grid_queue.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentSelectIf\n */\ntemplate <\n    int                         _BLOCK_THREADS,                 ///< Threads per thread block\n    int                         _ITEMS_PER_THREAD,              ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm          _LOAD_ALGORITHM,                ///< The BlockLoad algorithm to use\n    CacheLoadModifier           _LOAD_MODIFIER,                 ///< Cache load modifier for reading input elements\n    BlockScanAlgorithm          _SCAN_ALGORITHM>                ///< The BlockScan algorithm to use\nstruct AgentSelectIfPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;      ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;      ///< The BlockScan algorithm to use\n};\n\n\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\n\n/**\n * \\brief AgentSelectIf implements a stateful abstraction of CUDA thread blocks for participating in device-wide selection\n *\n * Performs functor-based selection if SelectOpT functor type != NullType\n * Otherwise performs flag-based selection if FlagsInputIterator's value type != NullType\n * Otherwise performs discontinuity selection (keep unique)\n */\ntemplate <\n    typename    AgentSelectIfPolicyT,           ///< Parameterized AgentSelectIfPolicy tuning policy type\n    typename    InputIteratorT,                 ///< Random-access input iterator type for selection items\n    typename    FlagsInputIteratorT,            ///< Random-access input iterator type for selections (NullType* if a selection functor or discontinuity flagging is to be used for selection)\n    typename    SelectedOutputIteratorT,        ///< Random-access input iterator type for selection_flags items\n    typename    SelectOpT,                      ///< Selection operator type (NullType if selections or discontinuity flagging is to be used for selection)\n    typename    EqualityOpT,                    ///< Equality operator type (NullType if selection functor or selections is to be used for selection)\n    typename    OffsetT,                        ///< Signed integer type for global offsets\n    bool        KEEP_REJECTS>                   ///< Whether or not we push rejected items to the back of the output\nstruct AgentSelectIf\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<SelectedOutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                                  // ... then the input iterator's value type,\n        typename std::iterator_traits<SelectedOutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // The flag value type\n    typedef typename std::iterator_traits<FlagsInputIteratorT>::value_type FlagT;\n\n    // Tile status descriptor interface type\n    typedef ScanTileState<OffsetT> ScanTileStateT;\n\n    // Constants\n    enum\n    {\n        USE_SELECT_OP,\n        USE_SELECT_FLAGS,\n        USE_DISCONTINUITY,\n\n        BLOCK_THREADS           = AgentSelectIfPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = AgentSelectIfPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS              = BLOCK_THREADS * ITEMS_PER_THREAD,\n        TWO_PHASE_SCATTER       = (ITEMS_PER_THREAD > 1),\n\n        SELECT_METHOD           = (!Equals<SelectOpT, NullType>::VALUE) ?\n                                    USE_SELECT_OP :\n                                    (!Equals<FlagT, NullType>::VALUE) ?\n                                        USE_SELECT_FLAGS :\n                                        USE_DISCONTINUITY\n    };\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for items\n    typedef typename If<IsPointer<InputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentSelectIfPolicyT::LOAD_MODIFIER, InputT, OffsetT>,        // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            InputIteratorT>::Type                                                               // Directly use the supplied input iterator type\n        WrappedInputIteratorT;\n\n    // Cache-modified Input iterator wrapper type (for applying cache modifier) for values\n    typedef typename If<IsPointer<FlagsInputIteratorT>::VALUE,\n            CacheModifiedInputIterator<AgentSelectIfPolicyT::LOAD_MODIFIER, FlagT, OffsetT>,    // Wrap the native input pointer with CacheModifiedValuesInputIterator\n            FlagsInputIteratorT>::Type                                                          // Directly use the supplied input iterator type\n        WrappedFlagsInputIteratorT;\n\n    // Parameterized BlockLoad type for input data\n    typedef BlockLoad<\n            OutputT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            AgentSelectIfPolicyT::LOAD_ALGORITHM>\n        BlockLoadT;\n\n    // Parameterized BlockLoad type for flags\n    typedef BlockLoad<\n            FlagT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            AgentSelectIfPolicyT::LOAD_ALGORITHM>\n        BlockLoadFlags;\n\n    // Parameterized BlockDiscontinuity type for items\n    typedef BlockDiscontinuity<\n            OutputT,\n            BLOCK_THREADS>\n        BlockDiscontinuityT;\n\n    // Parameterized BlockScan type\n    typedef BlockScan<\n            OffsetT,\n            BLOCK_THREADS,\n            AgentSelectIfPolicyT::SCAN_ALGORITHM>\n        BlockScanT;\n\n    // Callback type for obtaining tile prefix during block scan\n    typedef TilePrefixCallbackOp<\n            OffsetT,\n            cub::Sum,\n            ScanTileStateT>\n        TilePrefixCallbackOpT;\n\n    // Item exchange type\n    typedef OutputT ItemExchangeT[TILE_ITEMS];\n\n    // Shared memory type for this thread block\n    union _TempStorage\n    {\n        struct\n        {\n            typename BlockScanT::TempStorage                scan;           // Smem needed for tile scanning\n            typename TilePrefixCallbackOpT::TempStorage     prefix;         // Smem needed for cooperative prefix callback\n            typename BlockDiscontinuityT::TempStorage       discontinuity;  // Smem needed for discontinuity detection\n        };\n\n        // Smem needed for loading items\n        typename BlockLoadT::TempStorage load_items;\n\n        // Smem needed for loading values\n        typename BlockLoadFlags::TempStorage load_flags;\n\n        // Smem needed for compacting items (allows non POD items in this union)\n        Uninitialized<ItemExchangeT> raw_exchange;\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage&                   temp_storage;       ///< Reference to temp_storage\n    WrappedInputIteratorT           d_in;               ///< Input items\n    SelectedOutputIteratorT         d_selected_out;     ///< Unique output items\n    WrappedFlagsInputIteratorT      d_flags_in;         ///< Input selection flags (if applicable)\n    InequalityWrapper<EqualityOpT>  inequality_op;      ///< T inequality operator\n    SelectOpT                       select_op;          ///< Selection operator\n    OffsetT                         num_items;          ///< Total number of input items\n\n\n    //---------------------------------------------------------------------\n    // Constructor\n    //---------------------------------------------------------------------\n\n    // Constructor\n    __device__ __forceinline__\n    AgentSelectIf(\n        TempStorage                 &temp_storage,      ///< Reference to temp_storage\n        InputIteratorT              d_in,               ///< Input data\n        FlagsInputIteratorT         d_flags_in,         ///< Input selection flags (if applicable)\n        SelectedOutputIteratorT     d_selected_out,     ///< Output data\n        SelectOpT                   select_op,          ///< Selection operator\n        EqualityOpT                 equality_op,        ///< Equality operator\n        OffsetT                     num_items)          ///< Total number of input items\n    :\n        temp_storage(temp_storage.Alias()),\n        d_in(d_in),\n        d_flags_in(d_flags_in),\n        d_selected_out(d_selected_out),\n        select_op(select_op),\n        inequality_op(equality_op),\n        num_items(num_items)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Utility methods for initializing the selections\n    //---------------------------------------------------------------------\n\n    /**\n     * Initialize selections (specialized for selection operator)\n     */\n    template <bool IS_FIRST_TILE, bool IS_LAST_TILE>\n    __device__ __forceinline__ void InitializeSelections(\n        OffsetT                     /*tile_offset*/,\n        OffsetT                     num_tile_items,\n        OutputT                     (&items)[ITEMS_PER_THREAD],\n        OffsetT                     (&selection_flags)[ITEMS_PER_THREAD],\n        Int2Type<USE_SELECT_OP>     /*select_method*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            // Out-of-bounds items are selection_flags\n            selection_flags[ITEM] = 1;\n\n            if (!IS_LAST_TILE || (OffsetT(threadIdx.x * ITEMS_PER_THREAD) + ITEM < num_tile_items))\n                selection_flags[ITEM] = select_op(items[ITEM]);\n        }\n    }\n\n\n    /**\n     * Initialize selections (specialized for valid flags)\n     */\n    template <bool IS_FIRST_TILE, bool IS_LAST_TILE>\n    __device__ __forceinline__ void InitializeSelections(\n        OffsetT                     tile_offset,\n        OffsetT                     num_tile_items,\n        OutputT                     (&/*items*/)[ITEMS_PER_THREAD],\n        OffsetT                     (&selection_flags)[ITEMS_PER_THREAD],\n        Int2Type<USE_SELECT_FLAGS>  /*select_method*/)\n    {\n        CTA_SYNC();\n\n        FlagT flags[ITEMS_PER_THREAD];\n\n        if (IS_LAST_TILE)\n        {\n            // Out-of-bounds items are selection_flags\n            BlockLoadFlags(temp_storage.load_flags).Load(d_flags_in + tile_offset, flags, num_tile_items, 1);\n        }\n        else\n        {\n            BlockLoadFlags(temp_storage.load_flags).Load(d_flags_in + tile_offset, flags);\n        }\n\n        // Convert flag type to selection_flags type\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            selection_flags[ITEM] = flags[ITEM];\n        }\n    }\n\n\n    /**\n     * Initialize selections (specialized for discontinuity detection)\n     */\n    template <bool IS_FIRST_TILE, bool IS_LAST_TILE>\n    __device__ __forceinline__ void InitializeSelections(\n        OffsetT                     tile_offset,\n        OffsetT                     num_tile_items,\n        OutputT                     (&items)[ITEMS_PER_THREAD],\n        OffsetT                     (&selection_flags)[ITEMS_PER_THREAD],\n        Int2Type<USE_DISCONTINUITY> /*select_method*/)\n    {\n        if (IS_FIRST_TILE)\n        {\n            CTA_SYNC();\n\n            // Set head selection_flags.  First tile sets the first flag for the first item\n            BlockDiscontinuityT(temp_storage.discontinuity).FlagHeads(selection_flags, items, inequality_op);\n        }\n        else\n        {\n            OutputT tile_predecessor;\n            if (threadIdx.x == 0)\n                tile_predecessor = d_in[tile_offset - 1];\n\n            CTA_SYNC();\n\n            BlockDiscontinuityT(temp_storage.discontinuity).FlagHeads(selection_flags, items, inequality_op, tile_predecessor);\n        }\n\n        // Set selection flags for out-of-bounds items\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            // Set selection_flags for out-of-bounds items\n            if ((IS_LAST_TILE) && (OffsetT(threadIdx.x * ITEMS_PER_THREAD) + ITEM >= num_tile_items))\n                selection_flags[ITEM] = 1;\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Scatter utility methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Scatter flagged items to output offsets (specialized for direct scattering)\n     */\n    template <bool IS_LAST_TILE, bool IS_FIRST_TILE>\n    __device__ __forceinline__ void ScatterDirect(\n        OutputT (&items)[ITEMS_PER_THREAD],\n        OffsetT (&selection_flags)[ITEMS_PER_THREAD],\n        OffsetT (&selection_indices)[ITEMS_PER_THREAD],\n        OffsetT num_selections)\n    {\n        // Scatter flagged items\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (selection_flags[ITEM])\n            {\n                if ((!IS_LAST_TILE) || selection_indices[ITEM] < num_selections)\n                {\n                    d_selected_out[selection_indices[ITEM]] = items[ITEM];\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Scatter flagged items to output offsets (specialized for two-phase scattering)\n     */\n    template <bool IS_LAST_TILE, bool IS_FIRST_TILE>\n    __device__ __forceinline__ void ScatterTwoPhase(\n        OutputT         (&items)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_indices)[ITEMS_PER_THREAD],\n        int             /*num_tile_items*/,                         ///< Number of valid items in this tile\n        int             num_tile_selections,                        ///< Number of selections in this tile\n        OffsetT         num_selections_prefix,                      ///< Total number of selections prior to this tile\n        OffsetT         /*num_rejected_prefix*/,                    ///< Total number of rejections prior to this tile\n        Int2Type<false> /*is_keep_rejects*/)                        ///< Marker type indicating whether to keep rejected items in the second partition\n    {\n        CTA_SYNC();\n\n        // Compact and scatter items\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int local_scatter_offset = selection_indices[ITEM] - num_selections_prefix;\n            if (selection_flags[ITEM])\n            {\n                temp_storage.raw_exchange.Alias()[local_scatter_offset] = items[ITEM];\n            }\n        }\n\n        CTA_SYNC();\n\n        for (int item = threadIdx.x; item < num_tile_selections; item += BLOCK_THREADS)\n        {\n            d_selected_out[num_selections_prefix + item] = temp_storage.raw_exchange.Alias()[item];\n        }\n    }\n\n\n    /**\n     * Scatter flagged items to output offsets (specialized for two-phase scattering)\n     */\n    template <bool IS_LAST_TILE, bool IS_FIRST_TILE>\n    __device__ __forceinline__ void ScatterTwoPhase(\n        OutputT         (&items)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_indices)[ITEMS_PER_THREAD],\n        int             num_tile_items,                             ///< Number of valid items in this tile\n        int             num_tile_selections,                        ///< Number of selections in this tile\n        OffsetT         num_selections_prefix,                      ///< Total number of selections prior to this tile\n        OffsetT         num_rejected_prefix,                        ///< Total number of rejections prior to this tile\n        Int2Type<true>  /*is_keep_rejects*/)                        ///< Marker type indicating whether to keep rejected items in the second partition\n    {\n        CTA_SYNC();\n\n        int tile_num_rejections = num_tile_items - num_tile_selections;\n\n        // Scatter items to shared memory (rejections first)\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int item_idx                = (threadIdx.x * ITEMS_PER_THREAD) + ITEM;\n            int local_selection_idx     = selection_indices[ITEM] - num_selections_prefix;\n            int local_rejection_idx     = item_idx - local_selection_idx;\n            int local_scatter_offset    = (selection_flags[ITEM]) ?\n                                            tile_num_rejections + local_selection_idx :\n                                            local_rejection_idx;\n\n            temp_storage.raw_exchange.Alias()[local_scatter_offset] = items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        // Gather items from shared memory and scatter to global\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int item_idx            = (ITEM * BLOCK_THREADS) + threadIdx.x;\n            int rejection_idx       = item_idx;\n            int selection_idx       = item_idx - tile_num_rejections;\n            OffsetT scatter_offset  = (item_idx < tile_num_rejections) ?\n                                        num_items - num_rejected_prefix - rejection_idx - 1 :\n                                        num_selections_prefix + selection_idx;\n\n            OutputT item = temp_storage.raw_exchange.Alias()[item_idx];\n\n            if (!IS_LAST_TILE || (item_idx < num_tile_items))\n            {\n                d_selected_out[scatter_offset] = item;\n            }\n        }\n    }\n\n\n    /**\n     * Scatter flagged items\n     */\n    template <bool IS_LAST_TILE, bool IS_FIRST_TILE>\n    __device__ __forceinline__ void Scatter(\n        OutputT         (&items)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_flags)[ITEMS_PER_THREAD],\n        OffsetT         (&selection_indices)[ITEMS_PER_THREAD],\n        int             num_tile_items,                             ///< Number of valid items in this tile\n        int             num_tile_selections,                        ///< Number of selections in this tile\n        OffsetT         num_selections_prefix,                      ///< Total number of selections prior to this tile\n        OffsetT         num_rejected_prefix,                        ///< Total number of rejections prior to this tile\n        OffsetT         num_selections)                             ///< Total number of selections including this tile\n    {\n        // Do a two-phase scatter if (a) keeping both partitions or (b) two-phase is enabled and the average number of selection_flags items per thread is greater than one\n        if (KEEP_REJECTS || (TWO_PHASE_SCATTER && (num_tile_selections > BLOCK_THREADS)))\n        {\n            ScatterTwoPhase<IS_LAST_TILE, IS_FIRST_TILE>(\n                items,\n                selection_flags,\n                selection_indices,\n                num_tile_items,\n                num_tile_selections,\n                num_selections_prefix,\n                num_rejected_prefix,\n                Int2Type<KEEP_REJECTS>());\n        }\n        else\n        {\n            ScatterDirect<IS_LAST_TILE, IS_FIRST_TILE>(\n                items,\n                selection_flags,\n                selection_indices,\n                num_selections);\n        }\n    }\n\n    //---------------------------------------------------------------------\n    // Cooperatively scan a device-wide sequence of tiles with other CTAs\n    //---------------------------------------------------------------------\n\n\n    /**\n     * Process first tile of input (dynamic chained scan).  Returns the running count of selections (including this tile)\n     */\n    template <bool IS_LAST_TILE>\n    __device__ __forceinline__ OffsetT ConsumeFirstTile(\n        int                 num_tile_items,      ///< Number of input items comprising this tile\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        OutputT     items[ITEMS_PER_THREAD];\n        OffsetT     selection_flags[ITEMS_PER_THREAD];\n        OffsetT     selection_indices[ITEMS_PER_THREAD];\n\n        // Load items\n        if (IS_LAST_TILE)\n            BlockLoadT(temp_storage.load_items).Load(d_in + tile_offset, items, num_tile_items);\n        else\n            BlockLoadT(temp_storage.load_items).Load(d_in + tile_offset, items);\n\n        // Initialize selection_flags\n        InitializeSelections<true, IS_LAST_TILE>(\n            tile_offset,\n            num_tile_items,\n            items,\n            selection_flags,\n            Int2Type<SELECT_METHOD>());\n\n        CTA_SYNC();\n\n        // Exclusive scan of selection_flags\n        OffsetT num_tile_selections;\n        BlockScanT(temp_storage.scan).ExclusiveSum(selection_flags, selection_indices, num_tile_selections);\n\n        if (threadIdx.x == 0)\n        {\n            // Update tile status if this is not the last tile\n            if (!IS_LAST_TILE)\n                tile_state.SetInclusive(0, num_tile_selections);\n        }\n\n        // Discount any out-of-bounds selections\n        if (IS_LAST_TILE)\n            num_tile_selections -= (TILE_ITEMS - num_tile_items);\n\n        // Scatter flagged items\n        Scatter<IS_LAST_TILE, true>(\n            items,\n            selection_flags,\n            selection_indices,\n            num_tile_items,\n            num_tile_selections,\n            0,\n            0,\n            num_tile_selections);\n\n        return num_tile_selections;\n    }\n\n\n    /**\n     * Process subsequent tile of input (dynamic chained scan).  Returns the running count of selections (including this tile)\n     */\n    template <bool IS_LAST_TILE>\n    __device__ __forceinline__ OffsetT ConsumeSubsequentTile(\n        int                 num_tile_items,      ///< Number of input items comprising this tile\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        OutputT     items[ITEMS_PER_THREAD];\n        OffsetT     selection_flags[ITEMS_PER_THREAD];\n        OffsetT     selection_indices[ITEMS_PER_THREAD];\n\n        // Load items\n        if (IS_LAST_TILE)\n            BlockLoadT(temp_storage.load_items).Load(d_in + tile_offset, items, num_tile_items);\n        else\n            BlockLoadT(temp_storage.load_items).Load(d_in + tile_offset, items);\n\n        // Initialize selection_flags\n        InitializeSelections<false, IS_LAST_TILE>(\n            tile_offset,\n            num_tile_items,\n            items,\n            selection_flags,\n            Int2Type<SELECT_METHOD>());\n\n        CTA_SYNC();\n\n        // Exclusive scan of values and selection_flags\n        TilePrefixCallbackOpT prefix_op(tile_state, temp_storage.prefix, cub::Sum(), tile_idx);\n        BlockScanT(temp_storage.scan).ExclusiveSum(selection_flags, selection_indices, prefix_op);\n\n        OffsetT num_tile_selections     = prefix_op.GetBlockAggregate();\n        OffsetT num_selections          = prefix_op.GetInclusivePrefix();\n        OffsetT num_selections_prefix   = prefix_op.GetExclusivePrefix();\n        OffsetT num_rejected_prefix     = (tile_idx * TILE_ITEMS) - num_selections_prefix;\n\n        // Discount any out-of-bounds selections\n        if (IS_LAST_TILE)\n        {\n            int num_discount    = TILE_ITEMS - num_tile_items;\n            num_selections      -= num_discount;\n            num_tile_selections -= num_discount;\n        }\n\n        // Scatter flagged items\n        Scatter<IS_LAST_TILE, false>(\n            items,\n            selection_flags,\n            selection_indices,\n            num_tile_items,\n            num_tile_selections,\n            num_selections_prefix,\n            num_rejected_prefix,\n            num_selections);\n\n        return num_selections;\n    }\n\n\n    /**\n     * Process a tile of input\n     */\n    template <bool IS_LAST_TILE>\n    __device__ __forceinline__ OffsetT ConsumeTile(\n        int                 num_tile_items,         ///< Number of input items comprising this tile\n        int                 tile_idx,           ///< Tile index\n        OffsetT             tile_offset,        ///< Tile offset\n        ScanTileStateT&     tile_state)         ///< Global tile state descriptor\n    {\n        OffsetT num_selections;\n        if (tile_idx == 0)\n        {\n            num_selections = ConsumeFirstTile<IS_LAST_TILE>(num_tile_items, tile_offset, tile_state);\n        }\n        else\n        {\n            num_selections = ConsumeSubsequentTile<IS_LAST_TILE>(num_tile_items, tile_idx, tile_offset, tile_state);\n        }\n\n        return num_selections;\n    }\n\n\n    /**\n     * Scan tiles of items as part of a dynamic chained scan\n     */\n    template <typename NumSelectedIteratorT>        ///< Output iterator type for recording number of items selection_flags\n    __device__ __forceinline__ void ConsumeRange(\n        int                     num_tiles,          ///< Total number of input tiles\n        ScanTileStateT&         tile_state,         ///< Global tile state descriptor\n        NumSelectedIteratorT    d_num_selected_out) ///< Output total number selection_flags\n    {\n        // Blocks are launched in increasing order, so just assign one tile per block\n        int     tile_idx        = (blockIdx.x * gridDim.y) + blockIdx.y;    // Current tile index\n        OffsetT tile_offset     = tile_idx * TILE_ITEMS;                    // Global offset for the current tile\n\n        if (tile_idx < num_tiles - 1)\n        {\n            // Not the last tile (full)\n            ConsumeTile<false>(TILE_ITEMS, tile_idx, tile_offset, tile_state);\n        }\n        else\n        {\n            // The last tile (possibly partially-full)\n            OffsetT num_remaining   = num_items - tile_offset;\n            OffsetT num_selections  = ConsumeTile<true>(num_remaining, tile_idx, tile_offset, tile_state);\n\n            if (threadIdx.x == 0)\n            {\n                // Output the total number of items selection_flags\n                *d_num_selected_out = num_selections;\n            }\n        }\n    }\n\n};\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/agent_spmv_orig.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::AgentSpmv implements a stateful abstraction of CUDA thread blocks for participating in device-wide SpMV.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"../util_type.cuh\"\n#include \"../block/block_reduce.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../block/block_exchange.cuh\"\n#include \"../thread/thread_search.cuh\"\n#include \"../thread/thread_operators.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../iterator/counting_input_iterator.cuh\"\n#include \"../iterator/tex_ref_input_iterator.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Tuning policy\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for AgentSpmv\n */\ntemplate <\n    int                             _BLOCK_THREADS,                         ///< Threads per thread block\n    int                             _ITEMS_PER_THREAD,                      ///< Items per thread (per tile of input)\n    CacheLoadModifier               _ROW_OFFSETS_SEARCH_LOAD_MODIFIER,      ///< Cache load modifier for reading CSR row-offsets during search\n    CacheLoadModifier               _ROW_OFFSETS_LOAD_MODIFIER,             ///< Cache load modifier for reading CSR row-offsets\n    CacheLoadModifier               _COLUMN_INDICES_LOAD_MODIFIER,          ///< Cache load modifier for reading CSR column-indices\n    CacheLoadModifier               _VALUES_LOAD_MODIFIER,                  ///< Cache load modifier for reading CSR values\n    CacheLoadModifier               _VECTOR_VALUES_LOAD_MODIFIER,           ///< Cache load modifier for reading vector values\n    bool                            _DIRECT_LOAD_NONZEROS,                  ///< Whether to load nonzeros directly from global during sequential merging (vs. pre-staged through shared memory)\n    BlockScanAlgorithm              _SCAN_ALGORITHM>                        ///< The BlockScan algorithm to use\nstruct AgentSpmvPolicy\n{\n    enum\n    {\n        BLOCK_THREADS                                                   = _BLOCK_THREADS,                       ///< Threads per thread block\n        ITEMS_PER_THREAD                                                = _ITEMS_PER_THREAD,                    ///< Items per thread (per tile of input)\n        DIRECT_LOAD_NONZEROS                                            = _DIRECT_LOAD_NONZEROS,                ///< Whether to load nonzeros directly from global during sequential merging (pre-staged through shared memory)\n    };\n\n    static const CacheLoadModifier  ROW_OFFSETS_SEARCH_LOAD_MODIFIER    = _ROW_OFFSETS_SEARCH_LOAD_MODIFIER;    ///< Cache load modifier for reading CSR row-offsets\n    static const CacheLoadModifier  ROW_OFFSETS_LOAD_MODIFIER           = _ROW_OFFSETS_LOAD_MODIFIER;           ///< Cache load modifier for reading CSR row-offsets\n    static const CacheLoadModifier  COLUMN_INDICES_LOAD_MODIFIER        = _COLUMN_INDICES_LOAD_MODIFIER;        ///< Cache load modifier for reading CSR column-indices\n    static const CacheLoadModifier  VALUES_LOAD_MODIFIER                = _VALUES_LOAD_MODIFIER;                ///< Cache load modifier for reading CSR values\n    static const CacheLoadModifier  VECTOR_VALUES_LOAD_MODIFIER         = _VECTOR_VALUES_LOAD_MODIFIER;         ///< Cache load modifier for reading vector values\n    static const BlockScanAlgorithm SCAN_ALGORITHM                      = _SCAN_ALGORITHM;                      ///< The BlockScan algorithm to use\n\n};\n\n\n/******************************************************************************\n * Thread block abstractions\n ******************************************************************************/\n\ntemplate <\n    typename        ValueT,              ///< Matrix and vector value type\n    typename        OffsetT>             ///< Signed integer type for sequence offsets\nstruct SpmvParams\n{\n    ValueT*         d_values;            ///< Pointer to the array of \\p num_nonzeros values of the corresponding nonzero elements of matrix <b>A</b>.\n    OffsetT*        d_row_end_offsets;   ///< Pointer to the array of \\p m offsets demarcating the end of every row in \\p d_column_indices and \\p d_values\n    OffsetT*        d_column_indices;    ///< Pointer to the array of \\p num_nonzeros column-indices of the corresponding nonzero elements of matrix <b>A</b>.  (Indices are zero-valued.)\n    ValueT*         d_vector_x;          ///< Pointer to the array of \\p num_cols values corresponding to the dense input vector <em>x</em>\n    ValueT*         d_vector_y;          ///< Pointer to the array of \\p num_rows values corresponding to the dense output vector <em>y</em>\n    int             num_rows;            ///< Number of rows of matrix <b>A</b>.\n    int             num_cols;            ///< Number of columns of matrix <b>A</b>.\n    int             num_nonzeros;        ///< Number of nonzero elements of matrix <b>A</b>.\n    ValueT          alpha;               ///< Alpha multiplicand\n    ValueT          beta;                ///< Beta addend-multiplicand\n\n    TexRefInputIterator<ValueT, 66778899, OffsetT>  t_vector_x;\n};\n\n\n/**\n * \\brief AgentSpmv implements a stateful abstraction of CUDA thread blocks for participating in device-wide SpMV.\n */\ntemplate <\n    typename    AgentSpmvPolicyT,           ///< Parameterized AgentSpmvPolicy tuning policy type\n    typename    ValueT,                     ///< Matrix and vector value type\n    typename    OffsetT,                    ///< Signed integer type for sequence offsets\n    bool        HAS_ALPHA,                  ///< Whether the input parameter \\p alpha is 1\n    bool        HAS_BETA,                   ///< Whether the input parameter \\p beta is 0\n    int         PTX_ARCH = CUB_PTX_ARCH>    ///< PTX compute capability\nstruct AgentSpmv\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// Constants\n    enum\n    {\n        BLOCK_THREADS           = AgentSpmvPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = AgentSpmvPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS              = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    /// 2D merge path coordinate type\n    typedef typename CubVector<OffsetT, 2>::Type CoordinateT;\n\n    /// Input iterator wrapper types (for applying cache modifiers)\n\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::ROW_OFFSETS_SEARCH_LOAD_MODIFIER,\n            OffsetT,\n            OffsetT>\n        RowOffsetsSearchIteratorT;\n\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::ROW_OFFSETS_LOAD_MODIFIER,\n            OffsetT,\n            OffsetT>\n        RowOffsetsIteratorT;\n\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::COLUMN_INDICES_LOAD_MODIFIER,\n            OffsetT,\n            OffsetT>\n        ColumnIndicesIteratorT;\n\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::VALUES_LOAD_MODIFIER,\n            ValueT,\n            OffsetT>\n        ValueIteratorT;\n\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::VECTOR_VALUES_LOAD_MODIFIER,\n            ValueT,\n            OffsetT>\n        VectorValueIteratorT;\n\n    // Tuple type for scanning (pairs accumulated segment-value with segment-index)\n    typedef KeyValuePair<OffsetT, ValueT> KeyValuePairT;\n\n    // Reduce-value-by-segment scan operator\n    typedef ReduceByKeyOp<cub::Sum> ReduceBySegmentOpT;\n\n    // BlockReduce specialization\n    typedef BlockReduce<\n            ValueT,\n            BLOCK_THREADS,\n            BLOCK_REDUCE_WARP_REDUCTIONS>\n        BlockReduceT;\n\n    // BlockScan specialization\n    typedef BlockScan<\n            KeyValuePairT,\n            BLOCK_THREADS,\n            AgentSpmvPolicyT::SCAN_ALGORITHM>\n        BlockScanT;\n\n    // BlockScan specialization\n    typedef BlockScan<\n            ValueT,\n            BLOCK_THREADS,\n            AgentSpmvPolicyT::SCAN_ALGORITHM>\n        BlockPrefixSumT;\n\n    // BlockExchange specialization\n    typedef BlockExchange<\n            ValueT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD>\n        BlockExchangeT;\n\n    /// Merge item type (either a non-zero value or a row-end offset)\n    union MergeItem\n    {\n        // Value type to pair with index type OffsetT (NullType if loading values directly during merge)\n        typedef typename If<AgentSpmvPolicyT::DIRECT_LOAD_NONZEROS, NullType, ValueT>::Type MergeValueT;\n\n        OffsetT     row_end_offset;\n        MergeValueT nonzero;\n    };\n\n    /// Shared memory type required by this thread block\n    struct _TempStorage\n    {\n        CoordinateT tile_coords[2];\n\n        union Aliasable\n        {\n            // Smem needed for tile of merge items\n            MergeItem merge_items[ITEMS_PER_THREAD + TILE_ITEMS + 1];\n\n            // Smem needed for block exchange\n            typename BlockExchangeT::TempStorage exchange;\n\n            // Smem needed for block-wide reduction\n            typename BlockReduceT::TempStorage reduce;\n\n            // Smem needed for tile scanning\n            typename BlockScanT::TempStorage scan;\n\n            // Smem needed for tile prefix sum\n            typename BlockPrefixSumT::TempStorage prefix_sum;\n\n        } aliasable;\n    };\n\n    /// Temporary storage type (unionable)\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n\n    _TempStorage&                   temp_storage;         /// Reference to temp_storage\n\n    SpmvParams<ValueT, OffsetT>&    spmv_params;\n\n    ValueIteratorT                  wd_values;            ///< Wrapped pointer to the array of \\p num_nonzeros values of the corresponding nonzero elements of matrix <b>A</b>.\n    RowOffsetsIteratorT             wd_row_end_offsets;   ///< Wrapped Pointer to the array of \\p m offsets demarcating the end of every row in \\p d_column_indices and \\p d_values\n    ColumnIndicesIteratorT          wd_column_indices;    ///< Wrapped Pointer to the array of \\p num_nonzeros column-indices of the corresponding nonzero elements of matrix <b>A</b>.  (Indices are zero-valued.)\n    VectorValueIteratorT            wd_vector_x;          ///< Wrapped Pointer to the array of \\p num_cols values corresponding to the dense input vector <em>x</em>\n    VectorValueIteratorT            wd_vector_y;          ///< Wrapped Pointer to the array of \\p num_cols values corresponding to the dense input vector <em>x</em>\n\n\n    //---------------------------------------------------------------------\n    // Interface\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__ AgentSpmv(\n        TempStorage&                    temp_storage,           ///< Reference to temp_storage\n        SpmvParams<ValueT, OffsetT>&    spmv_params)            ///< SpMV input parameter bundle\n    :\n        temp_storage(temp_storage.Alias()),\n        spmv_params(spmv_params),\n        wd_values(spmv_params.d_values),\n        wd_row_end_offsets(spmv_params.d_row_end_offsets),\n        wd_column_indices(spmv_params.d_column_indices),\n        wd_vector_x(spmv_params.d_vector_x),\n        wd_vector_y(spmv_params.d_vector_y)\n    {}\n\n\n\n\n    /**\n     * Consume a merge tile, specialized for direct-load of nonzeros\n     */\n    __device__ __forceinline__ KeyValuePairT ConsumeTile(\n        int             tile_idx,\n        CoordinateT     tile_start_coord,\n        CoordinateT     tile_end_coord,\n        Int2Type<true>  is_direct_load)     ///< Marker type indicating whether to load nonzeros directly during path-discovery or beforehand in batch\n    {\n        int         tile_num_rows           = tile_end_coord.x - tile_start_coord.x;\n        int         tile_num_nonzeros       = tile_end_coord.y - tile_start_coord.y;\n        OffsetT*    s_tile_row_end_offsets  = &temp_storage.aliasable.merge_items[0].row_end_offset;\n\n        // Gather the row end-offsets for the merge tile into shared memory\n        for (int item = threadIdx.x; item <= tile_num_rows; item += BLOCK_THREADS)\n        {\n            s_tile_row_end_offsets[item] = wd_row_end_offsets[tile_start_coord.x + item];\n        }\n\n        CTA_SYNC();\n\n        // Search for the thread's starting coordinate within the merge tile\n        CountingInputIterator<OffsetT>  tile_nonzero_indices(tile_start_coord.y);\n        CoordinateT                     thread_start_coord;\n\n        MergePathSearch(\n            OffsetT(threadIdx.x * ITEMS_PER_THREAD),    // Diagonal\n            s_tile_row_end_offsets,                     // List A\n            tile_nonzero_indices,                       // List B\n            tile_num_rows,\n            tile_num_nonzeros,\n            thread_start_coord);\n\n        CTA_SYNC();            // Perf-sync\n\n        // Compute the thread's merge path segment\n        CoordinateT     thread_current_coord = thread_start_coord;\n        KeyValuePairT   scan_segment[ITEMS_PER_THREAD];\n\n        ValueT          running_total = 0.0;\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            OffsetT nonzero_idx         = CUB_MIN(tile_nonzero_indices[thread_current_coord.y], spmv_params.num_nonzeros - 1);\n            OffsetT column_idx          = wd_column_indices[nonzero_idx];\n            ValueT  value               = wd_values[nonzero_idx];\n\n            ValueT  vector_value        = spmv_params.t_vector_x[column_idx];\n#if (CUB_PTX_ARCH >= 350)\n            vector_value                = wd_vector_x[column_idx];\n#endif\n            ValueT  nonzero             = value * vector_value;\n\n            OffsetT row_end_offset      = s_tile_row_end_offsets[thread_current_coord.x];\n\n            if (tile_nonzero_indices[thread_current_coord.y] < row_end_offset)\n            {\n                // Move down (accumulate)\n                running_total += nonzero;\n                scan_segment[ITEM].value    = running_total;\n                scan_segment[ITEM].key      = tile_num_rows;\n                ++thread_current_coord.y;\n            }\n            else\n            {\n                // Move right (reset)\n                scan_segment[ITEM].value    = running_total;\n                scan_segment[ITEM].key      = thread_current_coord.x;\n                running_total               = 0.0;\n                ++thread_current_coord.x;\n            }\n        }\n\n        CTA_SYNC();\n\n        // Block-wide reduce-value-by-segment\n        KeyValuePairT       tile_carry;\n        ReduceBySegmentOpT  scan_op;\n        KeyValuePairT       scan_item;\n\n        scan_item.value = running_total;\n        scan_item.key   = thread_current_coord.x;\n\n        BlockScanT(temp_storage.aliasable.scan).ExclusiveScan(scan_item, scan_item, scan_op, tile_carry);\n\n        if (tile_num_rows > 0)\n        {\n            if (threadIdx.x == 0)\n                scan_item.key = -1;\n\n            // Direct scatter\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            {\n                if (scan_segment[ITEM].key < tile_num_rows)\n                {\n                    if (scan_item.key == scan_segment[ITEM].key)\n                        scan_segment[ITEM].value = scan_item.value + scan_segment[ITEM].value;\n\n                    if (HAS_ALPHA)\n                    {\n                        scan_segment[ITEM].value *= spmv_params.alpha;\n                    }\n\n                    if (HAS_BETA)\n                    {\n                        // Update the output vector element\n                        ValueT addend = spmv_params.beta * wd_vector_y[tile_start_coord.x + scan_segment[ITEM].key];\n                        scan_segment[ITEM].value += addend;\n                    }\n\n                    // Set the output vector element\n                    spmv_params.d_vector_y[tile_start_coord.x + scan_segment[ITEM].key] = scan_segment[ITEM].value;\n                }\n            }\n        }\n\n        // Return the tile's running carry-out\n        return tile_carry;\n    }\n\n\n\n    /**\n     * Consume a merge tile, specialized for indirect load of nonzeros\n     */\n    __device__ __forceinline__ KeyValuePairT ConsumeTile(\n        int             tile_idx,\n        CoordinateT     tile_start_coord,\n        CoordinateT     tile_end_coord,\n        Int2Type<false> is_direct_load)     ///< Marker type indicating whether to load nonzeros directly during path-discovery or beforehand in batch\n    {\n        int         tile_num_rows           = tile_end_coord.x - tile_start_coord.x;\n        int         tile_num_nonzeros       = tile_end_coord.y - tile_start_coord.y;\n\n#if (CUB_PTX_ARCH >= 520)\n\n/*\n        OffsetT*    s_tile_row_end_offsets  = &temp_storage.merge_items[tile_num_nonzeros].row_end_offset;\n        ValueT*     s_tile_nonzeros         = &temp_storage.merge_items[0].nonzero;\n\n        OffsetT col_indices[ITEMS_PER_THREAD];\n        ValueT mat_values[ITEMS_PER_THREAD];\n        int nonzero_indices[ITEMS_PER_THREAD];\n\n        // Gather the nonzeros for the merge tile into shared memory\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            nonzero_indices[ITEM]           = threadIdx.x + (ITEM * BLOCK_THREADS);\n\n            ValueIteratorT a                = wd_values + tile_start_coord.y + nonzero_indices[ITEM];\n            ColumnIndicesIteratorT ci       = wd_column_indices + tile_start_coord.y + nonzero_indices[ITEM];\n\n            col_indices[ITEM]               = (nonzero_indices[ITEM] < tile_num_nonzeros) ? *ci : 0;\n            mat_values[ITEM]                = (nonzero_indices[ITEM] < tile_num_nonzeros) ? *a : 0.0;\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            VectorValueIteratorT x = wd_vector_x + col_indices[ITEM];\n            mat_values[ITEM] *= *x;\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            ValueT *s = s_tile_nonzeros + nonzero_indices[ITEM];\n\n            *s = mat_values[ITEM];\n        }\n\n        CTA_SYNC();\n\n*/\n\n        OffsetT*    s_tile_row_end_offsets  = &temp_storage.merge_items[0].row_end_offset;\n        ValueT*     s_tile_nonzeros         = &temp_storage.merge_items[tile_num_rows + ITEMS_PER_THREAD].nonzero;\n\n        // Gather the nonzeros for the merge tile into shared memory\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int nonzero_idx = threadIdx.x + (ITEM * BLOCK_THREADS);\n\n            ValueIteratorT a                = wd_values + tile_start_coord.y + nonzero_idx;\n            ColumnIndicesIteratorT ci       = wd_column_indices + tile_start_coord.y + nonzero_idx;\n            ValueT* s                       = s_tile_nonzeros + nonzero_idx;\n\n            if (nonzero_idx < tile_num_nonzeros)\n            {\n\n                OffsetT column_idx              = *ci;\n                ValueT  value                   = *a;\n\n                ValueT  vector_value            = spmv_params.t_vector_x[column_idx];\n                vector_value                    = wd_vector_x[column_idx];\n\n                ValueT  nonzero                 = value * vector_value;\n\n                *s    = nonzero;\n            }\n        }\n\n\n#else\n\n        OffsetT*    s_tile_row_end_offsets  = &temp_storage.aliasable.merge_items[0].row_end_offset;\n        ValueT*     s_tile_nonzeros         = &temp_storage.aliasable.merge_items[tile_num_rows + ITEMS_PER_THREAD].nonzero;\n\n        // Gather the nonzeros for the merge tile into shared memory\n        if (tile_num_nonzeros > 0)\n        {\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            {\n                int     nonzero_idx             = threadIdx.x + (ITEM * BLOCK_THREADS);\n                nonzero_idx                     = CUB_MIN(nonzero_idx, tile_num_nonzeros - 1);\n\n                OffsetT column_idx              = wd_column_indices[tile_start_coord.y + nonzero_idx];\n                ValueT  value                   = wd_values[tile_start_coord.y + nonzero_idx];\n\n                ValueT  vector_value            = spmv_params.t_vector_x[column_idx];\n#if (CUB_PTX_ARCH >= 350)\n                vector_value                    = wd_vector_x[column_idx];\n#endif\n                ValueT  nonzero                 = value * vector_value;\n\n                s_tile_nonzeros[nonzero_idx]    = nonzero;\n            }\n        }\n\n#endif\n\n        // Gather the row end-offsets for the merge tile into shared memory\n        #pragma unroll 1\n        for (int item = threadIdx.x; item <= tile_num_rows; item += BLOCK_THREADS)\n        {\n            s_tile_row_end_offsets[item] = wd_row_end_offsets[tile_start_coord.x + item];\n        }\n\n        CTA_SYNC();\n\n        // Search for the thread's starting coordinate within the merge tile\n        CountingInputIterator<OffsetT>  tile_nonzero_indices(tile_start_coord.y);\n        CoordinateT                     thread_start_coord;\n\n        MergePathSearch(\n            OffsetT(threadIdx.x * ITEMS_PER_THREAD),    // Diagonal\n            s_tile_row_end_offsets,                     // List A\n            tile_nonzero_indices,                       // List B\n            tile_num_rows,\n            tile_num_nonzeros,\n            thread_start_coord);\n\n        CTA_SYNC();            // Perf-sync\n\n        // Compute the thread's merge path segment\n        CoordinateT     thread_current_coord = thread_start_coord;\n        KeyValuePairT   scan_segment[ITEMS_PER_THREAD];\n        ValueT          running_total = 0.0;\n\n        OffsetT row_end_offset  = s_tile_row_end_offsets[thread_current_coord.x];\n        ValueT  nonzero         = s_tile_nonzeros[thread_current_coord.y];\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (tile_nonzero_indices[thread_current_coord.y] < row_end_offset)\n            {\n                // Move down (accumulate)\n                scan_segment[ITEM].value    = nonzero;\n                running_total               += nonzero;\n                ++thread_current_coord.y;\n                nonzero                     = s_tile_nonzeros[thread_current_coord.y];\n            }\n            else\n            {\n                // Move right (reset)\n                scan_segment[ITEM].value    = 0.0;\n                running_total               = 0.0;\n                ++thread_current_coord.x;\n                row_end_offset              = s_tile_row_end_offsets[thread_current_coord.x];\n            }\n\n            scan_segment[ITEM].key = thread_current_coord.x;\n        }\n\n        CTA_SYNC();\n\n        // Block-wide reduce-value-by-segment\n        KeyValuePairT       tile_carry;\n        ReduceBySegmentOpT  scan_op;\n        KeyValuePairT       scan_item;\n\n        scan_item.value = running_total;\n        scan_item.key = thread_current_coord.x;\n\n        BlockScanT(temp_storage.aliasable.scan).ExclusiveScan(scan_item, scan_item, scan_op, tile_carry);\n\n        if (threadIdx.x == 0)\n        {\n            scan_item.key = thread_start_coord.x;\n            scan_item.value = 0.0;\n        }\n\n        if (tile_num_rows > 0)\n        {\n\n            CTA_SYNC();\n\n            // Scan downsweep and scatter\n            ValueT* s_partials = &temp_storage.aliasable.merge_items[0].nonzero;\n\n            if (scan_item.key != scan_segment[0].key)\n            {\n                s_partials[scan_item.key] = scan_item.value;\n            }\n            else\n            {\n                scan_segment[0].value += scan_item.value;\n            }\n\n            #pragma unroll\n            for (int ITEM = 1; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            {\n                if (scan_segment[ITEM - 1].key != scan_segment[ITEM].key)\n                {\n                    s_partials[scan_segment[ITEM - 1].key] = scan_segment[ITEM - 1].value;\n                }\n                else\n                {\n                    scan_segment[ITEM].value += scan_segment[ITEM - 1].value;\n                }\n            }\n\n            CTA_SYNC();\n\n            #pragma unroll 1\n            for (int item = threadIdx.x; item < tile_num_rows; item += BLOCK_THREADS)\n            {\n                spmv_params.d_vector_y[tile_start_coord.x + item] = s_partials[item];\n            }\n        }\n\n        // Return the tile's running carry-out\n        return tile_carry;\n    }\n\n\n\n\n\n\n\n    /**\n     * Consume a merge tile, specialized for indirect load of nonzeros\n     * /\n    template <typename IsDirectLoadT>\n    __device__ __forceinline__ KeyValuePairT ConsumeTile1(\n        int             tile_idx,\n        CoordinateT     tile_start_coord,\n        CoordinateT     tile_end_coord,\n        IsDirectLoadT   is_direct_load)     ///< Marker type indicating whether to load nonzeros directly during path-discovery or beforehand in batch\n    {\n        int         tile_num_rows           = tile_end_coord.x - tile_start_coord.x;\n        int         tile_num_nonzeros       = tile_end_coord.y - tile_start_coord.y;\n\n        OffsetT*    s_tile_row_end_offsets  = &temp_storage.merge_items[0].row_end_offset;\n\n        int warp_idx                        = threadIdx.x / WARP_THREADS;\n        int lane_idx                        = LaneId();\n\n        // Gather the row end-offsets for the merge tile into shared memory\n        #pragma unroll 1\n        for (int item = threadIdx.x; item <= tile_num_rows; item += BLOCK_THREADS)\n        {\n            s_tile_row_end_offsets[item] = wd_row_end_offsets[tile_start_coord.x + item];\n        }\n\n        CTA_SYNC();\n\n        // Search for warp start/end coords\n        if (lane_idx == 0)\n        {\n            MergePathSearch(\n                OffsetT(warp_idx * ITEMS_PER_WARP),                 // Diagonal\n                s_tile_row_end_offsets,                             // List A\n                CountingInputIterator<OffsetT>(tile_start_coord.y), // List B\n                tile_num_rows,\n                tile_num_nonzeros,\n                temp_storage.warp_coords[warp_idx]);\n\n            CoordinateT last = {tile_num_rows, tile_num_nonzeros};\n            temp_storage.warp_coords[WARPS] = last;\n        }\n\n        CTA_SYNC();\n\n        CoordinateT     warp_coord          = temp_storage.warp_coords[warp_idx];\n        CoordinateT     warp_end_coord      = temp_storage.warp_coords[warp_idx + 1];\n        OffsetT         warp_nonzero_idx    = tile_start_coord.y + warp_coord.y;\n\n        // Consume whole rows\n        #pragma unroll 1\n        for (; warp_coord.x < warp_end_coord.x; ++warp_coord.x)\n        {\n            ValueT  row_total       = 0.0;\n            OffsetT row_end_offset  = s_tile_row_end_offsets[warp_coord.x];\n\n            #pragma unroll 1\n            for (OffsetT nonzero_idx = warp_nonzero_idx + lane_idx;\n                nonzero_idx < row_end_offset;\n                nonzero_idx += WARP_THREADS)\n            {\n                OffsetT column_idx          = wd_column_indices[nonzero_idx];\n                ValueT  value               = wd_values[nonzero_idx];\n                ValueT  vector_value        = wd_vector_x[column_idx];\n                row_total                   += value * vector_value;\n            }\n\n            // Warp reduce\n            row_total = WarpReduceT(temp_storage.warp_reduce[warp_idx]).Sum(row_total);\n\n            // Output\n            if (lane_idx == 0)\n            {\n                spmv_params.d_vector_y[tile_start_coord.x + warp_coord.x] = row_total;\n            }\n\n            warp_nonzero_idx = row_end_offset;\n        }\n\n        // Consume partial portion of thread's last row\n        if (warp_nonzero_idx < tile_start_coord.y + warp_end_coord.y)\n        {\n            ValueT row_total = 0.0;\n            for (OffsetT nonzero_idx = warp_nonzero_idx + lane_idx;\n                nonzero_idx < tile_start_coord.y + warp_end_coord.y;\n                nonzero_idx += WARP_THREADS)\n            {\n\n                OffsetT column_idx          = wd_column_indices[nonzero_idx];\n                ValueT  value               = wd_values[nonzero_idx];\n                ValueT  vector_value        = wd_vector_x[column_idx];\n                row_total                   += value * vector_value;\n            }\n\n            // Warp reduce\n            row_total = WarpReduceT(temp_storage.warp_reduce[warp_idx]).Sum(row_total);\n\n            // Output\n            if (lane_idx == 0)\n            {\n                spmv_params.d_vector_y[tile_start_coord.x + warp_coord.x] = row_total;\n            }\n        }\n\n        // Return the tile's running carry-out\n        KeyValuePairT tile_carry(tile_num_rows, 0.0);\n        return tile_carry;\n    }\n*/\n\n\n\n\n\n\n\n    /**\n     * Consume a merge tile, specialized for indirect load of nonzeros\n     * /\n    __device__ __forceinline__ KeyValuePairT ConsumeTile2(\n        int             tile_idx,\n        CoordinateT     tile_start_coord,\n        CoordinateT     tile_end_coord,\n        Int2Type<false> is_direct_load)     ///< Marker type indicating whether to load nonzeros directly during path-discovery or beforehand in batch\n    {\n        int         tile_num_rows           = tile_end_coord.x - tile_start_coord.x;\n        int         tile_num_nonzeros       = tile_end_coord.y - tile_start_coord.y;\n\n        ValueT*     s_tile_nonzeros         = &temp_storage.merge_items[0].nonzero;\n\n        ValueT      nonzeros[ITEMS_PER_THREAD];\n\n        // Gather the nonzeros for the merge tile into shared memory\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int     nonzero_idx         = threadIdx.x + (ITEM * BLOCK_THREADS);\n            nonzero_idx                 = CUB_MIN(nonzero_idx, tile_num_nonzeros - 1);\n\n            OffsetT column_idx          = wd_column_indices[tile_start_coord.y + nonzero_idx];\n            ValueT  value               = wd_values[tile_start_coord.y + nonzero_idx];\n\n            ValueT  vector_value        = spmv_params.t_vector_x[column_idx];\n#if (CUB_PTX_ARCH >= 350)\n            vector_value                = wd_vector_x[column_idx];\n#endif\n\n            nonzeros[ITEM]              = value * vector_value;\n        }\n\n        // Exchange striped->blocked\n        BlockExchangeT(temp_storage.exchange).StripedToBlocked(nonzeros);\n\n        CTA_SYNC();\n\n        // Compute an inclusive prefix sum\n        BlockPrefixSumT(temp_storage.prefix_sum).InclusiveSum(nonzeros, nonzeros);\n\n        CTA_SYNC();\n\n        if (threadIdx.x == 0)\n            s_tile_nonzeros[0] = 0.0;\n\n        // Scatter back to smem\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            int item_idx = (threadIdx.x * ITEMS_PER_THREAD) + ITEM + 1;\n            s_tile_nonzeros[item_idx] = nonzeros[ITEM];\n        }\n\n        CTA_SYNC();\n\n        // Gather the row end-offsets for the merge tile into shared memory\n        #pragma unroll 1\n        for (int item = threadIdx.x; item < tile_num_rows; item += BLOCK_THREADS)\n        {\n            OffsetT start = CUB_MAX(wd_row_end_offsets[tile_start_coord.x + item - 1], tile_start_coord.y);\n            OffsetT end = wd_row_end_offsets[tile_start_coord.x + item];\n\n            start -= tile_start_coord.y;\n            end -= tile_start_coord.y;\n\n            ValueT row_partial = s_tile_nonzeros[end] - s_tile_nonzeros[start];\n\n            spmv_params.d_vector_y[tile_start_coord.x + item] = row_partial;\n        }\n\n        // Get the tile's carry-out\n        KeyValuePairT tile_carry;\n        if (threadIdx.x == 0)\n        {\n            tile_carry.key = tile_num_rows;\n\n            OffsetT start = CUB_MAX(wd_row_end_offsets[tile_end_coord.x - 1], tile_start_coord.y);\n            start -= tile_start_coord.y;\n            OffsetT end = tile_num_nonzeros;\n\n            tile_carry.value = s_tile_nonzeros[end] - s_tile_nonzeros[start];\n        }\n\n        // Return the tile's running carry-out\n        return tile_carry;\n    }\n*/\n\n\n    /**\n     * Consume input tile\n     */\n    __device__ __forceinline__ void ConsumeTile(\n        CoordinateT*    d_tile_coordinates,     ///< [in] Pointer to the temporary array of tile starting coordinates\n        KeyValuePairT*  d_tile_carry_pairs,     ///< [out] Pointer to the temporary array carry-out dot product row-ids, one per block\n        int             num_merge_tiles)        ///< [in] Number of merge tiles\n    {\n        int tile_idx = (blockIdx.x * gridDim.y) + blockIdx.y;    // Current tile index\n\n        if (tile_idx >= num_merge_tiles)\n            return;\n\n        // Read our starting coordinates\n        if (threadIdx.x < 2)\n        {\n            if (d_tile_coordinates == NULL)\n            {\n                // Search our starting coordinates\n                OffsetT                         diagonal = (tile_idx + threadIdx.x) * TILE_ITEMS;\n                CoordinateT                     tile_coord;\n                CountingInputIterator<OffsetT>  nonzero_indices(0);\n\n                // Search the merge path\n                MergePathSearch(\n                    diagonal,\n                    RowOffsetsSearchIteratorT(spmv_params.d_row_end_offsets),\n                    nonzero_indices,\n                    spmv_params.num_rows,\n                    spmv_params.num_nonzeros,\n                    tile_coord);\n\n                temp_storage.tile_coords[threadIdx.x] = tile_coord;\n            }\n            else\n            {\n                temp_storage.tile_coords[threadIdx.x] = d_tile_coordinates[tile_idx + threadIdx.x];\n            }\n        }\n\n        CTA_SYNC();\n\n        CoordinateT tile_start_coord     = temp_storage.tile_coords[0];\n        CoordinateT tile_end_coord       = temp_storage.tile_coords[1];\n\n        // Consume multi-segment tile\n        KeyValuePairT tile_carry = ConsumeTile(\n            tile_idx,\n            tile_start_coord,\n            tile_end_coord,\n            Int2Type<AgentSpmvPolicyT::DIRECT_LOAD_NONZEROS>());\n\n        // Output the tile's carry-out\n        if (threadIdx.x == 0)\n        {\n            if (HAS_ALPHA)\n                tile_carry.value *= spmv_params.alpha;\n\n            tile_carry.key += tile_start_coord.x;\n            d_tile_carry_pairs[tile_idx]    = tile_carry;\n        }\n    }\n\n\n};\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/agent/single_pass_scan_operators.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Callback operator types for supplying BlockScan prefixes\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../warp/warp_reduce.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Prefix functor type for maintaining a running prefix while scanning a\n * region independent of other thread blocks\n ******************************************************************************/\n\n/**\n * Stateful callback operator type for supplying BlockScan prefixes.\n * Maintains a running prefix that can be applied to consecutive\n * BlockScan operations.\n */\ntemplate <\n    typename T,                 ///< BlockScan value type\n    typename ScanOpT>            ///< Wrapped scan operator type\nstruct BlockScanRunningPrefixOp\n{\n    ScanOpT     op;                 ///< Wrapped scan operator\n    T           running_total;      ///< Running block-wide prefix\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanRunningPrefixOp(ScanOpT op)\n    :\n        op(op)\n    {}\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanRunningPrefixOp(\n        T starting_prefix,\n        ScanOpT op)\n    :\n        op(op),\n        running_total(starting_prefix)\n    {}\n\n    /**\n     * Prefix callback operator.  Returns the block-wide running_total in thread-0.\n     */\n    __device__ __forceinline__ T operator()(\n        const T &block_aggregate)              ///< The aggregate sum of the BlockScan inputs\n    {\n        T retval = running_total;\n        running_total = op(running_total, block_aggregate);\n        return retval;\n    }\n};\n\n\n/******************************************************************************\n * Generic tile status interface types for block-cooperative scans\n ******************************************************************************/\n\n/**\n * Enumerations of tile status\n */\nenum ScanTileStatus\n{\n    SCAN_TILE_OOB,          // Out-of-bounds (e.g., padding)\n    SCAN_TILE_INVALID = 99, // Not yet processed\n    SCAN_TILE_PARTIAL,      // Tile aggregate is available\n    SCAN_TILE_INCLUSIVE,    // Inclusive tile prefix is available\n};\n\n\n/**\n * Tile status interface.\n */\ntemplate <\n    typename    T,\n    bool        SINGLE_WORD = Traits<T>::PRIMITIVE>\nstruct ScanTileState;\n\n\n/**\n * Tile status interface specialized for scan status and value types\n * that can be combined into one machine word that can be\n * read/written coherently in a single access.\n */\ntemplate <typename T>\nstruct ScanTileState<T, true>\n{\n    // Status word type\n    typedef typename If<(sizeof(T) == 8),\n        long long,\n        typename If<(sizeof(T) == 4),\n            int,\n            typename If<(sizeof(T) == 2),\n                short,\n                char>::Type>::Type>::Type StatusWord;\n\n\n    // Unit word type\n    typedef typename If<(sizeof(T) == 8),\n        longlong2,\n        typename If<(sizeof(T) == 4),\n            int2,\n            typename If<(sizeof(T) == 2),\n                int,\n                uchar2>::Type>::Type>::Type TxnWord;\n\n\n    // Device word type\n    struct TileDescriptor\n    {\n        StatusWord  status;\n        T           value;\n    };\n\n\n    // Constants\n    enum\n    {\n        TILE_STATUS_PADDING = CUB_PTX_WARP_THREADS,\n    };\n\n\n    // Device storage\n    TxnWord *d_tile_descriptors;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    ScanTileState()\n    :\n        d_tile_descriptors(NULL)\n    {}\n\n\n    /// Initializer\n    __host__ __device__ __forceinline__\n    cudaError_t Init(\n        int     /*num_tiles*/,                      ///< [in] Number of tiles\n        void    *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t  /*temp_storage_bytes*/)             ///< [in] Size in bytes of \\t d_temp_storage allocation\n    {\n        d_tile_descriptors = reinterpret_cast<TxnWord*>(d_temp_storage);\n        return cudaSuccess;\n    }\n\n\n    /**\n     * Compute device memory needed for tile status\n     */\n    __host__ __device__ __forceinline__\n    static cudaError_t AllocationSize(\n        int     num_tiles,                          ///< [in] Number of tiles\n        size_t  &temp_storage_bytes)                ///< [out] Size in bytes of \\t d_temp_storage allocation\n    {\n        temp_storage_bytes = (num_tiles + TILE_STATUS_PADDING) * sizeof(TileDescriptor);       // bytes needed for tile status descriptors\n        return cudaSuccess;\n    }\n\n\n    /**\n     * Initialize (from device)\n     */\n    __device__ __forceinline__ void InitializeStatus(int num_tiles)\n    {\n        int tile_idx = (blockIdx.x * blockDim.x) + threadIdx.x;\n\n        TxnWord val = TxnWord();\n        TileDescriptor *descriptor = reinterpret_cast<TileDescriptor*>(&val);\n\n        if (tile_idx < num_tiles)\n        {\n            // Not-yet-set\n            descriptor->status = StatusWord(SCAN_TILE_INVALID);\n            d_tile_descriptors[TILE_STATUS_PADDING + tile_idx] = val;\n        }\n\n        if ((blockIdx.x == 0) && (threadIdx.x < TILE_STATUS_PADDING))\n        {\n            // Padding\n            descriptor->status = StatusWord(SCAN_TILE_OOB);\n            d_tile_descriptors[threadIdx.x] = val;\n        }\n    }\n\n\n    /**\n     * Update the specified tile's inclusive value and corresponding status\n     */\n    __device__ __forceinline__ void SetInclusive(int tile_idx, T tile_inclusive)\n    {\n        TileDescriptor tile_descriptor;\n        tile_descriptor.status = SCAN_TILE_INCLUSIVE;\n        tile_descriptor.value = tile_inclusive;\n\n        TxnWord alias;\n        *reinterpret_cast<TileDescriptor*>(&alias) = tile_descriptor;\n        ThreadStore<STORE_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx, alias);\n    }\n\n\n    /**\n     * Update the specified tile's partial value and corresponding status\n     */\n    __device__ __forceinline__ void SetPartial(int tile_idx, T tile_partial)\n    {\n        TileDescriptor tile_descriptor;\n        tile_descriptor.status = SCAN_TILE_PARTIAL;\n        tile_descriptor.value = tile_partial;\n\n        TxnWord alias;\n        *reinterpret_cast<TileDescriptor*>(&alias) = tile_descriptor;\n        ThreadStore<STORE_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx, alias);\n    }\n\n    /**\n     * Wait for the corresponding tile to become non-invalid\n     */\n    __device__ __forceinline__ void WaitForValid(\n        int             tile_idx,\n        StatusWord      &status,\n        T               &value)\n    {\n        TileDescriptor tile_descriptor;\n        do\n        {\n            __threadfence_block(); // prevent hoisting loads from loop\n            TxnWord alias = ThreadLoad<LOAD_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx);\n            tile_descriptor = reinterpret_cast<TileDescriptor&>(alias);\n\n        } while (WARP_ANY((tile_descriptor.status == SCAN_TILE_INVALID), 0xffffffff));\n\n        status = tile_descriptor.status;\n        value = tile_descriptor.value;\n    }\n\n};\n\n\n\n/**\n * Tile status interface specialized for scan status and value types that\n * cannot be combined into one machine word.\n */\ntemplate <typename T>\nstruct ScanTileState<T, false>\n{\n    // Status word type\n    typedef char StatusWord;\n\n    // Constants\n    enum\n    {\n        TILE_STATUS_PADDING = CUB_PTX_WARP_THREADS,\n    };\n\n    // Device storage\n    StatusWord  *d_tile_status;\n    T           *d_tile_partial;\n    T           *d_tile_inclusive;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    ScanTileState()\n    :\n        d_tile_status(NULL),\n        d_tile_partial(NULL),\n        d_tile_inclusive(NULL)\n    {}\n\n\n    /// Initializer\n    __host__ __device__ __forceinline__\n    cudaError_t Init(\n        int     num_tiles,                          ///< [in] Number of tiles\n        void    *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t  temp_storage_bytes)                 ///< [in] Size in bytes of \\t d_temp_storage allocation\n    {\n        cudaError_t error = cudaSuccess;\n        do\n        {\n            void*   allocations[3];\n            size_t  allocation_sizes[3];\n\n            allocation_sizes[0] = (num_tiles + TILE_STATUS_PADDING) * sizeof(StatusWord);           // bytes needed for tile status descriptors\n            allocation_sizes[1] = (num_tiles + TILE_STATUS_PADDING) * sizeof(Uninitialized<T>);     // bytes needed for partials\n            allocation_sizes[2] = (num_tiles + TILE_STATUS_PADDING) * sizeof(Uninitialized<T>);     // bytes needed for inclusives\n\n            // Compute allocation pointers into the single storage blob\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n\n            // Alias the offsets\n            d_tile_status       = reinterpret_cast<StatusWord*>(allocations[0]);\n            d_tile_partial      = reinterpret_cast<T*>(allocations[1]);\n            d_tile_inclusive    = reinterpret_cast<T*>(allocations[2]);\n        }\n        while (0);\n\n        return error;\n    }\n\n\n    /**\n     * Compute device memory needed for tile status\n     */\n    __host__ __device__ __forceinline__\n    static cudaError_t AllocationSize(\n        int     num_tiles,                          ///< [in] Number of tiles\n        size_t  &temp_storage_bytes)                ///< [out] Size in bytes of \\t d_temp_storage allocation\n    {\n        // Specify storage allocation requirements\n        size_t  allocation_sizes[3];\n        allocation_sizes[0] = (num_tiles + TILE_STATUS_PADDING) * sizeof(StatusWord);         // bytes needed for tile status descriptors\n        allocation_sizes[1] = (num_tiles + TILE_STATUS_PADDING) * sizeof(Uninitialized<T>);   // bytes needed for partials\n        allocation_sizes[2] = (num_tiles + TILE_STATUS_PADDING) * sizeof(Uninitialized<T>);   // bytes needed for inclusives\n\n        // Set the necessary size of the blob\n        void* allocations[3];\n        return CubDebug(AliasTemporaries(NULL, temp_storage_bytes, allocations, allocation_sizes));\n    }\n\n\n    /**\n     * Initialize (from device)\n     */\n    __device__ __forceinline__ void InitializeStatus(int num_tiles)\n    {\n        int tile_idx = (blockIdx.x * blockDim.x) + threadIdx.x;\n        if (tile_idx < num_tiles)\n        {\n            // Not-yet-set\n            d_tile_status[TILE_STATUS_PADDING + tile_idx] = StatusWord(SCAN_TILE_INVALID);\n        }\n\n        if ((blockIdx.x == 0) && (threadIdx.x < TILE_STATUS_PADDING))\n        {\n            // Padding\n            d_tile_status[threadIdx.x] = StatusWord(SCAN_TILE_OOB);\n        }\n    }\n\n\n    /**\n     * Update the specified tile's inclusive value and corresponding status\n     */\n    __device__ __forceinline__ void SetInclusive(int tile_idx, T tile_inclusive)\n    {\n        // Update tile inclusive value\n        ThreadStore<STORE_CG>(d_tile_inclusive + TILE_STATUS_PADDING + tile_idx, tile_inclusive);\n\n        // Fence\n        __threadfence();\n\n        // Update tile status\n        ThreadStore<STORE_CG>(d_tile_status + TILE_STATUS_PADDING + tile_idx, StatusWord(SCAN_TILE_INCLUSIVE));\n    }\n\n\n    /**\n     * Update the specified tile's partial value and corresponding status\n     */\n    __device__ __forceinline__ void SetPartial(int tile_idx, T tile_partial)\n    {\n        // Update tile partial value\n        ThreadStore<STORE_CG>(d_tile_partial + TILE_STATUS_PADDING + tile_idx, tile_partial);\n\n        // Fence\n        __threadfence();\n\n        // Update tile status\n        ThreadStore<STORE_CG>(d_tile_status + TILE_STATUS_PADDING + tile_idx, StatusWord(SCAN_TILE_PARTIAL));\n    }\n\n    /**\n     * Wait for the corresponding tile to become non-invalid\n     */\n    __device__ __forceinline__ void WaitForValid(\n        int             tile_idx,\n        StatusWord      &status,\n        T               &value)\n    {\n        do {\n            status = ThreadLoad<LOAD_CG>(d_tile_status + TILE_STATUS_PADDING + tile_idx);\n\n            __threadfence();    // prevent hoisting loads from loop or loads below above this one\n\n        } while (status == SCAN_TILE_INVALID);\n\n        if (status == StatusWord(SCAN_TILE_PARTIAL)) \n            value = ThreadLoad<LOAD_CG>(d_tile_partial + TILE_STATUS_PADDING + tile_idx);\n        else\n            value = ThreadLoad<LOAD_CG>(d_tile_inclusive + TILE_STATUS_PADDING + tile_idx);\n    }\n};\n\n\n/******************************************************************************\n * ReduceByKey tile status interface types for block-cooperative scans\n ******************************************************************************/\n\n/**\n * Tile status interface for reduction by key.\n *\n */\ntemplate <\n    typename    ValueT,\n    typename    KeyT,\n    bool        SINGLE_WORD = (Traits<ValueT>::PRIMITIVE) && (sizeof(ValueT) + sizeof(KeyT) < 16)>\nstruct ReduceByKeyScanTileState;\n\n\n/**\n * Tile status interface for reduction by key, specialized for scan status and value types that\n * cannot be combined into one machine word.\n */\ntemplate <\n    typename    ValueT,\n    typename    KeyT>\nstruct ReduceByKeyScanTileState<ValueT, KeyT, false> :\n    ScanTileState<KeyValuePair<KeyT, ValueT> >\n{\n    typedef ScanTileState<KeyValuePair<KeyT, ValueT> > SuperClass;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    ReduceByKeyScanTileState() : SuperClass() {}\n};\n\n\n/**\n * Tile status interface for reduction by key, specialized for scan status and value types that\n * can be combined into one machine word that can be read/written coherently in a single access.\n */\ntemplate <\n    typename ValueT,\n    typename KeyT>\nstruct ReduceByKeyScanTileState<ValueT, KeyT, true>\n{\n    typedef KeyValuePair<KeyT, ValueT>KeyValuePairT;\n\n    // Constants\n    enum\n    {\n        PAIR_SIZE           = sizeof(ValueT) + sizeof(KeyT),\n        TXN_WORD_SIZE       = 1 << Log2<PAIR_SIZE + 1>::VALUE,\n        STATUS_WORD_SIZE    = TXN_WORD_SIZE - PAIR_SIZE,\n\n        TILE_STATUS_PADDING = CUB_PTX_WARP_THREADS,\n    };\n\n    // Status word type\n    typedef typename If<(STATUS_WORD_SIZE == 8),\n        long long,\n        typename If<(STATUS_WORD_SIZE == 4),\n            int,\n            typename If<(STATUS_WORD_SIZE == 2),\n                short,\n                char>::Type>::Type>::Type StatusWord;\n\n    // Status word type\n    typedef typename If<(TXN_WORD_SIZE == 16),\n        longlong2,\n        typename If<(TXN_WORD_SIZE == 8),\n            long long,\n            int>::Type>::Type TxnWord;\n\n    // Device word type (for when sizeof(ValueT) == sizeof(KeyT))\n    struct TileDescriptorBigStatus\n    {\n        KeyT        key;\n        ValueT      value;\n        StatusWord  status;\n    };\n\n    // Device word type (for when sizeof(ValueT) != sizeof(KeyT))\n    struct TileDescriptorLittleStatus\n    {\n        ValueT      value;\n        StatusWord  status;\n        KeyT        key;\n    };\n\n    // Device word type\n    typedef typename If<\n            (sizeof(ValueT) == sizeof(KeyT)),\n            TileDescriptorBigStatus,\n            TileDescriptorLittleStatus>::Type\n        TileDescriptor;\n\n\n    // Device storage\n    TxnWord *d_tile_descriptors;\n\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    ReduceByKeyScanTileState()\n    :\n        d_tile_descriptors(NULL)\n    {}\n\n\n    /// Initializer\n    __host__ __device__ __forceinline__\n    cudaError_t Init(\n        int     /*num_tiles*/,                      ///< [in] Number of tiles\n        void    *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t  /*temp_storage_bytes*/)             ///< [in] Size in bytes of \\t d_temp_storage allocation\n    {\n        d_tile_descriptors = reinterpret_cast<TxnWord*>(d_temp_storage);\n        return cudaSuccess;\n    }\n\n\n    /**\n     * Compute device memory needed for tile status\n     */\n    __host__ __device__ __forceinline__\n    static cudaError_t AllocationSize(\n        int     num_tiles,                          ///< [in] Number of tiles\n        size_t  &temp_storage_bytes)                ///< [out] Size in bytes of \\t d_temp_storage allocation\n    {\n        temp_storage_bytes = (num_tiles + TILE_STATUS_PADDING) * sizeof(TileDescriptor);       // bytes needed for tile status descriptors\n        return cudaSuccess;\n    }\n\n\n    /**\n     * Initialize (from device)\n     */\n    __device__ __forceinline__ void InitializeStatus(int num_tiles)\n    {\n        int             tile_idx    = (blockIdx.x * blockDim.x) + threadIdx.x;\n        TxnWord         val         = TxnWord();\n        TileDescriptor  *descriptor = reinterpret_cast<TileDescriptor*>(&val);\n\n        if (tile_idx < num_tiles)\n        {\n            // Not-yet-set\n            descriptor->status = StatusWord(SCAN_TILE_INVALID);\n            d_tile_descriptors[TILE_STATUS_PADDING + tile_idx] = val;\n        }\n\n        if ((blockIdx.x == 0) && (threadIdx.x < TILE_STATUS_PADDING))\n        {\n            // Padding\n            descriptor->status = StatusWord(SCAN_TILE_OOB);\n            d_tile_descriptors[threadIdx.x] = val;\n        }\n    }\n\n\n    /**\n     * Update the specified tile's inclusive value and corresponding status\n     */\n    __device__ __forceinline__ void SetInclusive(int tile_idx, KeyValuePairT tile_inclusive)\n    {\n        TileDescriptor tile_descriptor;\n        tile_descriptor.status  = SCAN_TILE_INCLUSIVE;\n        tile_descriptor.value   = tile_inclusive.value;\n        tile_descriptor.key     = tile_inclusive.key;\n\n        TxnWord alias;\n        *reinterpret_cast<TileDescriptor*>(&alias) = tile_descriptor;\n        ThreadStore<STORE_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx, alias);\n    }\n\n\n    /**\n     * Update the specified tile's partial value and corresponding status\n     */\n    __device__ __forceinline__ void SetPartial(int tile_idx, KeyValuePairT tile_partial)\n    {\n        TileDescriptor tile_descriptor;\n        tile_descriptor.status  = SCAN_TILE_PARTIAL;\n        tile_descriptor.value   = tile_partial.value;\n        tile_descriptor.key     = tile_partial.key;\n\n        TxnWord alias;\n        *reinterpret_cast<TileDescriptor*>(&alias) = tile_descriptor;\n        ThreadStore<STORE_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx, alias);\n    }\n\n    /**\n     * Wait for the corresponding tile to become non-invalid\n     */\n    __device__ __forceinline__ void WaitForValid(\n        int                     tile_idx,\n        StatusWord              &status,\n        KeyValuePairT           &value)\n    {\n//        TxnWord         alias           = ThreadLoad<LOAD_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx);\n//        TileDescriptor  tile_descriptor = reinterpret_cast<TileDescriptor&>(alias);\n//\n//        while (tile_descriptor.status == SCAN_TILE_INVALID)\n//        {\n//            __threadfence_block(); // prevent hoisting loads from loop\n//\n//            alias           = ThreadLoad<LOAD_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx);\n//            tile_descriptor = reinterpret_cast<TileDescriptor&>(alias);\n//        }\n//\n//        status      = tile_descriptor.status;\n//        value.value = tile_descriptor.value;\n//        value.key   = tile_descriptor.key;\n\n        TileDescriptor tile_descriptor;\n        do\n        {\n            __threadfence_block(); // prevent hoisting loads from loop\n            TxnWord alias = ThreadLoad<LOAD_CG>(d_tile_descriptors + TILE_STATUS_PADDING + tile_idx);\n            tile_descriptor = reinterpret_cast<TileDescriptor&>(alias);\n\n        } while (WARP_ANY((tile_descriptor.status == SCAN_TILE_INVALID), 0xffffffff));\n\n        status      = tile_descriptor.status;\n        value.value = tile_descriptor.value;\n        value.key   = tile_descriptor.key;\n    }\n\n};\n\n\n/******************************************************************************\n * Prefix call-back operator for coupling local block scan within a\n * block-cooperative scan\n ******************************************************************************/\n\n/**\n * Stateful block-scan prefix functor.  Provides the the running prefix for\n * the current tile by using the call-back warp to wait on on\n * aggregates/prefixes from predecessor tiles to become available.\n */\ntemplate <\n    typename    T,\n    typename    ScanOpT,\n    typename    ScanTileStateT,\n    int         PTX_ARCH = CUB_PTX_ARCH>\nstruct TilePrefixCallbackOp\n{\n    // Parameterized warp reduce\n    typedef WarpReduce<T, CUB_PTX_WARP_THREADS, PTX_ARCH> WarpReduceT;\n\n    // Temporary storage type\n    struct _TempStorage\n    {\n        typename WarpReduceT::TempStorage   warp_reduce;\n        T                                   exclusive_prefix;\n        T                                   inclusive_prefix;\n        T                                   block_aggregate;\n    };\n\n    // Alias wrapper allowing temporary storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n    // Type of status word\n    typedef typename ScanTileStateT::StatusWord StatusWord;\n\n    // Fields\n    _TempStorage&               temp_storage;       ///< Reference to a warp-reduction instance\n    ScanTileStateT&             tile_status;        ///< Interface to tile status\n    ScanOpT                     scan_op;            ///< Binary scan operator\n    int                         tile_idx;           ///< The current tile index\n    T                           exclusive_prefix;   ///< Exclusive prefix for the tile\n    T                           inclusive_prefix;   ///< Inclusive prefix for the tile\n\n    // Constructor\n    __device__ __forceinline__\n    TilePrefixCallbackOp(\n        ScanTileStateT       &tile_status,\n        TempStorage         &temp_storage,\n        ScanOpT              scan_op,\n        int                 tile_idx)\n    :\n        temp_storage(temp_storage.Alias()),\n        tile_status(tile_status),\n        scan_op(scan_op),\n        tile_idx(tile_idx) {}\n\n\n    // Block until all predecessors within the warp-wide window have non-invalid status\n    __device__ __forceinline__\n    void ProcessWindow(\n        int         predecessor_idx,        ///< Preceding tile index to inspect\n        StatusWord  &predecessor_status,    ///< [out] Preceding tile status\n        T           &window_aggregate)      ///< [out] Relevant partial reduction from this window of preceding tiles\n    {\n        T value;\n        tile_status.WaitForValid(predecessor_idx, predecessor_status, value);\n\n        // Perform a segmented reduction to get the prefix for the current window.\n        // Use the swizzled scan operator because we are now scanning *down* towards thread0.\n\n        int tail_flag = (predecessor_status == StatusWord(SCAN_TILE_INCLUSIVE));\n        window_aggregate = WarpReduceT(temp_storage.warp_reduce).TailSegmentedReduce(\n            value,\n            tail_flag,\n            SwizzleScanOp<ScanOpT>(scan_op));\n    }\n\n\n    // BlockScan prefix callback functor (called by the first warp)\n    __device__ __forceinline__\n    T operator()(T block_aggregate)\n    {\n\n        // Update our status with our tile-aggregate\n        if (threadIdx.x == 0)\n        {\n            temp_storage.block_aggregate = block_aggregate;\n            tile_status.SetPartial(tile_idx, block_aggregate);\n        }\n\n        int         predecessor_idx = tile_idx - threadIdx.x - 1;\n        StatusWord  predecessor_status;\n        T           window_aggregate;\n\n        // Wait for the warp-wide window of predecessor tiles to become valid\n        ProcessWindow(predecessor_idx, predecessor_status, window_aggregate);\n\n        // The exclusive tile prefix starts out as the current window aggregate\n        exclusive_prefix = window_aggregate;\n\n        // Keep sliding the window back until we come across a tile whose inclusive prefix is known\n        while (WARP_ALL((predecessor_status != StatusWord(SCAN_TILE_INCLUSIVE)), 0xffffffff))\n        {\n            predecessor_idx -= CUB_PTX_WARP_THREADS;\n\n            // Update exclusive tile prefix with the window prefix\n            ProcessWindow(predecessor_idx, predecessor_status, window_aggregate);\n            exclusive_prefix = scan_op(window_aggregate, exclusive_prefix);\n        }\n\n        // Compute the inclusive tile prefix and update the status for this tile\n        if (threadIdx.x == 0)\n        {\n            inclusive_prefix = scan_op(exclusive_prefix, block_aggregate);\n            tile_status.SetInclusive(tile_idx, inclusive_prefix);\n\n            temp_storage.exclusive_prefix = exclusive_prefix;\n            temp_storage.inclusive_prefix = inclusive_prefix;\n        }\n\n        // Return exclusive_prefix\n        return exclusive_prefix;\n    }\n\n    // Get the exclusive prefix stored in temporary storage\n    __device__ __forceinline__\n    T GetExclusivePrefix()\n    {\n        return temp_storage.exclusive_prefix;\n    }\n\n    // Get the inclusive prefix stored in temporary storage\n    __device__ __forceinline__\n    T GetInclusivePrefix()\n    {\n        return temp_storage.inclusive_prefix;\n    }\n\n    // Get the block aggregate stored in temporary storage\n    __device__ __forceinline__\n    T GetBlockAggregate()\n    {\n        return temp_storage.block_aggregate;\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_adjacent_difference.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockDiscontinuity class provides [<em>collective</em>](index.html#sec0) methods for flagging discontinuities within an ordered set of items partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../util_type.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\ntemplate <\n    typename    T,\n    int         BLOCK_DIM_X,\n    int         BLOCK_DIM_Y     = 1,\n    int         BLOCK_DIM_Z     = 1,\n    int         PTX_ARCH        = CUB_PTX_ARCH>\nclass BlockAdjacentDifference\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n\n    /// Shared memory storage layout type (last element from each thread's input)\n    struct _TempStorage\n    {\n        T first_items[BLOCK_THREADS];\n        T last_items[BLOCK_THREADS];\n    };\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /// Specialization for when FlagOp has third index param\n    template <typename FlagOp, bool HAS_PARAM = BinaryOpHasIdxParam<T, FlagOp>::HAS_PARAM>\n    struct ApplyOp\n    {\n        // Apply flag operator\n        static __device__ __forceinline__ T FlagT(FlagOp flag_op, const T &a, const T &b, int idx)\n        {\n            return flag_op(b, a, idx);\n        }\n    };\n\n    /// Specialization for when FlagOp does not have a third index param\n    template <typename FlagOp>\n    struct ApplyOp<FlagOp, false>\n    {\n        // Apply flag operator\n        static __device__ __forceinline__ T FlagT(FlagOp flag_op, const T &a, const T &b, int /*idx*/)\n        {\n            return flag_op(b, a);\n        }\n    };\n\n    /// Templated unrolling of item comparison (inductive case)\n    template <int ITERATION, int MAX_ITERATIONS>\n    struct Iterate\n    {\n        // Head flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagHeads(\n            int                     linear_tid,\n            FlagT                   (&flags)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            T                       (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n            FlagOp                  flag_op)                            ///< [in] Binary boolean flag predicate\n        {\n            preds[ITERATION] = input[ITERATION - 1];\n\n            flags[ITERATION] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[ITERATION],\n                input[ITERATION],\n                (linear_tid * ITEMS_PER_THREAD) + ITERATION);\n\n            Iterate<ITERATION + 1, MAX_ITERATIONS>::FlagHeads(linear_tid, flags, input, preds, flag_op);\n        }\n\n        // Tail flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagTails(\n            int                     linear_tid,\n            FlagT                   (&flags)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            FlagOp                  flag_op)                            ///< [in] Binary boolean flag predicate\n        {\n            flags[ITERATION] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITERATION],\n                input[ITERATION + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITERATION + 1);\n\n            Iterate<ITERATION + 1, MAX_ITERATIONS>::FlagTails(linear_tid, flags, input, flag_op);\n        }\n\n    };\n\n    /// Templated unrolling of item comparison (termination case)\n    template <int MAX_ITERATIONS>\n    struct Iterate<MAX_ITERATIONS, MAX_ITERATIONS>\n    {\n        // Head flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagHeads(\n            int                     /*linear_tid*/,\n            FlagT                   (&/*flags*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&/*input*/)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            T                       (&/*preds*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n            FlagOp                  /*flag_op*/)                            ///< [in] Binary boolean flag predicate\n        {}\n\n        // Tail flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagTails(\n            int                     /*linear_tid*/,\n            FlagT                   (&/*flags*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&/*input*/)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            FlagOp                  /*flag_op*/)                            ///< [in] Binary boolean flag predicate\n        {}\n    };\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\npublic:\n\n    /// \\smemstorage{BlockDiscontinuity}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockAdjacentDifference()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockAdjacentDifference(\n        TempStorage &temp_storage)  ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Head flag operations\n     *********************************************************************/\n    //@{\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        T               (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share last item\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        if (linear_tid == 0)\n        {\n            // Set flag for first thread-item (preds[0] is undefined)\n            head_flags[0] = 1;\n        }\n        else\n        {\n            preds[0] = temp_storage.last_items[linear_tid - 1];\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(flag_op, preds[0], input[0], linear_tid * ITEMS_PER_THREAD);\n        }\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n    }\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        T               (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_predecessor_item)              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n    {\n        // Share last item\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(flag_op, preds[0], input[0], linear_tid * ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n    }\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        T preds[ITEMS_PER_THREAD];\n        FlagHeads(head_flags, input, preds, flag_op);\n    }\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_predecessor_item)              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n    {\n        T preds[ITEMS_PER_THREAD];\n        FlagHeads(head_flags, input, preds, flag_op, tile_predecessor_item);\n    }\n\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagTails(\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first item\n        temp_storage.first_items[linear_tid] = input[0];\n\n        CTA_SYNC();\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagTails(\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_successor_item)                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n    {\n        // Share first item\n        temp_storage.first_items[linear_tid] = input[0];\n\n        CTA_SYNC();\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = temp_storage.last_items[linear_tid - 1];\n        if (linear_tid == 0)\n        {\n            head_flags[0] = 1;\n        }\n        else\n        {\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[0],\n                input[0],\n                linear_tid * ITEMS_PER_THREAD);\n        }\n\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               tile_successor_item,                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        if (linear_tid == 0)\n        {\n            head_flags[0] = 1;\n        }\n        else\n        {\n            preds[0] = temp_storage.last_items[linear_tid - 1];\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[0],\n                input[0],\n                linear_tid * ITEMS_PER_THREAD);\n        }\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               tile_predecessor_item,              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            preds[0],\n            input[0],\n            linear_tid * ITEMS_PER_THREAD);\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               tile_predecessor_item,              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               tile_successor_item,                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            preds[0],\n            input[0],\n            linear_tid * ITEMS_PER_THREAD);\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/block/block_discontinuity.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockDiscontinuity class provides [<em>collective</em>](index.html#sec0) methods for flagging discontinuities within an ordered set of items partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../util_type.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief The BlockDiscontinuity class provides [<em>collective</em>](index.html#sec0) methods for flagging discontinuities within an ordered set of items partitioned across a CUDA thread block. ![](discont_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam T                The data type to be flagged.\n * \\tparam BLOCK_DIM_X      The thread block length in threads along the X dimension\n * \\tparam BLOCK_DIM_Y      <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z      <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH         <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - A set of \"head flags\" (or \"tail flags\") is often used to indicate corresponding items\n *   that differ from their predecessors (or successors).  For example, head flags are convenient\n *   for demarcating disjoint data segments as part of a segmented scan or reduction.\n * - \\blocked\n *\n * \\par Performance Considerations\n * - \\granularity\n *\n * \\par A Simple Example\n * \\blockcollective{BlockDiscontinuity}\n * \\par\n * The code snippet below illustrates the head flagging of 512 integer items that\n * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n * where each thread owns 4 consecutive items.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n *\n *     // Allocate shared memory for BlockDiscontinuity\n *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n *\n *     // Obtain a segment of consecutive items that are blocked across threads\n *     int thread_data[4];\n *     ...\n *\n *     // Collectively compute head flags for discontinuities in the segment\n *     int head_flags[4];\n *     BlockDiscontinuity(temp_storage).FlagHeads(head_flags, thread_data, cub::Inequality());\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the block of threads is\n * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], [3,4,4,4], ... }</tt>.\n * The corresponding output \\p head_flags in those threads will be\n * <tt>{ [1,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n *\n * \\par Performance Considerations\n * - Incurs zero bank conflicts for most types\n *\n */\ntemplate <\n    typename    T,\n    int         BLOCK_DIM_X,\n    int         BLOCK_DIM_Y     = 1,\n    int         BLOCK_DIM_Z     = 1,\n    int         PTX_ARCH        = CUB_PTX_ARCH>\nclass BlockDiscontinuity\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n\n    /// Shared memory storage layout type (last element from each thread's input)\n    struct _TempStorage\n    {\n        T first_items[BLOCK_THREADS];\n        T last_items[BLOCK_THREADS];\n    };\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /// Specialization for when FlagOp has third index param\n    template <typename FlagOp, bool HAS_PARAM = BinaryOpHasIdxParam<T, FlagOp>::HAS_PARAM>\n    struct ApplyOp\n    {\n        // Apply flag operator\n        static __device__ __forceinline__ bool FlagT(FlagOp flag_op, const T &a, const T &b, int idx)\n        {\n            return flag_op(a, b, idx);\n        }\n    };\n\n    /// Specialization for when FlagOp does not have a third index param\n    template <typename FlagOp>\n    struct ApplyOp<FlagOp, false>\n    {\n        // Apply flag operator\n        static __device__ __forceinline__ bool FlagT(FlagOp flag_op, const T &a, const T &b, int /*idx*/)\n        {\n            return flag_op(a, b);\n        }\n    };\n\n    /// Templated unrolling of item comparison (inductive case)\n    template <int ITERATION, int MAX_ITERATIONS>\n    struct Iterate\n    {\n        // Head flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagHeads(\n            int                     linear_tid,\n            FlagT                   (&flags)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            T                       (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n            FlagOp                  flag_op)                            ///< [in] Binary boolean flag predicate\n        {\n            preds[ITERATION] = input[ITERATION - 1];\n\n            flags[ITERATION] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[ITERATION],\n                input[ITERATION],\n                (linear_tid * ITEMS_PER_THREAD) + ITERATION);\n\n            Iterate<ITERATION + 1, MAX_ITERATIONS>::FlagHeads(linear_tid, flags, input, preds, flag_op);\n        }\n\n        // Tail flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagTails(\n            int                     linear_tid,\n            FlagT                   (&flags)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            FlagOp                  flag_op)                            ///< [in] Binary boolean flag predicate\n        {\n            flags[ITERATION] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITERATION],\n                input[ITERATION + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITERATION + 1);\n\n            Iterate<ITERATION + 1, MAX_ITERATIONS>::FlagTails(linear_tid, flags, input, flag_op);\n        }\n\n    };\n\n    /// Templated unrolling of item comparison (termination case)\n    template <int MAX_ITERATIONS>\n    struct Iterate<MAX_ITERATIONS, MAX_ITERATIONS>\n    {\n        // Head flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagHeads(\n            int                     /*linear_tid*/,\n            FlagT                   (&/*flags*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&/*input*/)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            T                       (&/*preds*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n            FlagOp                  /*flag_op*/)                            ///< [in] Binary boolean flag predicate\n        {}\n\n        // Tail flags\n        template <\n            int             ITEMS_PER_THREAD,\n            typename        FlagT,\n            typename        FlagOp>\n        static __device__ __forceinline__ void FlagTails(\n            int                     /*linear_tid*/,\n            FlagT                   (&/*flags*/)[ITEMS_PER_THREAD],         ///< [out] Calling thread's discontinuity head_flags\n            T                       (&/*input*/)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n            FlagOp                  /*flag_op*/)                            ///< [in] Binary boolean flag predicate\n        {}\n    };\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\npublic:\n\n    /// \\smemstorage{BlockDiscontinuity}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockDiscontinuity()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockDiscontinuity(\n        TempStorage &temp_storage)  ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Head flag operations\n     *********************************************************************/\n    //@{\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        T               (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share last item\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        if (linear_tid == 0)\n        {\n            // Set flag for first thread-item (preds[0] is undefined)\n            head_flags[0] = 1;\n        }\n        else\n        {\n            preds[0] = temp_storage.last_items[linear_tid - 1];\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(flag_op, preds[0], input[0], linear_tid * ITEMS_PER_THREAD);\n        }\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n    }\n\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        T               (&preds)[ITEMS_PER_THREAD],         ///< [out] Calling thread's predecessor items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_predecessor_item)              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n    {\n        // Share last item\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(flag_op, preds[0], input[0], linear_tid * ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n    }\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n    /**\n     * \\brief Sets head flags indicating discontinuities between items partitioned across the thread block, for which the first item has no reference and is always flagged.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is always flagged.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute head flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagHeads(head_flags, thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], [3,4,4,4], ... }</tt>.\n     * The corresponding output \\p head_flags in those threads will be\n     * <tt>{ [1,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        T preds[ITEMS_PER_THREAD];\n        FlagHeads(head_flags, input, preds, flag_op);\n    }\n\n\n    /**\n     * \\brief Sets head flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is compared\n     *   against \\p tile_predecessor_item.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Have thread0 obtain the predecessor item for the entire tile\n     *     int tile_predecessor_item;\n     *     if (threadIdx.x == 0) tile_predecessor_item == ...\n     *\n     *     // Collectively compute head flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagHeads(\n     *         head_flags, thread_data, cub::Inequality(), tile_predecessor_item);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], [3,4,4,4], ... }</tt>,\n     * and that \\p tile_predecessor_item is \\p 0.  The corresponding output \\p head_flags in those threads will be\n     * <tt>{ [0,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeads(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_predecessor_item)              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n    {\n        T preds[ITEMS_PER_THREAD];\n        FlagHeads(head_flags, input, preds, flag_op, tile_predecessor_item);\n    }\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Tail flag operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Sets tail flags indicating discontinuities between items partitioned across the thread block, for which the last item has no reference and is always flagged.\n     *\n     * \\par\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is always flagged.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute tail flags for discontinuities in the segment\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(tail_flags, thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>.\n     * The corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,1] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagTails(\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first item\n        temp_storage.first_items[linear_tid] = input[0];\n\n        CTA_SYNC();\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    /**\n     * \\brief Sets tail flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is compared\n     *   against \\p tile_successor_item.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Have thread127 obtain the successor item for the entire tile\n     *     int tile_successor_item;\n     *     if (threadIdx.x == 127) tile_successor_item == ...\n     *\n     *     // Collectively compute tail flags for discontinuities in the segment\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(\n     *         tail_flags, thread_data, cub::Inequality(), tile_successor_item);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>\n     * and that \\p tile_successor_item is \\p 125.  The corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,0] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagTails(\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op,                            ///< [in] Binary boolean flag predicate\n        T               tile_successor_item)                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n    {\n        // Share first item\n        temp_storage.first_items[linear_tid] = input[0];\n\n        CTA_SYNC();\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Head & tail flag operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Sets both head and tail flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is always flagged.\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is always flagged.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head- and tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute head and flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(\n     *         head_flags, tail_flags, thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>\n     * and that the tile_successor_item is \\p 125.  The corresponding output \\p head_flags\n     * in those threads will be <tt>{ [1,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     * and the corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,1] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = temp_storage.last_items[linear_tid - 1];\n        if (linear_tid == 0)\n        {\n            head_flags[0] = 1;\n        }\n        else\n        {\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[0],\n                input[0],\n                linear_tid * ITEMS_PER_THREAD);\n        }\n\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    /**\n     * \\brief Sets both head and tail flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is always flagged.\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is compared\n     *   against \\p tile_predecessor_item.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head- and tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Have thread127 obtain the successor item for the entire tile\n     *     int tile_successor_item;\n     *     if (threadIdx.x == 127) tile_successor_item == ...\n     *\n     *     // Collectively compute head and flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(\n     *         head_flags, tail_flags, tile_successor_item, thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>\n     * and that the tile_successor_item is \\p 125.  The corresponding output \\p head_flags\n     * in those threads will be <tt>{ [1,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     * and the corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,0] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               tile_successor_item,                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        if (linear_tid == 0)\n        {\n            head_flags[0] = 1;\n        }\n        else\n        {\n            preds[0] = temp_storage.last_items[linear_tid - 1];\n            head_flags[0] = ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                preds[0],\n                input[0],\n                linear_tid * ITEMS_PER_THREAD);\n        }\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    /**\n     * \\brief Sets both head and tail flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is compared\n     *   against \\p tile_predecessor_item.\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is always flagged.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head- and tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Have thread0 obtain the predecessor item for the entire tile\n     *     int tile_predecessor_item;\n     *     if (threadIdx.x == 0) tile_predecessor_item == ...\n     *\n     *     // Have thread127 obtain the successor item for the entire tile\n     *     int tile_successor_item;\n     *     if (threadIdx.x == 127) tile_successor_item == ...\n     *\n     *     // Collectively compute head and flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(\n     *         head_flags, tile_predecessor_item, tail_flags, tile_successor_item,\n     *         thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>,\n     * that the \\p tile_predecessor_item is \\p 0, and that the\n     * \\p tile_successor_item is \\p 125.  The corresponding output \\p head_flags\n     * in those threads will be <tt>{ [0,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     * and the corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,1] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               tile_predecessor_item,              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            preds[0],\n            input[0],\n            linear_tid * ITEMS_PER_THREAD);\n\n        // Set flag for last thread-item\n        tail_flags[ITEMS_PER_THREAD - 1] = (linear_tid == BLOCK_THREADS - 1) ?\n            1 :                             // Last thread\n            ApplyOp<FlagOp>::FlagT(\n                flag_op,\n                input[ITEMS_PER_THREAD - 1],\n                temp_storage.first_items[linear_tid + 1],\n                (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n    /**\n     * \\brief Sets both head and tail flags indicating discontinuities between items partitioned across the thread block.\n     *\n     * \\par\n     * - The flag <tt>head_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(</tt><em>previous-item</em><tt>, input<sub><em>i</em></sub>)</tt>\n     *   returns \\p true (where <em>previous-item</em> is either the preceding item\n     *   in the same thread or the last item in the previous thread).\n     * - For <em>thread</em><sub>0</sub>, item <tt>input<sub>0</sub></tt> is compared\n     *   against \\p tile_predecessor_item.\n     * - The flag <tt>tail_flags<sub><em>i</em></sub></tt> is set for item\n     *   <tt>input<sub><em>i</em></sub></tt> when\n     *   <tt>flag_op(input<sub><em>i</em></sub>, </tt><em>next-item</em><tt>)</tt>\n     *   returns \\p true (where <em>next-item</em> is either the next item\n     *   in the same thread or the first item in the next thread).\n     * - For <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>, item\n     *   <tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> is compared\n     *   against \\p tile_successor_item.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the head- and tail-flagging of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_discontinuity.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockDiscontinuity for a 1D block of 128 threads on type int\n     *     typedef cub::BlockDiscontinuity<int, 128> BlockDiscontinuity;\n     *\n     *     // Allocate shared memory for BlockDiscontinuity\n     *     __shared__ typename BlockDiscontinuity::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Have thread0 obtain the predecessor item for the entire tile\n     *     int tile_predecessor_item;\n     *     if (threadIdx.x == 0) tile_predecessor_item == ...\n     *\n     *     // Have thread127 obtain the successor item for the entire tile\n     *     int tile_successor_item;\n     *     if (threadIdx.x == 127) tile_successor_item == ...\n     *\n     *     // Collectively compute head and flags for discontinuities in the segment\n     *     int head_flags[4];\n     *     int tail_flags[4];\n     *     BlockDiscontinuity(temp_storage).FlagTails(\n     *         head_flags, tile_predecessor_item, tail_flags, tile_successor_item,\n     *         thread_data, cub::Inequality());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,0,1,1], [1,1,1,1], [2,3,3,3], ..., [124,125,125,125] }</tt>,\n     * that the \\p tile_predecessor_item is \\p 0, and that the\n     * \\p tile_successor_item is \\p 125.  The corresponding output \\p head_flags\n     * in those threads will be <tt>{ [0,0,1,0], [0,0,0,0], [1,1,0,0], [0,1,0,0], ... }</tt>.\n     * and the corresponding output \\p tail_flags in those threads will be\n     * <tt>{ [0,1,0,0], [0,0,0,1], [1,0,0,...], ..., [1,0,0,0] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam FlagT                <b>[inferred]</b> The flag type (must be an integer type)\n     * \\tparam FlagOp               <b>[inferred]</b> Binary predicate functor type having member <tt>T operator()(const T &a, const T &b)</tt> or member <tt>T operator()(const T &a, const T &b, unsigned int b_index)</tt>, and returning \\p true if a discontinuity exists between \\p a and \\p b, otherwise \\p false.  \\p b_index is the rank of b in the aggregate tile of data.\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        FlagT,\n        typename        FlagOp>\n    __device__ __forceinline__ void FlagHeadsAndTails(\n        FlagT           (&head_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity head_flags\n        T               tile_predecessor_item,              ///< [in] <b>[<em>thread</em><sub>0</sub> only]</b> Item with which to compare the first tile item (<tt>input<sub>0</sub></tt> from <em>thread</em><sub>0</sub>).\n        FlagT           (&tail_flags)[ITEMS_PER_THREAD],    ///< [out] Calling thread's discontinuity tail_flags\n        T               tile_successor_item,                ///< [in] <b>[<em>thread</em><sub><tt>BLOCK_THREADS</tt>-1</sub> only]</b> Item with which to compare the last tile item (<tt>input</tt><sub><em>ITEMS_PER_THREAD</em>-1</sub> from <em>thread</em><sub><em>BLOCK_THREADS</em>-1</sub>).\n        T               (&input)[ITEMS_PER_THREAD],         ///< [in] Calling thread's input items\n        FlagOp          flag_op)                            ///< [in] Binary boolean flag predicate\n    {\n        // Share first and last items\n        temp_storage.first_items[linear_tid] = input[0];\n        temp_storage.last_items[linear_tid] = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        T preds[ITEMS_PER_THREAD];\n\n        // Set flag for first thread-item\n        preds[0] = (linear_tid == 0) ?\n            tile_predecessor_item :              // First thread\n            temp_storage.last_items[linear_tid - 1];\n\n        head_flags[0] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            preds[0],\n            input[0],\n            linear_tid * ITEMS_PER_THREAD);\n\n        // Set flag for last thread-item\n        T successor_item = (linear_tid == BLOCK_THREADS - 1) ?\n            tile_successor_item :              // Last thread\n            temp_storage.first_items[linear_tid + 1];\n\n        tail_flags[ITEMS_PER_THREAD - 1] = ApplyOp<FlagOp>::FlagT(\n            flag_op,\n            input[ITEMS_PER_THREAD - 1],\n            successor_item,\n            (linear_tid * ITEMS_PER_THREAD) + ITEMS_PER_THREAD);\n\n        // Set head_flags for remaining items\n        Iterate<1, ITEMS_PER_THREAD>::FlagHeads(linear_tid, head_flags, input, preds, flag_op);\n\n        // Set tail_flags for remaining items\n        Iterate<0, ITEMS_PER_THREAD - 1>::FlagTails(linear_tid, tail_flags, input, flag_op);\n    }\n\n\n\n\n    //@}  end member group\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/block/block_exchange.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockExchange class provides [<em>collective</em>](index.html#sec0) methods for rearranging data partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../util_ptx.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_macro.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief The BlockExchange class provides [<em>collective</em>](index.html#sec0) methods for rearranging data partitioned across a CUDA thread block. ![](transpose_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam T                    The data type to be exchanged.\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam ITEMS_PER_THREAD     The number of items partitioned onto each thread.\n * \\tparam WARP_TIME_SLICING    <b>[optional]</b> When \\p true, only use enough shared memory for a single warp's worth of tile data, time-slicing the block-wide exchange over multiple synchronized rounds.  Yields a smaller memory footprint at the expense of decreased parallelism.  (Default: false)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - It is commonplace for blocks of threads to rearrange data items between\n *   threads.  For example, the device-accessible memory subsystem prefers access patterns\n *   where data items are \"striped\" across threads (where consecutive threads access consecutive items),\n *   yet most block-wide operations prefer a \"blocked\" partitioning of items across threads\n *   (where consecutive items belong to a single thread).\n * - BlockExchange supports the following types of data exchanges:\n *   - Transposing between [<em>blocked</em>](index.html#sec5sec3) and [<em>striped</em>](index.html#sec5sec3) arrangements\n *   - Transposing between [<em>blocked</em>](index.html#sec5sec3) and [<em>warp-striped</em>](index.html#sec5sec3) arrangements\n *   - Scattering ranked items to a [<em>blocked arrangement</em>](index.html#sec5sec3)\n *   - Scattering ranked items to a [<em>striped arrangement</em>](index.html#sec5sec3)\n * - \\rowmajor\n *\n * \\par A Simple Example\n * \\blockcollective{BlockExchange}\n * \\par\n * The code snippet below illustrates the conversion from a \"blocked\" to a \"striped\" arrangement\n * of 512 integer items partitioned across 128 threads where each thread owns 4 items.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_exchange.cuh>\n *\n * __global__ void ExampleKernel(int *d_data, ...)\n * {\n *     // Specialize BlockExchange for a 1D block of 128 threads owning 4 integer items each\n *     typedef cub::BlockExchange<int, 128, 4> BlockExchange;\n *\n *     // Allocate shared memory for BlockExchange\n *     __shared__ typename BlockExchange::TempStorage temp_storage;\n *\n *     // Load a tile of data striped across threads\n *     int thread_data[4];\n *     cub::LoadDirectStriped<128>(threadIdx.x, d_data, thread_data);\n *\n *     // Collectively exchange data into a blocked arrangement across threads\n *     BlockExchange(temp_storage).StripedToBlocked(thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of striped input \\p thread_data across the block of threads is\n * <tt>{ [0,128,256,384], [1,129,257,385], ..., [127,255,383,511] }</tt>.\n * The corresponding output \\p thread_data in those threads will be\n * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n *\n * \\par Performance Considerations\n * - Proper device-specific padding ensures zero bank conflicts for most types.\n *\n */\ntemplate <\n    typename    InputT,\n    int         BLOCK_DIM_X,\n    int         ITEMS_PER_THREAD,\n    bool        WARP_TIME_SLICING   = false,\n    int         BLOCK_DIM_Y         = 1,\n    int         BLOCK_DIM_Z         = 1,\n    int         PTX_ARCH            = CUB_PTX_ARCH>\nclass BlockExchange\n{\nprivate:\n\n    /******************************************************************************\n     * Constants\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS               = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        LOG_WARP_THREADS            = CUB_LOG_WARP_THREADS(PTX_ARCH),\n        WARP_THREADS                = 1 << LOG_WARP_THREADS,\n        WARPS                       = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        LOG_SMEM_BANKS              = CUB_LOG_SMEM_BANKS(PTX_ARCH),\n        SMEM_BANKS                  = 1 << LOG_SMEM_BANKS,\n\n        TILE_ITEMS                  = BLOCK_THREADS * ITEMS_PER_THREAD,\n\n        TIME_SLICES                 = (WARP_TIME_SLICING) ? WARPS : 1,\n\n        TIME_SLICED_THREADS         = (WARP_TIME_SLICING) ? CUB_MIN(BLOCK_THREADS, WARP_THREADS) : BLOCK_THREADS,\n        TIME_SLICED_ITEMS           = TIME_SLICED_THREADS * ITEMS_PER_THREAD,\n\n        WARP_TIME_SLICED_THREADS    = CUB_MIN(BLOCK_THREADS, WARP_THREADS),\n        WARP_TIME_SLICED_ITEMS      = WARP_TIME_SLICED_THREADS * ITEMS_PER_THREAD,\n\n        // Insert padding to avoid bank conflicts during raking when items per thread is a power of two and > 4 (otherwise we can typically use 128b loads)\n        INSERT_PADDING              = (ITEMS_PER_THREAD > 4) && (PowerOfTwo<ITEMS_PER_THREAD>::VALUE),\n        PADDING_ITEMS               = (INSERT_PADDING) ? (TIME_SLICED_ITEMS >> LOG_SMEM_BANKS) : 0,\n    };\n\n    /******************************************************************************\n     * Type definitions\n     ******************************************************************************/\n\n    /// Shared memory storage layout type\n    struct __align__(16) _TempStorage\n    {\n        InputT buff[TIME_SLICED_ITEMS + PADDING_ITEMS];\n    };\n\npublic:\n\n    /// \\smemstorage{BlockExchange}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\nprivate:\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n    unsigned int lane_id;\n    unsigned int warp_id;\n    unsigned int warp_offset;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /**\n     * Transposes data items from <em>blocked</em> arrangement to <em>striped</em> arrangement.  Specialized for no timeslicing.\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = (linear_tid * ITEMS_PER_THREAD) + ITEM;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = int(ITEM * BLOCK_THREADS) + linear_tid;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>blocked</em> arrangement to <em>striped</em> arrangement.  Specialized for warp-timeslicing.\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<true>  /*time_slicing*/)\n    {\n        InputT temp_items[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int SLICE = 0; SLICE < TIME_SLICES; SLICE++)\n        {\n            const int SLICE_OFFSET  = SLICE * TIME_SLICED_ITEMS;\n            const int SLICE_OOB     = SLICE_OFFSET + TIME_SLICED_ITEMS;\n\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = (lane_id * ITEMS_PER_THREAD) + ITEM;\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    temp_storage.buff[item_offset] = input_items[ITEM];\n                }\n            }\n\n            CTA_SYNC();\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                // Read a strip of items\n                const int STRIP_OFFSET  = ITEM * BLOCK_THREADS;\n                const int STRIP_OOB     = STRIP_OFFSET + BLOCK_THREADS;\n\n                if ((SLICE_OFFSET < STRIP_OOB) && (SLICE_OOB > STRIP_OFFSET))\n                {\n                    int item_offset = STRIP_OFFSET + linear_tid - SLICE_OFFSET;\n                    if ((item_offset >= 0) && (item_offset < TIME_SLICED_ITEMS))\n                    {\n                        if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                        temp_items[ITEM] = temp_storage.buff[item_offset];\n                    }\n                }\n            }\n        }\n\n        // Copy\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            output_items[ITEM] = temp_items[ITEM];\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>blocked</em> arrangement to <em>warp-striped</em> arrangement. Specialized for no timeslicing\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToWarpStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = warp_offset + ITEM + (lane_id * ITEMS_PER_THREAD);\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        WARP_SYNC(0xffffffff);\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = warp_offset + (ITEM * WARP_TIME_SLICED_THREADS) + lane_id;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n    /**\n     * Transposes data items from <em>blocked</em> arrangement to <em>warp-striped</em> arrangement. Specialized for warp-timeslicing\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToWarpStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<true>  /*time_slicing*/)\n    {\n        if (warp_id == 0)\n        {\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                int item_offset = ITEM + (lane_id * ITEMS_PER_THREAD);\n                if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                temp_storage.buff[item_offset] = input_items[ITEM];\n            }\n\n            WARP_SYNC(0xffffffff);\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                int item_offset = (ITEM * WARP_TIME_SLICED_THREADS) + lane_id;\n                if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                output_items[ITEM] = temp_storage.buff[item_offset];\n            }\n        }\n\n        #pragma unroll\n        for (unsigned int SLICE = 1; SLICE < TIME_SLICES; ++SLICE)\n        {\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = ITEM + (lane_id * ITEMS_PER_THREAD);\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    temp_storage.buff[item_offset] = input_items[ITEM];\n                }\n\n                WARP_SYNC(0xffffffff);\n\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = (ITEM * WARP_TIME_SLICED_THREADS) + lane_id;\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    output_items[ITEM] = temp_storage.buff[item_offset];\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>striped</em> arrangement to <em>blocked</em> arrangement.  Specialized for no timeslicing.\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void StripedToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = int(ITEM * BLOCK_THREADS) + linear_tid;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        // No timeslicing\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = (linear_tid * ITEMS_PER_THREAD) + ITEM;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>striped</em> arrangement to <em>blocked</em> arrangement.  Specialized for warp-timeslicing.\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void StripedToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<true>  /*time_slicing*/)\n    {\n        // Warp time-slicing\n        InputT temp_items[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int SLICE = 0; SLICE < TIME_SLICES; SLICE++)\n        {\n            const int SLICE_OFFSET  = SLICE * TIME_SLICED_ITEMS;\n            const int SLICE_OOB     = SLICE_OFFSET + TIME_SLICED_ITEMS;\n\n            CTA_SYNC();\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                // Write a strip of items\n                const int STRIP_OFFSET  = ITEM * BLOCK_THREADS;\n                const int STRIP_OOB     = STRIP_OFFSET + BLOCK_THREADS;\n\n                if ((SLICE_OFFSET < STRIP_OOB) && (SLICE_OOB > STRIP_OFFSET))\n                {\n                    int item_offset = STRIP_OFFSET + linear_tid - SLICE_OFFSET;\n                    if ((item_offset >= 0) && (item_offset < TIME_SLICED_ITEMS))\n                    {\n                        if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                        temp_storage.buff[item_offset] = input_items[ITEM];\n                    }\n                }\n            }\n\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = (lane_id * ITEMS_PER_THREAD) + ITEM;\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    temp_items[ITEM] = temp_storage.buff[item_offset];\n                }\n            }\n        }\n\n        // Copy\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            output_items[ITEM] = temp_items[ITEM];\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>warp-striped</em> arrangement to <em>blocked</em> arrangement.  Specialized for no timeslicing\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void WarpStripedToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = warp_offset + (ITEM * WARP_TIME_SLICED_THREADS) + lane_id;\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        WARP_SYNC(0xffffffff);\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = warp_offset + ITEM + (lane_id * ITEMS_PER_THREAD);\n            if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n    /**\n     * Transposes data items from <em>warp-striped</em> arrangement to <em>blocked</em> arrangement.  Specialized for warp-timeslicing\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void WarpStripedToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        Int2Type<true>  /*time_slicing*/)\n    {\n        #pragma unroll\n        for (unsigned int SLICE = 0; SLICE < TIME_SLICES; ++SLICE)\n        {\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = (ITEM * WARP_TIME_SLICED_THREADS) + lane_id;\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    temp_storage.buff[item_offset] = input_items[ITEM];\n                }\n\n                WARP_SYNC(0xffffffff);\n\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = ITEM + (lane_id * ITEMS_PER_THREAD);\n                    if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                    output_items[ITEM] = temp_storage.buff[item_offset];\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Exchanges data items annotated by rank into <em>blocked</em> arrangement.  Specialized for no timeslicing.\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OffsetT         ranks[ITEMS_PER_THREAD],    ///< [in] Corresponding scatter ranks\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = ranks[ITEM];\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = (linear_tid * ITEMS_PER_THREAD) + ITEM;\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n    /**\n     * Exchanges data items annotated by rank into <em>blocked</em> arrangement.  Specialized for warp-timeslicing.\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToBlocked(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OffsetT         ranks[ITEMS_PER_THREAD],    ///< [in] Corresponding scatter ranks\n        Int2Type<true>  /*time_slicing*/)\n    {\n        InputT temp_items[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int SLICE = 0; SLICE < TIME_SLICES; SLICE++)\n        {\n            CTA_SYNC();\n\n            const int SLICE_OFFSET = TIME_SLICED_ITEMS * SLICE;\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                int item_offset = ranks[ITEM] - SLICE_OFFSET;\n                if ((item_offset >= 0) && (item_offset < WARP_TIME_SLICED_ITEMS))\n                {\n                    if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n                    temp_storage.buff[item_offset] = input_items[ITEM];\n                }\n            }\n\n            CTA_SYNC();\n\n            if (warp_id == SLICE)\n            {\n                #pragma unroll\n                for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n                {\n                    int item_offset = (lane_id * ITEMS_PER_THREAD) + ITEM;\n                    if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n                    temp_items[ITEM] = temp_storage.buff[item_offset];\n                }\n            }\n        }\n\n        // Copy\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            output_items[ITEM] = temp_items[ITEM];\n        }\n    }\n\n\n    /**\n     * Exchanges data items annotated by rank into <em>striped</em> arrangement.  Specialized for no timeslicing.\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OffsetT         ranks[ITEMS_PER_THREAD],    ///< [in] Corresponding scatter ranks\n        Int2Type<false> /*time_slicing*/)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = ranks[ITEM];\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = int(ITEM * BLOCK_THREADS) + linear_tid;\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n    /**\n     * Exchanges data items annotated by rank into <em>striped</em> arrangement.  Specialized for warp-timeslicing.\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToStriped(\n        InputT          input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OutputT         output_items[ITEMS_PER_THREAD],     ///< [out] Items to exchange, converting between <em>blocked</em> and <em>striped</em> arrangements.\n        OffsetT         ranks[ITEMS_PER_THREAD],    ///< [in] Corresponding scatter ranks\n        Int2Type<true> /*time_slicing*/)\n    {\n        InputT temp_items[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int SLICE = 0; SLICE < TIME_SLICES; SLICE++)\n        {\n            const int SLICE_OFFSET  = SLICE * TIME_SLICED_ITEMS;\n            const int SLICE_OOB     = SLICE_OFFSET + TIME_SLICED_ITEMS;\n\n            CTA_SYNC();\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                int item_offset = ranks[ITEM] - SLICE_OFFSET;\n                if ((item_offset >= 0) && (item_offset < WARP_TIME_SLICED_ITEMS))\n                {\n                    if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n                    temp_storage.buff[item_offset] = input_items[ITEM];\n                }\n            }\n\n            CTA_SYNC();\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n            {\n                // Read a strip of items\n                const int STRIP_OFFSET  = ITEM * BLOCK_THREADS;\n                const int STRIP_OOB     = STRIP_OFFSET + BLOCK_THREADS;\n\n                if ((SLICE_OFFSET < STRIP_OOB) && (SLICE_OOB > STRIP_OFFSET))\n                {\n                    int item_offset = STRIP_OFFSET + linear_tid - SLICE_OFFSET;\n                    if ((item_offset >= 0) && (item_offset < TIME_SLICED_ITEMS))\n                    {\n                        if (INSERT_PADDING) item_offset += item_offset >> LOG_SMEM_BANKS;\n                        temp_items[ITEM] = temp_storage.buff[item_offset];\n                    }\n                }\n            }\n        }\n\n        // Copy\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            output_items[ITEM] = temp_items[ITEM];\n        }\n    }\n\n\npublic:\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockExchange()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        warp_id((WARPS == 1) ? 0 : linear_tid / WARP_THREADS),\n        lane_id(LaneId()),\n        warp_offset(warp_id * WARP_TIME_SLICED_ITEMS)\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockExchange(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        lane_id(LaneId()),\n        warp_id((WARPS == 1) ? 0 : linear_tid / WARP_THREADS),\n        warp_offset(warp_id * WARP_TIME_SLICED_ITEMS)\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Structured exchanges\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Transposes data items from <em>striped</em> arrangement to <em>blocked</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the conversion from a \"striped\" to a \"blocked\" arrangement\n     * of 512 integer items partitioned across 128 threads where each thread owns 4 items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_exchange.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockExchange for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockExchange<int, 128, 4> BlockExchange;\n     *\n     *     // Allocate shared memory for BlockExchange\n     *     __shared__ typename BlockExchange::TempStorage temp_storage;\n     *\n     *     // Load a tile of ordered data into a striped arrangement across block threads\n     *     int thread_data[4];\n     *     cub::LoadDirectStriped<128>(threadIdx.x, d_data, thread_data);\n     *\n     *     // Collectively exchange data into a blocked arrangement across threads\n     *     BlockExchange(temp_storage).StripedToBlocked(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of striped input \\p thread_data across the block of threads is\n     * <tt>{ [0,128,256,384], [1,129,257,385], ..., [127,255,383,511] }</tt> after loading from device-accessible memory.\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     *\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void StripedToBlocked(\n        InputT      input_items[ITEMS_PER_THREAD],    ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD])   ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        StripedToBlocked(input_items, output_items, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n    /**\n     * \\brief Transposes data items from <em>blocked</em> arrangement to <em>striped</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the conversion from a \"blocked\" to a \"striped\" arrangement\n     * of 512 integer items partitioned across 128 threads where each thread owns 4 items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_exchange.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockExchange for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockExchange<int, 128, 4> BlockExchange;\n     *\n     *     // Allocate shared memory for BlockExchange\n     *     __shared__ typename BlockExchange::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively exchange data into a striped arrangement across threads\n     *     BlockExchange(temp_storage).BlockedToStriped(thread_data, thread_data);\n     *\n     *     // Store data striped across block threads into an ordered tile\n     *     cub::StoreDirectStriped<STORE_DEFAULT, 128>(threadIdx.x, d_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of blocked input \\p thread_data across the block of threads is\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [0,128,256,384], [1,129,257,385], ..., [127,255,383,511] }</tt> in\n     * preparation for storing to device-accessible memory.\n     *\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToStriped(\n        InputT      input_items[ITEMS_PER_THREAD],    ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD])   ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        BlockedToStriped(input_items, output_items, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n\n    /**\n     * \\brief Transposes data items from <em>warp-striped</em> arrangement to <em>blocked</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the conversion from a \"warp-striped\" to a \"blocked\" arrangement\n     * of 512 integer items partitioned across 128 threads where each thread owns 4 items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_exchange.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockExchange for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockExchange<int, 128, 4> BlockExchange;\n     *\n     *     // Allocate shared memory for BlockExchange\n     *     __shared__ typename BlockExchange::TempStorage temp_storage;\n     *\n     *     // Load a tile of ordered data into a warp-striped arrangement across warp threads\n     *     int thread_data[4];\n     *     cub::LoadSWarptriped<LOAD_DEFAULT>(threadIdx.x, d_data, thread_data);\n     *\n     *     // Collectively exchange data into a blocked arrangement across threads\n     *     BlockExchange(temp_storage).WarpStripedToBlocked(thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of warp-striped input \\p thread_data across the block of threads is\n     * <tt>{ [0,32,64,96], [1,33,65,97], [2,34,66,98], ..., [415,447,479,511] }</tt>\n     * after loading from device-accessible memory.  (The first 128 items are striped across\n     * the first warp of 32 threads, the second 128 items are striped across the second warp, etc.)\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     *\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void WarpStripedToBlocked(\n        InputT      input_items[ITEMS_PER_THREAD],    ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD])   ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        WarpStripedToBlocked(input_items, output_items, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n\n    /**\n     * \\brief Transposes data items from <em>blocked</em> arrangement to <em>warp-striped</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the conversion from a \"blocked\" to a \"warp-striped\" arrangement\n     * of 512 integer items partitioned across 128 threads where each thread owns 4 items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_exchange.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockExchange for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockExchange<int, 128, 4> BlockExchange;\n     *\n     *     // Allocate shared memory for BlockExchange\n     *     __shared__ typename BlockExchange::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively exchange data into a warp-striped arrangement across threads\n     *     BlockExchange(temp_storage).BlockedToWarpStriped(thread_data, thread_data);\n     *\n     *     // Store data striped across warp threads into an ordered tile\n     *     cub::StoreDirectStriped<STORE_DEFAULT, 128>(threadIdx.x, d_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of blocked input \\p thread_data across the block of threads is\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [0,32,64,96], [1,33,65,97], [2,34,66,98], ..., [415,447,479,511] }</tt>\n     * in preparation for storing to device-accessible memory. (The first 128 items are striped across\n     * the first warp of 32 threads, the second 128 items are striped across the second warp, etc.)\n     *\n     */\n    template <typename OutputT>\n    __device__ __forceinline__ void BlockedToWarpStriped(\n        InputT      input_items[ITEMS_PER_THREAD],    ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD])   ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        BlockedToWarpStriped(input_items, output_items, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Scatter exchanges\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Exchanges data items annotated by rank into <em>blocked</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\tparam OffsetT                              <b>[inferred]</b> Signed integer type for local offsets\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToBlocked(\n        InputT      input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD],     ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])            ///< [in] Corresponding scatter ranks\n    {\n        ScatterToBlocked(input_items, output_items, ranks, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n\n    /**\n     * \\brief Exchanges data items annotated by rank into <em>striped</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\tparam OffsetT                              <b>[inferred]</b> Signed integer type for local offsets\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToStriped(\n        InputT      input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD],     ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])            ///< [in] Corresponding scatter ranks\n    {\n        ScatterToStriped(input_items, output_items, ranks, Int2Type<WARP_TIME_SLICING>());\n    }\n\n\n\n    /**\n     * \\brief Exchanges data items annotated by rank into <em>striped</em> arrangement.  Items with rank -1 are not exchanged.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\tparam OffsetT                              <b>[inferred]</b> Signed integer type for local offsets\n     */\n    template <typename OutputT, typename OffsetT>\n    __device__ __forceinline__ void ScatterToStripedGuarded(\n        InputT      input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD],     ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])            ///< [in] Corresponding scatter ranks\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = ranks[ITEM];\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            if (ranks[ITEM] >= 0)\n                temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = int(ITEM * BLOCK_THREADS) + linear_tid;\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n\n\n    /**\n     * \\brief Exchanges valid data items annotated by rank into <em>striped</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\tparam OffsetT                              <b>[inferred]</b> Signed integer type for local offsets\n     * \\tparam ValidFlag                            <b>[inferred]</b> FlagT type denoting which items are valid\n     */\n    template <typename OutputT, typename OffsetT, typename ValidFlag>\n    __device__ __forceinline__ void ScatterToStripedFlagged(\n        InputT      input_items[ITEMS_PER_THREAD],      ///< [in] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OutputT     output_items[ITEMS_PER_THREAD],     ///< [out] Items from exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD],            ///< [in] Corresponding scatter ranks\n        ValidFlag   is_valid[ITEMS_PER_THREAD])         ///< [in] Corresponding flag denoting item validity\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = ranks[ITEM];\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            if (is_valid[ITEM])\n                temp_storage.buff[item_offset] = input_items[ITEM];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = int(ITEM * BLOCK_THREADS) + linear_tid;\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            output_items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n\n    //@}  end member group\n\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n    __device__ __forceinline__ void StripedToBlocked(\n        InputT      items[ITEMS_PER_THREAD])   ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        StripedToBlocked(items, items);\n    }\n\n    __device__ __forceinline__ void BlockedToStriped(\n        InputT      items[ITEMS_PER_THREAD])   ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        BlockedToStriped(items, items);\n    }\n\n    __device__ __forceinline__ void WarpStripedToBlocked(\n        InputT      items[ITEMS_PER_THREAD])    ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        WarpStripedToBlocked(items, items);\n    }\n\n    __device__ __forceinline__ void BlockedToWarpStriped(\n        InputT      items[ITEMS_PER_THREAD])    ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n    {\n        BlockedToWarpStriped(items, items);\n    }\n\n    template <typename OffsetT>\n    __device__ __forceinline__ void ScatterToBlocked(\n        InputT      items[ITEMS_PER_THREAD],    ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])    ///< [in] Corresponding scatter ranks\n    {\n        ScatterToBlocked(items, items, ranks);\n    }\n\n    template <typename OffsetT>\n    __device__ __forceinline__ void ScatterToStriped(\n        InputT      items[ITEMS_PER_THREAD],    ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])    ///< [in] Corresponding scatter ranks\n    {\n        ScatterToStriped(items, items, ranks);\n    }\n\n    template <typename OffsetT>\n    __device__ __forceinline__ void ScatterToStripedGuarded(\n        InputT      items[ITEMS_PER_THREAD],    ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD])    ///< [in] Corresponding scatter ranks\n    {\n        ScatterToStripedGuarded(items, items, ranks);\n    }\n\n    template <typename OffsetT, typename ValidFlag>\n    __device__ __forceinline__ void ScatterToStripedFlagged(\n        InputT      items[ITEMS_PER_THREAD],        ///< [in-out] Items to exchange, converting between <em>striped</em> and <em>blocked</em> arrangements.\n        OffsetT     ranks[ITEMS_PER_THREAD],        ///< [in] Corresponding scatter ranks\n        ValidFlag   is_valid[ITEMS_PER_THREAD])     ///< [in] Corresponding flag denoting item validity\n    {\n        ScatterToStriped(items, items, ranks, is_valid);\n    }\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n};\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\ntemplate <\n    typename    T,\n    int         ITEMS_PER_THREAD,\n    int         LOGICAL_WARP_THREADS    = CUB_PTX_WARP_THREADS,\n    int         PTX_ARCH                = CUB_PTX_ARCH>\nclass WarpExchange\n{\nprivate:\n\n    /******************************************************************************\n     * Constants\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        // Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        WARP_ITEMS                  = (ITEMS_PER_THREAD * LOGICAL_WARP_THREADS) + 1,\n\n        LOG_SMEM_BANKS              = CUB_LOG_SMEM_BANKS(PTX_ARCH),\n        SMEM_BANKS                  = 1 << LOG_SMEM_BANKS,\n\n        // Insert padding if the number of items per thread is a power of two and > 4 (otherwise we can typically use 128b loads)\n        INSERT_PADDING              = (ITEMS_PER_THREAD > 4) && (PowerOfTwo<ITEMS_PER_THREAD>::VALUE),\n        PADDING_ITEMS               = (INSERT_PADDING) ? (WARP_ITEMS >> LOG_SMEM_BANKS) : 0,\n    };\n\n    /******************************************************************************\n     * Type definitions\n     ******************************************************************************/\n\n    /// Shared memory storage layout type\n    struct _TempStorage\n    {\n        T buff[WARP_ITEMS + PADDING_ITEMS];\n    };\n\npublic:\n\n    /// \\smemstorage{WarpExchange}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\nprivate:\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    _TempStorage    &temp_storage;\n    int             lane_id;\n\npublic:\n\n    /******************************************************************************\n     * Construction\n     ******************************************************************************/\n\n    /// Constructor\n    __device__ __forceinline__ WarpExchange(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        lane_id(IS_ARCH_WARP ?\n            LaneId() :\n            LaneId() % LOGICAL_WARP_THREADS)\n    {}\n\n\n    /******************************************************************************\n     * Interface\n     ******************************************************************************/\n\n    /**\n     * \\brief Exchanges valid data items annotated by rank into <em>striped</em> arrangement.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\tparam OffsetT                              <b>[inferred]</b> Signed integer type for local offsets\n     */\n    template <typename OffsetT>\n    __device__ __forceinline__ void ScatterToStriped(\n        T               items[ITEMS_PER_THREAD],        ///< [in-out] Items to exchange\n        OffsetT         ranks[ITEMS_PER_THREAD])        ///< [in] Corresponding scatter ranks\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if (INSERT_PADDING) ranks[ITEM] = SHR_ADD(ranks[ITEM], LOG_SMEM_BANKS, ranks[ITEM]);\n            temp_storage.buff[ranks[ITEM]] = items[ITEM];\n        }\n\n        WARP_SYNC(0xffffffff);\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            int item_offset = (ITEM * LOGICAL_WARP_THREADS) + lane_id;\n            if (INSERT_PADDING) item_offset = SHR_ADD(item_offset, LOG_SMEM_BANKS, item_offset);\n            items[ITEM] = temp_storage.buff[item_offset];\n        }\n    }\n\n};\n\n\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_histogram.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockHistogram class provides [<em>collective</em>](index.html#sec0) methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"specializations/block_histogram_sort.cuh\"\n#include \"specializations/block_histogram_atomic.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Algorithmic variants\n ******************************************************************************/\n\n/**\n * \\brief BlockHistogramAlgorithm enumerates alternative algorithms for the parallel construction of block-wide histograms.\n */\nenum BlockHistogramAlgorithm\n{\n\n    /**\n     * \\par Overview\n     * Sorting followed by differentiation.  Execution is comprised of two phases:\n     * -# Sort the data using efficient radix sort\n     * -# Look for \"runs\" of same-valued keys by detecting discontinuities; the run-lengths are histogram bin counts.\n     *\n     * \\par Performance Considerations\n     * Delivers consistent throughput regardless of sample bin distribution.\n     */\n    BLOCK_HISTO_SORT,\n\n\n    /**\n     * \\par Overview\n     * Use atomic addition to update byte counts directly\n     *\n     * \\par Performance Considerations\n     * Performance is strongly tied to the hardware implementation of atomic\n     * addition, and may be significantly degraded for non uniformly-random\n     * input distributions where many concurrent updates are likely to be\n     * made to the same bin counter.\n     */\n    BLOCK_HISTO_ATOMIC,\n};\n\n\n\n/******************************************************************************\n * Block histogram\n ******************************************************************************/\n\n\n/**\n * \\brief The BlockHistogram class provides [<em>collective</em>](index.html#sec0) methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block. ![](histogram_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam T                    The sample type being histogrammed (must be castable to an integer bin identifier)\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam ITEMS_PER_THREAD     The number of items per thread\n * \\tparam BINS                 The number bins within the histogram\n * \\tparam ALGORITHM            <b>[optional]</b> cub::BlockHistogramAlgorithm enumerator specifying the underlying algorithm to use (default: cub::BLOCK_HISTO_SORT)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - A <a href=\"http://en.wikipedia.org/wiki/Histogram\"><em>histogram</em></a>\n *   counts the number of observations that fall into each of the disjoint categories (known as <em>bins</em>).\n * - BlockHistogram can be optionally specialized to use different algorithms:\n *   -# <b>cub::BLOCK_HISTO_SORT</b>.  Sorting followed by differentiation. [More...](\\ref cub::BlockHistogramAlgorithm)\n *   -# <b>cub::BLOCK_HISTO_ATOMIC</b>.  Use atomic addition to update byte counts directly. [More...](\\ref cub::BlockHistogramAlgorithm)\n *\n * \\par Performance Considerations\n * - \\granularity\n *\n * \\par A Simple Example\n * \\blockcollective{BlockHistogram}\n * \\par\n * The code snippet below illustrates a 256-bin histogram of 512 integer samples that\n * are partitioned across 128 threads where each thread owns 4 samples.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_histogram.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize a 256-bin BlockHistogram type for a 1D block of 128 threads having 4 character samples each\n *     typedef cub::BlockHistogram<unsigned char, 128, 4, 256> BlockHistogram;\n *\n *     // Allocate shared memory for BlockHistogram\n *     __shared__ typename BlockHistogram::TempStorage temp_storage;\n *\n *     // Allocate shared memory for block-wide histogram bin counts\n *     __shared__ unsigned int smem_histogram[256];\n *\n *     // Obtain input samples per thread\n *     unsigned char data[4];\n *     ...\n *\n *     // Compute the block-wide histogram\n *     BlockHistogram(temp_storage).Histogram(data, smem_histogram);\n *\n * \\endcode\n *\n * \\par Performance and Usage Considerations\n * - The histogram output can be constructed in shared or device-accessible memory\n * - See cub::BlockHistogramAlgorithm for performance details regarding algorithmic alternatives\n *\n */\ntemplate <\n    typename                T,\n    int                     BLOCK_DIM_X,\n    int                     ITEMS_PER_THREAD,\n    int                     BINS,\n    BlockHistogramAlgorithm ALGORITHM           = BLOCK_HISTO_SORT,\n    int                     BLOCK_DIM_Y         = 1,\n    int                     BLOCK_DIM_Z         = 1,\n    int                     PTX_ARCH            = CUB_PTX_ARCH>\nclass BlockHistogram\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    /**\n     * Ensure the template parameterization meets the requirements of the\n     * targeted device architecture.  BLOCK_HISTO_ATOMIC can only be used\n     * on version SM120 or later.  Otherwise BLOCK_HISTO_SORT is used\n     * regardless.\n     */\n    static const BlockHistogramAlgorithm SAFE_ALGORITHM =\n        ((ALGORITHM == BLOCK_HISTO_ATOMIC) && (PTX_ARCH < 120)) ?\n            BLOCK_HISTO_SORT :\n            ALGORITHM;\n\n    /// Internal specialization.\n    typedef typename If<(SAFE_ALGORITHM == BLOCK_HISTO_SORT),\n        BlockHistogramSort<T, BLOCK_DIM_X, ITEMS_PER_THREAD, BINS, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH>,\n        BlockHistogramAtomic<BINS> >::Type InternalBlockHistogram;\n\n    /// Shared memory storage layout type for BlockHistogram\n    typedef typename InternalBlockHistogram::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\npublic:\n\n    /// \\smemstorage{BlockHistogram}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockHistogram()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockHistogram(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Histogram operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Initialize the shared histogram counters to zero.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a the initialization and update of a\n     * histogram of 512 integer samples that are partitioned across 128 threads\n     * where each thread owns 4 samples.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_histogram.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize a 256-bin BlockHistogram type for a 1D block of 128 threads having 4 character samples each\n     *     typedef cub::BlockHistogram<unsigned char, 128, 4, 256> BlockHistogram;\n     *\n     *     // Allocate shared memory for BlockHistogram\n     *     __shared__ typename BlockHistogram::TempStorage temp_storage;\n     *\n     *     // Allocate shared memory for block-wide histogram bin counts\n     *     __shared__ unsigned int smem_histogram[256];\n     *\n     *     // Obtain input samples per thread\n     *     unsigned char thread_samples[4];\n     *     ...\n     *\n     *     // Initialize the block-wide histogram\n     *     BlockHistogram(temp_storage).InitHistogram(smem_histogram);\n     *\n     *     // Update the block-wide histogram\n     *     BlockHistogram(temp_storage).Composite(thread_samples, smem_histogram);\n     *\n     * \\endcode\n     *\n     * \\tparam CounterT              <b>[inferred]</b> Histogram counter type\n     */\n    template <typename CounterT     >\n    __device__ __forceinline__ void InitHistogram(CounterT      histogram[BINS])\n    {\n        // Initialize histogram bin counts to zeros\n        int histo_offset = 0;\n\n        #pragma unroll\n        for(; histo_offset + BLOCK_THREADS <= BINS; histo_offset += BLOCK_THREADS)\n        {\n            histogram[histo_offset + linear_tid] = 0;\n        }\n        // Finish up with guarded initialization if necessary\n        if ((BINS % BLOCK_THREADS != 0) && (histo_offset + linear_tid < BINS))\n        {\n            histogram[histo_offset + linear_tid] = 0;\n        }\n    }\n\n\n    /**\n     * \\brief Constructs a block-wide histogram in shared/device-accessible memory.  Each thread contributes an array of input elements.\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a 256-bin histogram of 512 integer samples that\n     * are partitioned across 128 threads where each thread owns 4 samples.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_histogram.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize a 256-bin BlockHistogram type for a 1D block of 128 threads having 4 character samples each\n     *     typedef cub::BlockHistogram<unsigned char, 128, 4, 256> BlockHistogram;\n     *\n     *     // Allocate shared memory for BlockHistogram\n     *     __shared__ typename BlockHistogram::TempStorage temp_storage;\n     *\n     *     // Allocate shared memory for block-wide histogram bin counts\n     *     __shared__ unsigned int smem_histogram[256];\n     *\n     *     // Obtain input samples per thread\n     *     unsigned char thread_samples[4];\n     *     ...\n     *\n     *     // Compute the block-wide histogram\n     *     BlockHistogram(temp_storage).Histogram(thread_samples, smem_histogram);\n     *\n     * \\endcode\n     *\n     * \\tparam CounterT              <b>[inferred]</b> Histogram counter type\n     */\n    template <\n        typename            CounterT     >\n    __device__ __forceinline__ void Histogram(\n        T                   (&items)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input values to histogram\n        CounterT             histogram[BINS])                ///< [out] Reference to shared/device-accessible memory histogram\n    {\n        // Initialize histogram bin counts to zeros\n        InitHistogram(histogram);\n\n        CTA_SYNC();\n\n        // Composite the histogram\n        InternalBlockHistogram(temp_storage).Composite(items, histogram);\n    }\n\n\n\n    /**\n     * \\brief Updates an existing block-wide histogram in shared/device-accessible memory.  Each thread composites an array of input elements.\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a the initialization and update of a\n     * histogram of 512 integer samples that are partitioned across 128 threads\n     * where each thread owns 4 samples.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_histogram.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize a 256-bin BlockHistogram type for a 1D block of 128 threads having 4 character samples each\n     *     typedef cub::BlockHistogram<unsigned char, 128, 4, 256> BlockHistogram;\n     *\n     *     // Allocate shared memory for BlockHistogram\n     *     __shared__ typename BlockHistogram::TempStorage temp_storage;\n     *\n     *     // Allocate shared memory for block-wide histogram bin counts\n     *     __shared__ unsigned int smem_histogram[256];\n     *\n     *     // Obtain input samples per thread\n     *     unsigned char thread_samples[4];\n     *     ...\n     *\n     *     // Initialize the block-wide histogram\n     *     BlockHistogram(temp_storage).InitHistogram(smem_histogram);\n     *\n     *     // Update the block-wide histogram\n     *     BlockHistogram(temp_storage).Composite(thread_samples, smem_histogram);\n     *\n     * \\endcode\n     *\n     * \\tparam CounterT              <b>[inferred]</b> Histogram counter type\n     */\n    template <\n        typename            CounterT     >\n    __device__ __forceinline__ void Composite(\n        T                   (&items)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input values to histogram\n        CounterT             histogram[BINS])                 ///< [out] Reference to shared/device-accessible memory histogram\n    {\n        InternalBlockHistogram(temp_storage).Composite(items, histogram);\n    }\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_load.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Operations for reading linear tiles of data into the CUDA thread block.\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"block_exchange.cuh\"\n#include \"../iterator/cache_modified_input_iterator.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_macro.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIo\n * @{\n */\n\n\n/******************************************************************//**\n * \\name Blocked arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n\n/**\n * \\brief Load a linear segment of items into a blocked arrangement across the thread block.\n *\n * \\blocked\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectBlocked(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    InputIteratorT thread_itr = block_itr + (linear_tid * ITEMS_PER_THREAD);\n\n    // Load directly in thread-blocked order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        items[ITEM] = thread_itr[ITEM];\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a blocked arrangement across the thread block, guarded by range.\n *\n * \\blocked\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectBlocked(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items)                ///< [in] Number of valid items to load\n{\n    InputIteratorT thread_itr = block_itr + (linear_tid * ITEMS_PER_THREAD);\n\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if ((linear_tid * ITEMS_PER_THREAD) + ITEM < valid_items)\n        {\n            items[ITEM] = thread_itr[ITEM];\n        }\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a blocked arrangement across the thread block, guarded by range, with a fall-back assignment of out-of-bound elements..\n *\n * \\blocked\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    typename        DefaultT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectBlocked(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items,                ///< [in] Number of valid items to load\n    DefaultT        oob_default)                ///< [in] Default value to assign out-of-bound items\n{\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        items[ITEM] = oob_default;\n\n    LoadDirectBlocked(linear_tid, block_itr, items, valid_items);\n}\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n/**\n * Internal implementation for load vectorization\n */\ntemplate <\n    CacheLoadModifier   MODIFIER,\n    typename            T,\n    int                 ITEMS_PER_THREAD>\n__device__ __forceinline__ void InternalLoadDirectBlockedVectorized(\n    int    linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    T      *block_ptr,                 ///< [in] Input pointer for loading from\n    T      (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    // Biggest memory access word that T is a whole multiple of\n    typedef typename UnitWord<T>::DeviceWord DeviceWord;\n\n    enum\n    {\n        TOTAL_WORDS = sizeof(items) / sizeof(DeviceWord),\n\n        VECTOR_SIZE = (TOTAL_WORDS % 4 == 0) ?\n            4 :\n            (TOTAL_WORDS % 2 == 0) ?\n                2 :\n                1,\n\n        VECTORS_PER_THREAD = TOTAL_WORDS / VECTOR_SIZE,\n    };\n\n    // Vector type\n    typedef typename CubVector<DeviceWord, VECTOR_SIZE>::Type Vector;\n\n    // Vector items\n    Vector vec_items[VECTORS_PER_THREAD];\n\n    // Aliased input ptr\n    Vector* vec_ptr = reinterpret_cast<Vector*>(block_ptr) + (linear_tid * VECTORS_PER_THREAD);\n\n    // Load directly in thread-blocked order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < VECTORS_PER_THREAD; ITEM++)\n    {\n        vec_items[ITEM] = ThreadLoad<MODIFIER>(vec_ptr + ITEM);\n    }\n\n    // Copy\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        items[ITEM] = *(reinterpret_cast<T*>(vec_items) + ITEM);\n    }\n}\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/**\n * \\brief Load a linear segment of items into a blocked arrangement across the thread block.\n *\n * \\blocked\n *\n * The input offset (\\p block_ptr + \\p block_offset) must be quad-item aligned\n *\n * The following conditions will prevent vectorization and loading will fall back to cub::BLOCK_LOAD_DIRECT:\n *   - \\p ITEMS_PER_THREAD is odd\n *   - The data type \\p T is not a built-in primitive or CUDA vector type (e.g., \\p short, \\p int2, \\p double, \\p float2, etc.)\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n */\ntemplate <\n    typename        T,\n    int             ITEMS_PER_THREAD>\n__device__ __forceinline__ void LoadDirectBlockedVectorized(\n    int linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    T   *block_ptr,                 ///< [in] Input pointer for loading from\n    T   (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    InternalLoadDirectBlockedVectorized<LOAD_DEFAULT>(linear_tid, block_ptr, items);\n}\n\n\n//@}  end member group\n/******************************************************************//**\n * \\name Striped arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n\n/**\n * \\brief Load a linear segment of items into a striped arrangement across the thread block.\n *\n * \\striped\n *\n * \\tparam BLOCK_THREADS        The thread block size in threads\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    int             BLOCK_THREADS,\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    InputIteratorT thread_itr = block_itr + linear_tid;\n\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        items[ITEM] = thread_itr[ITEM * BLOCK_THREADS];\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a striped arrangement across the thread block, guarded by range\n *\n * \\striped\n *\n * \\tparam BLOCK_THREADS        The thread block size in threads\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    int             BLOCK_THREADS,\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items)                ///< [in] Number of valid items to load\n{\n    InputIteratorT thread_itr = block_itr + linear_tid;\n\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if (linear_tid + (ITEM * BLOCK_THREADS) < valid_items)\n        {\n            items[ITEM] = thread_itr[ITEM * BLOCK_THREADS];\n        }\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a striped arrangement across the thread block, guarded by range, with a fall-back assignment of out-of-bound elements.\n *\n * \\striped\n *\n * \\tparam BLOCK_THREADS        The thread block size in threads\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    int             BLOCK_THREADS,\n    typename        InputT,\n    typename        DefaultT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items,                ///< [in] Number of valid items to load\n    DefaultT        oob_default)                ///< [in] Default value to assign out-of-bound items\n{\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        items[ITEM] = oob_default;\n\n    LoadDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items, valid_items);\n}\n\n\n\n//@}  end member group\n/******************************************************************//**\n * \\name Warp-striped arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n\n/**\n * \\brief Load a linear segment of items into a warp-striped arrangement across the thread block.\n *\n * \\warpstriped\n *\n * \\par Usage Considerations\n * The number of threads in the thread block must be a multiple of the architecture's warp size.\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT       <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectWarpStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    int tid                = linear_tid & (CUB_PTX_WARP_THREADS - 1);\n    int wid                = linear_tid >> CUB_PTX_LOG_WARP_THREADS;\n    int warp_offset        = wid * CUB_PTX_WARP_THREADS * ITEMS_PER_THREAD;\n\n    InputIteratorT thread_itr = block_itr + warp_offset + tid ;\n\n    // Load directly in warp-striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        items[ITEM] = thread_itr[(ITEM * CUB_PTX_WARP_THREADS)];\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a warp-striped arrangement across the thread block, guarded by range\n *\n * \\warpstriped\n *\n * \\par Usage Considerations\n * The number of threads in the thread block must be a multiple of the architecture's warp size.\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT        <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectWarpStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items)                ///< [in] Number of valid items to load\n{\n    int tid                = linear_tid & (CUB_PTX_WARP_THREADS - 1);\n    int wid                = linear_tid >> CUB_PTX_LOG_WARP_THREADS;\n    int warp_offset        = wid * CUB_PTX_WARP_THREADS * ITEMS_PER_THREAD;\n\n    InputIteratorT thread_itr = block_itr + warp_offset + tid ;\n\n    // Load directly in warp-striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if (warp_offset + tid + (ITEM * CUB_PTX_WARP_THREADS) < valid_items)\n        {\n            items[ITEM] = thread_itr[(ITEM * CUB_PTX_WARP_THREADS)];\n        }\n    }\n}\n\n\n/**\n * \\brief Load a linear segment of items into a warp-striped arrangement across the thread block, guarded by range, with a fall-back assignment of out-of-bound elements.\n *\n * \\warpstriped\n *\n * \\par Usage Considerations\n * The number of threads in the thread block must be a multiple of the architecture's warp size.\n *\n * \\tparam T                    <b>[inferred]</b> The data type to load.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam InputIteratorT        <b>[inferred]</b> The random-access iterator type for input \\iterator.\n */\ntemplate <\n    typename        InputT,\n    typename        DefaultT,\n    int             ITEMS_PER_THREAD,\n    typename        InputIteratorT>\n__device__ __forceinline__ void LoadDirectWarpStriped(\n    int             linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n    InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n    int             valid_items,                ///< [in] Number of valid items to load\n    DefaultT        oob_default)                ///< [in] Default value to assign out-of-bound items\n{\n    // Load directly in warp-striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        items[ITEM] = oob_default;\n\n    LoadDirectWarpStriped(linear_tid, block_itr, items, valid_items);\n}\n\n\n\n//@}  end member group\n\n/** @} */       // end group UtilIo\n\n\n\n//-----------------------------------------------------------------------------\n// Generic BlockLoad abstraction\n//-----------------------------------------------------------------------------\n\n/**\n * \\brief cub::BlockLoadAlgorithm enumerates alternative algorithms for cub::BlockLoad to read a linear segment of data from memory into a blocked arrangement across a CUDA thread block.\n */\n\n/**\n * \\brief cub::BlockLoadAlgorithm enumerates alternative algorithms for cub::BlockLoad to read a linear segment of data from memory into a blocked arrangement across a CUDA thread block.\n */\nenum BlockLoadAlgorithm\n{\n    /**\n     * \\par Overview\n     *\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) of data is read\n     * directly from memory.\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) decreases as the\n     *   access stride between threads increases (i.e., the number items per thread).\n     */\n    BLOCK_LOAD_DIRECT,\n\n    /**\n     * \\par Overview\n     *\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) of data is read\n     * from memory using CUDA's built-in vectorized loads as a coalescing optimization.\n     * For example, <tt>ld.global.v4.s32</tt> instructions will be generated\n     * when \\p T = \\p int and \\p ITEMS_PER_THREAD % 4 == 0.\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high until the the\n     *   access stride between threads (i.e., the number items per thread) exceeds the\n     *   maximum vector load width (typically 4 items or 64B, whichever is lower).\n     * - The following conditions will prevent vectorization and loading will fall back to cub::BLOCK_LOAD_DIRECT:\n     *   - \\p ITEMS_PER_THREAD is odd\n     *   - The \\p InputIteratorTis not a simple pointer type\n     *   - The block input offset is not quadword-aligned\n     *   - The data type \\p T is not a built-in primitive or CUDA vector type (e.g., \\p short, \\p int2, \\p double, \\p float2, etc.)\n     */\n    BLOCK_LOAD_VECTORIZE,\n\n    /**\n     * \\par Overview\n     *\n     * A [<em>striped arrangement</em>](index.html#sec5sec3) of data is read\n     * efficiently from memory and then locally transposed into a\n     * [<em>blocked arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items loaded per thread.\n     * - The local reordering incurs slightly longer latencies and throughput than the\n     *   direct cub::BLOCK_LOAD_DIRECT and cub::BLOCK_LOAD_VECTORIZE alternatives.\n     */\n    BLOCK_LOAD_TRANSPOSE,\n\n\n    /**\n     * \\par Overview\n     *\n     * A [<em>warp-striped arrangement</em>](index.html#sec5sec3) of data is\n     * read efficiently from memory and then locally transposed into a\n     * [<em>blocked arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par Usage Considerations\n     * - BLOCK_THREADS must be a multiple of WARP_THREADS\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items loaded per thread.\n     * - The local reordering incurs slightly larger latencies than the\n     *   direct cub::BLOCK_LOAD_DIRECT and cub::BLOCK_LOAD_VECTORIZE alternatives.\n     * - Provisions more shared storage, but incurs smaller latencies than the\n     *   BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED alternative.\n     */\n    BLOCK_LOAD_WARP_TRANSPOSE,\n\n\n    /**\n     * \\par Overview\n     *\n     * Like \\p BLOCK_LOAD_WARP_TRANSPOSE, a [<em>warp-striped arrangement</em>](index.html#sec5sec3)\n     * of data is read directly from memory and then is locally transposed into a\n     * [<em>blocked arrangement</em>](index.html#sec5sec3). To reduce the shared memory\n     * requirement, only one warp's worth of shared memory is provisioned and is\n     * subsequently time-sliced among warps.\n     *\n     * \\par Usage Considerations\n     * - BLOCK_THREADS must be a multiple of WARP_THREADS\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items loaded per thread.\n     * - Provisions less shared memory temporary storage, but incurs larger\n     *   latencies than the BLOCK_LOAD_WARP_TRANSPOSE alternative.\n     */\n    BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED,\n};\n\n\n/**\n * \\brief The BlockLoad class provides [<em>collective</em>](index.html#sec0) data movement methods for loading a linear segment of items from memory into a [<em>blocked arrangement</em>](index.html#sec5sec3) across a CUDA thread block.  ![](block_load_logo.png)\n * \\ingroup BlockModule\n * \\ingroup UtilIo\n *\n * \\tparam InputT               The data type to read into (which must be convertible from the input iterator's value type).\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam ITEMS_PER_THREAD     The number of consecutive items partitioned onto each thread.\n * \\tparam ALGORITHM            <b>[optional]</b> cub::BlockLoadAlgorithm tuning policy.  default: cub::BLOCK_LOAD_DIRECT.\n * \\tparam WARP_TIME_SLICING    <b>[optional]</b> Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage). (default: false)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - The BlockLoad class provides a single data movement abstraction that can be specialized\n *   to implement different cub::BlockLoadAlgorithm strategies.  This facilitates different\n *   performance policies for different architectures, data types, granularity sizes, etc.\n * - BlockLoad can be optionally specialized by different data movement strategies:\n *   -# <b>cub::BLOCK_LOAD_DIRECT</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3)\n *      of data is read directly from memory.  [More...](\\ref cub::BlockLoadAlgorithm)\n *   -# <b>cub::BLOCK_LOAD_VECTORIZE</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3)\n *      of data is read directly from memory using CUDA's built-in vectorized loads as a\n *      coalescing optimization.    [More...](\\ref cub::BlockLoadAlgorithm)\n *   -# <b>cub::BLOCK_LOAD_TRANSPOSE</b>.  A [<em>striped arrangement</em>](index.html#sec5sec3)\n *      of data is read directly from memory and is then locally transposed into a\n *      [<em>blocked arrangement</em>](index.html#sec5sec3).  [More...](\\ref cub::BlockLoadAlgorithm)\n *   -# <b>cub::BLOCK_LOAD_WARP_TRANSPOSE</b>.  A [<em>warp-striped arrangement</em>](index.html#sec5sec3)\n *      of data is read directly from memory and is then locally transposed into a\n *      [<em>blocked arrangement</em>](index.html#sec5sec3).  [More...](\\ref cub::BlockLoadAlgorithm)\n *   -# <b>cub::BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED,</b>.  A [<em>warp-striped arrangement</em>](index.html#sec5sec3)\n *      of data is read directly from memory and is then locally transposed into a\n *      [<em>blocked arrangement</em>](index.html#sec5sec3) one warp at a time.  [More...](\\ref cub::BlockLoadAlgorithm)\n * - \\rowmajor\n *\n * \\par A Simple Example\n * \\blockcollective{BlockLoad}\n * \\par\n * The code snippet below illustrates the loading of a linear\n * segment of 512 integers into a \"blocked\" arrangement across 128 threads where each\n * thread owns 4 consecutive items.  The load is specialized for \\p BLOCK_LOAD_WARP_TRANSPOSE,\n * meaning memory references are efficiently coalesced using a warp-striped access\n * pattern (after which items are locally reordered among threads).\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_load.cuh>\n *\n * __global__ void ExampleKernel(int *d_data, ...)\n * {\n *     // Specialize BlockLoad for a 1D block of 128 threads owning 4 integer items each\n *     typedef cub::BlockLoad<int, 128, 4, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoad;\n *\n *     // Allocate shared memory for BlockLoad\n *     __shared__ typename BlockLoad::TempStorage temp_storage;\n *\n *     // Load a segment of consecutive items that are blocked across threads\n *     int thread_data[4];\n *     BlockLoad(temp_storage).Load(d_data, thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the input \\p d_data is <tt>0, 1, 2, 3, 4, 5, ...</tt>.\n * The set of \\p thread_data across the block of threads in those threads will be\n * <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n *\n */\ntemplate <\n    typename            InputT,\n    int                 BLOCK_DIM_X,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  ALGORITHM           = BLOCK_LOAD_DIRECT,\n    int                 BLOCK_DIM_Y         = 1,\n    int                 BLOCK_DIM_Z         = 1,\n    int                 PTX_ARCH            = CUB_PTX_ARCH>\nclass BlockLoad\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and typed definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n\n    /******************************************************************************\n     * Algorithmic variants\n     ******************************************************************************/\n\n    /// Load helper\n    template <BlockLoadAlgorithm _POLICY, int DUMMY>\n    struct LoadInternal;\n\n\n    /**\n     * BLOCK_LOAD_DIRECT specialization of load helper\n     */\n    template <int DUMMY>\n    struct LoadInternal<BLOCK_LOAD_DIRECT, DUMMY>\n    {\n        /// Shared memory storage layout type\n        typedef NullType TempStorage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ LoadInternal(\n            TempStorage &/*temp_storage*/,\n            int linear_tid)\n        :\n            linear_tid(linear_tid)\n        {}\n\n        /// Load a linear segment of items from memory\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items)                    ///< [in] Number of valid items to load\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items, valid_items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements\n        template <typename InputIteratorT, typename DefaultT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items,                    ///< [in] Number of valid items to load\n            DefaultT        oob_default)                    ///< [in] Default value to assign out-of-bound items\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items, valid_items, oob_default);\n        }\n\n    };\n\n\n    /**\n     * BLOCK_LOAD_VECTORIZE specialization of load helper\n     */\n    template <int DUMMY>\n    struct LoadInternal<BLOCK_LOAD_VECTORIZE, DUMMY>\n    {\n        /// Shared memory storage layout type\n        typedef NullType TempStorage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ LoadInternal(\n            TempStorage &/*temp_storage*/,\n            int linear_tid)\n        :\n            linear_tid(linear_tid)\n        {}\n\n        /// Load a linear segment of items from memory, specialized for native pointer types (attempts vectorization)\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputT               *block_ptr,                     ///< [in] The thread block's base input iterator for loading from\n            InputT               (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load\n        {\n            InternalLoadDirectBlockedVectorized<LOAD_DEFAULT>(linear_tid, block_ptr, items);\n        }\n\n        /// Load a linear segment of items from memory, specialized for native pointer types (attempts vectorization)\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            const InputT         *block_ptr,                     ///< [in] The thread block's base input iterator for loading from\n            InputT               (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load\n        {\n            InternalLoadDirectBlockedVectorized<LOAD_DEFAULT>(linear_tid, block_ptr, items);\n        }\n\n        /// Load a linear segment of items from memory, specialized for native pointer types (attempts vectorization)\n        template <\n            CacheLoadModifier   MODIFIER,\n            typename            ValueType,\n            typename            OffsetT>\n        __device__ __forceinline__ void Load(\n            CacheModifiedInputIterator<MODIFIER, ValueType, OffsetT>    block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT                                                     (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load\n        {\n            InternalLoadDirectBlockedVectorized<MODIFIER>(linear_tid, block_itr.ptr, items);\n        }\n\n        /// Load a linear segment of items from memory, specialized for opaque input iterators (skips vectorization)\n        template <typename _InputIteratorT>\n        __device__ __forceinline__ void Load(\n            _InputIteratorT   block_itr,                    ///< [in] The thread block's base input iterator for loading from\n            InputT           (&items)[ITEMS_PER_THREAD])   ///< [out] Data to load\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range (skips vectorization)\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items)                    ///< [in] Number of valid items to load\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items, valid_items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements (skips vectorization)\n        template <typename InputIteratorT, typename DefaultT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items,                    ///< [in] Number of valid items to load\n            DefaultT          oob_default)                    ///< [in] Default value to assign out-of-bound items\n        {\n            LoadDirectBlocked(linear_tid, block_itr, items, valid_items, oob_default);\n        }\n\n    };\n\n\n    /**\n     * BLOCK_LOAD_TRANSPOSE specialization of load helper\n     */\n    template <int DUMMY>\n    struct LoadInternal<BLOCK_LOAD_TRANSPOSE, DUMMY>\n    {\n        // BlockExchange utility type for keys\n        typedef BlockExchange<InputT, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ LoadInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Load a linear segment of items from memory\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load{\n        {\n            LoadDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items);\n            BlockExchange(temp_storage).StripedToBlocked(items, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items)                    ///< [in] Number of valid items to load\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items, temp_storage.valid_items);\n            BlockExchange(temp_storage).StripedToBlocked(items, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements\n        template <typename InputIteratorT, typename DefaultT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items,                    ///< [in] Number of valid items to load\n            DefaultT        oob_default)                    ///< [in] Default value to assign out-of-bound items\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items, temp_storage.valid_items, oob_default);\n            BlockExchange(temp_storage).StripedToBlocked(items, items);\n        }\n\n    };\n\n\n    /**\n     * BLOCK_LOAD_WARP_TRANSPOSE specialization of load helper\n     */\n    template <int DUMMY>\n    struct LoadInternal<BLOCK_LOAD_WARP_TRANSPOSE, DUMMY>\n    {\n        enum\n        {\n            WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH)\n        };\n\n        // Assert BLOCK_THREADS must be a multiple of WARP_THREADS\n        CUB_STATIC_ASSERT((BLOCK_THREADS % WARP_THREADS == 0), \"BLOCK_THREADS must be a multiple of WARP_THREADS\");\n\n        // BlockExchange utility type for keys\n        typedef BlockExchange<InputT, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ LoadInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Load a linear segment of items from memory\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load{\n        {\n            LoadDirectWarpStriped(linear_tid, block_itr, items);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items)                    ///< [in] Number of valid items to load\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n\n\n        /// Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements\n        template <typename InputIteratorT, typename DefaultT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items,                    ///< [in] Number of valid items to load\n            DefaultT        oob_default)                    ///< [in] Default value to assign out-of-bound items\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items, oob_default);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n    };\n\n\n    /**\n     * BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED specialization of load helper\n     */\n    template <int DUMMY>\n    struct LoadInternal<BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED, DUMMY>\n    {\n        enum\n        {\n            WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH)\n        };\n\n        // Assert BLOCK_THREADS must be a multiple of WARP_THREADS\n        CUB_STATIC_ASSERT((BLOCK_THREADS % WARP_THREADS == 0), \"BLOCK_THREADS must be a multiple of WARP_THREADS\");\n\n        // BlockExchange utility type for keys\n        typedef BlockExchange<InputT, BLOCK_DIM_X, ITEMS_PER_THREAD, true, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ LoadInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Load a linear segment of items from memory\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD])     ///< [out] Data to load{\n        {\n            LoadDirectWarpStriped(linear_tid, block_itr, items);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n\n        /// Load a linear segment of items from memory, guarded by range\n        template <typename InputIteratorT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items)                    ///< [in] Number of valid items to load\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n\n\n        /// Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements\n        template <typename InputIteratorT, typename DefaultT>\n        __device__ __forceinline__ void Load(\n            InputIteratorT  block_itr,                      ///< [in] The thread block's base input iterator for loading from\n            InputT          (&items)[ITEMS_PER_THREAD],     ///< [out] Data to load\n            int             valid_items,                    ///< [in] Number of valid items to load\n            DefaultT        oob_default)                    ///< [in] Default value to assign out-of-bound items\n        {\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            LoadDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items, oob_default);\n            BlockExchange(temp_storage).WarpStripedToBlocked(items, items);\n        }\n    };\n\n\n    /******************************************************************************\n     * Type definitions\n     ******************************************************************************/\n\n    /// Internal load implementation to use\n    typedef LoadInternal<ALGORITHM, 0> InternalLoad;\n\n\n    /// Shared memory storage layout type\n    typedef typename InternalLoad::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Thread reference to shared storage\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    int linear_tid;\n\npublic:\n\n    /// \\smemstorage{BlockLoad}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockLoad()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockLoad(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Data movement\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Load a linear segment of items from memory.\n     *\n     * \\par\n     * - \\blocked\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the loading of a linear\n     * segment of 512 integers into a \"blocked\" arrangement across 128 threads where each\n     * thread owns 4 consecutive items.  The load is specialized for \\p BLOCK_LOAD_WARP_TRANSPOSE,\n     * meaning memory references are efficiently coalesced using a warp-striped access\n     * pattern (after which items are locally reordered among threads).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_load.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockLoad for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockLoad<int, 128, 4, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoad;\n     *\n     *     // Allocate shared memory for BlockLoad\n     *     __shared__ typename BlockLoad::TempStorage temp_storage;\n     *\n     *     // Load a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     BlockLoad(temp_storage).Load(d_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, 1, 2, 3, 4, 5, ...</tt>.\n     * The set of \\p thread_data across the block of threads in those threads will be\n     * <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n     *\n     */\n    template <typename InputIteratorT>\n    __device__ __forceinline__ void Load(\n        InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n        InputT          (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n    {\n        InternalLoad(temp_storage, linear_tid).Load(block_itr, items);\n    }\n\n\n    /**\n     * \\brief Load a linear segment of items from memory, guarded by range.\n     *\n     * \\par\n     * - \\blocked\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the guarded loading of a linear\n     * segment of 512 integers into a \"blocked\" arrangement across 128 threads where each\n     * thread owns 4 consecutive items.  The load is specialized for \\p BLOCK_LOAD_WARP_TRANSPOSE,\n     * meaning memory references are efficiently coalesced using a warp-striped access\n     * pattern (after which items are locally reordered among threads).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_load.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, int valid_items, ...)\n     * {\n     *     // Specialize BlockLoad for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockLoad<int, 128, 4, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoad;\n     *\n     *     // Allocate shared memory for BlockLoad\n     *     __shared__ typename BlockLoad::TempStorage temp_storage;\n     *\n     *     // Load a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     BlockLoad(temp_storage).Load(d_data, thread_data, valid_items);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, 1, 2, 3, 4, 5, 6...</tt> and \\p valid_items is \\p 5.\n     * The set of \\p thread_data across the block of threads in those threads will be\n     * <tt>{ [0,1,2,3], [4,?,?,?], ..., [?,?,?,?] }</tt>, with only the first two threads\n     * being unmasked to load portions of valid data (and other items remaining unassigned).\n     *\n     */\n    template <typename InputIteratorT>\n    __device__ __forceinline__ void Load(\n        InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n        InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n        int             valid_items)                ///< [in] Number of valid items to load\n    {\n        InternalLoad(temp_storage, linear_tid).Load(block_itr, items, valid_items);\n    }\n\n\n    /**\n     * \\brief Load a linear segment of items from memory, guarded by range, with a fall-back assignment of out-of-bound elements\n     *\n     * \\par\n     * - \\blocked\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the guarded loading of a linear\n     * segment of 512 integers into a \"blocked\" arrangement across 128 threads where each\n     * thread owns 4 consecutive items.  The load is specialized for \\p BLOCK_LOAD_WARP_TRANSPOSE,\n     * meaning memory references are efficiently coalesced using a warp-striped access\n     * pattern (after which items are locally reordered among threads).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_load.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, int valid_items, ...)\n     * {\n     *     // Specialize BlockLoad for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockLoad<int, 128, 4, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoad;\n     *\n     *     // Allocate shared memory for BlockLoad\n     *     __shared__ typename BlockLoad::TempStorage temp_storage;\n     *\n     *     // Load a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     BlockLoad(temp_storage).Load(d_data, thread_data, valid_items, -1);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, 1, 2, 3, 4, 5, 6...</tt>,\n     * \\p valid_items is \\p 5, and the out-of-bounds default is \\p -1.\n     * The set of \\p thread_data across the block of threads in those threads will be\n     * <tt>{ [0,1,2,3], [4,-1,-1,-1], ..., [-1,-1,-1,-1] }</tt>, with only the first two threads\n     * being unmasked to load portions of valid data (and other items are assigned \\p -1)\n     *\n     */\n    template <typename InputIteratorT, typename DefaultT>\n    __device__ __forceinline__ void Load(\n        InputIteratorT  block_itr,                  ///< [in] The thread block's base input iterator for loading from\n        InputT          (&items)[ITEMS_PER_THREAD], ///< [out] Data to load\n        int             valid_items,                ///< [in] Number of valid items to load\n        DefaultT        oob_default)                ///< [in] Default value to assign out-of-bound items\n    {\n        InternalLoad(temp_storage, linear_tid).Load(block_itr, items, valid_items, oob_default);\n    }\n\n\n    //@}  end member group\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_radix_rank.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockRadixRank provides operations for ranking unsigned integer types within a CUDA thread block\n */\n\n#pragma once\n\n#include <stdint.h>\n\n#include \"../thread/thread_reduce.cuh\"\n#include \"../thread/thread_scan.cuh\"\n#include \"../block/block_scan.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief BlockRadixRank provides operations for ranking unsigned integer types within a CUDA thread block.\n * \\ingroup BlockModule\n *\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam RADIX_BITS           The number of radix bits per digit place\n * \\tparam IS_DESCENDING           Whether or not the sorted-order is high-to-low\n * \\tparam MEMOIZE_OUTER_SCAN   <b>[optional]</b> Whether or not to buffer outer raking scan partials to incur fewer shared memory reads at the expense of higher register pressure (default: true for architectures SM35 and newer, false otherwise).  See BlockScanAlgorithm::BLOCK_SCAN_RAKING_MEMOIZE for more details.\n * \\tparam INNER_SCAN_ALGORITHM <b>[optional]</b> The cub::BlockScanAlgorithm algorithm to use (default: cub::BLOCK_SCAN_WARP_SCANS)\n * \\tparam SMEM_CONFIG          <b>[optional]</b> Shared memory bank mode (default: \\p cudaSharedMemBankSizeFourByte)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * Blah...\n * - Keys must be in a form suitable for radix ranking (i.e., unsigned bits).\n * - \\blocked\n *\n * \\par Performance Considerations\n * - \\granularity\n *\n * \\par Examples\n * \\par\n * - <b>Example 1:</b> Simple radix rank of 32-bit integer keys\n *      \\code\n *      #include <cub/cub.cuh>\n *\n *      template <int BLOCK_THREADS>\n *      __global__ void ExampleKernel(...)\n *      {\n *\n *      \\endcode\n */\ntemplate <\n    int                     BLOCK_DIM_X,\n    int                     RADIX_BITS,\n    bool                    IS_DESCENDING,\n    bool                    MEMOIZE_OUTER_SCAN      = (CUB_PTX_ARCH >= 350) ? true : false,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM    = BLOCK_SCAN_WARP_SCANS,\n    cudaSharedMemConfig     SMEM_CONFIG             = cudaSharedMemBankSizeFourByte,\n    int                     BLOCK_DIM_Y             = 1,\n    int                     BLOCK_DIM_Z             = 1,\n    int                     PTX_ARCH                = CUB_PTX_ARCH>\nclass BlockRadixRank\n{\nprivate:\n\n    /******************************************************************************\n     * Type definitions and constants\n     ******************************************************************************/\n\n    // Integer type for digit counters (to be packed into words of type PackedCounters)\n    typedef unsigned short DigitCounter;\n\n    // Integer type for packing DigitCounters into columns of shared memory banks\n    typedef typename If<(SMEM_CONFIG == cudaSharedMemBankSizeEightByte),\n        unsigned long long,\n        unsigned int>::Type PackedCounter;\n\n    enum\n    {\n        // The thread block size in threads\n        BLOCK_THREADS               = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        RADIX_DIGITS                = 1 << RADIX_BITS,\n\n        LOG_WARP_THREADS            = CUB_LOG_WARP_THREADS(PTX_ARCH),\n        WARP_THREADS                = 1 << LOG_WARP_THREADS,\n        WARPS                       = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        BYTES_PER_COUNTER           = sizeof(DigitCounter),\n        LOG_BYTES_PER_COUNTER       = Log2<BYTES_PER_COUNTER>::VALUE,\n\n        PACKING_RATIO               = sizeof(PackedCounter) / sizeof(DigitCounter),\n        LOG_PACKING_RATIO           = Log2<PACKING_RATIO>::VALUE,\n\n        LOG_COUNTER_LANES           = CUB_MAX((RADIX_BITS - LOG_PACKING_RATIO), 0),                // Always at least one lane\n        COUNTER_LANES               = 1 << LOG_COUNTER_LANES,\n\n        // The number of packed counters per thread (plus one for padding)\n        PADDED_COUNTER_LANES        = COUNTER_LANES + 1,\n        RAKING_SEGMENT              = PADDED_COUNTER_LANES,\n    };\n\npublic:\n\n    enum\n    {\n        /// Number of bin-starting offsets tracked per thread\n        BINS_TRACKED_PER_THREAD = CUB_MAX(1, RADIX_DIGITS / BLOCK_THREADS),\n    };\n\nprivate:\n\n\n    /// BlockScan type\n    typedef BlockScan<\n            PackedCounter,\n            BLOCK_DIM_X,\n            INNER_SCAN_ALGORITHM,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        BlockScan;\n\n\n    /// Shared memory storage layout type for BlockRadixRank\n    struct __align__(16) _TempStorage\n    {\n        union Aliasable\n        {\n            DigitCounter            digit_counters[PADDED_COUNTER_LANES][BLOCK_THREADS][PACKING_RATIO];\n            PackedCounter           raking_grid[BLOCK_THREADS][RAKING_SEGMENT];\n\n        } aliasable;\n\n        // Storage for scanning local ranks\n        typename BlockScan::TempStorage block_scan;\n    };\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n    /// Copy of raking segment, promoted to registers\n    PackedCounter cached_segment[RAKING_SEGMENT];\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /**\n     * Internal storage allocator\n     */\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /**\n     * Performs upsweep raking reduction, returning the aggregate\n     */\n    __device__ __forceinline__ PackedCounter Upsweep()\n    {\n        PackedCounter *smem_raking_ptr = temp_storage.aliasable.raking_grid[linear_tid];\n        PackedCounter *raking_ptr;\n\n        if (MEMOIZE_OUTER_SCAN)\n        {\n            // Copy data into registers\n            #pragma unroll\n            for (int i = 0; i < RAKING_SEGMENT; i++)\n            {\n                cached_segment[i] = smem_raking_ptr[i];\n            }\n            raking_ptr = cached_segment;\n        }\n        else\n        {\n            raking_ptr = smem_raking_ptr;\n        }\n\n        return internal::ThreadReduce<RAKING_SEGMENT>(raking_ptr, Sum());\n    }\n\n\n    /// Performs exclusive downsweep raking scan\n    __device__ __forceinline__ void ExclusiveDownsweep(\n        PackedCounter raking_partial)\n    {\n        PackedCounter *smem_raking_ptr = temp_storage.aliasable.raking_grid[linear_tid];\n\n        PackedCounter *raking_ptr = (MEMOIZE_OUTER_SCAN) ?\n            cached_segment :\n            smem_raking_ptr;\n\n        // Exclusive raking downsweep scan\n        internal::ThreadScanExclusive<RAKING_SEGMENT>(raking_ptr, raking_ptr, Sum(), raking_partial);\n\n        if (MEMOIZE_OUTER_SCAN)\n        {\n            // Copy data back to smem\n            #pragma unroll\n            for (int i = 0; i < RAKING_SEGMENT; i++)\n            {\n                smem_raking_ptr[i] = cached_segment[i];\n            }\n        }\n    }\n\n\n    /**\n     * Reset shared memory digit counters\n     */\n    __device__ __forceinline__ void ResetCounters()\n    {\n        // Reset shared memory digit counters\n        #pragma unroll\n        for (int LANE = 0; LANE < PADDED_COUNTER_LANES; LANE++)\n        {\n            *((PackedCounter*) temp_storage.aliasable.digit_counters[LANE][linear_tid]) = 0;\n        }\n    }\n\n\n    /**\n     * Block-scan prefix callback\n     */\n    struct PrefixCallBack\n    {\n        __device__ __forceinline__ PackedCounter operator()(PackedCounter block_aggregate)\n        {\n            PackedCounter block_prefix = 0;\n\n            // Propagate totals in packed fields\n            #pragma unroll\n            for (int PACKED = 1; PACKED < PACKING_RATIO; PACKED++)\n            {\n                block_prefix += block_aggregate << (sizeof(DigitCounter) * 8 * PACKED);\n            }\n\n            return block_prefix;\n        }\n    };\n\n\n    /**\n     * Scan shared memory digit counters.\n     */\n    __device__ __forceinline__ void ScanCounters()\n    {\n        // Upsweep scan\n        PackedCounter raking_partial = Upsweep();\n\n        // Compute exclusive sum\n        PackedCounter exclusive_partial;\n        PrefixCallBack prefix_call_back;\n        BlockScan(temp_storage.block_scan).ExclusiveSum(raking_partial, exclusive_partial, prefix_call_back);\n\n        // Downsweep scan with exclusive partial\n        ExclusiveDownsweep(exclusive_partial);\n    }\n\npublic:\n\n    /// \\smemstorage{BlockScan}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockRadixRank()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockRadixRank(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Raking\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Rank keys.\n     */\n    template <\n        typename        UnsignedBits,\n        int             KEYS_PER_THREAD>\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&keys)[KEYS_PER_THREAD],           ///< [in] Keys for this tile\n        int             (&ranks)[KEYS_PER_THREAD],          ///< [out] For each key, the local rank within the tile\n        int             current_bit,                        ///< [in] The least-significant bit position of the current digit to extract\n        int             num_bits)                           ///< [in] The number of bits in the current digit\n    {\n        DigitCounter    thread_prefixes[KEYS_PER_THREAD];   // For each key, the count of previous keys in this tile having the same digit\n        DigitCounter*   digit_counters[KEYS_PER_THREAD];    // For each key, the byte-offset of its corresponding digit counter in smem\n\n        // Reset shared memory digit counters\n        ResetCounters();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < KEYS_PER_THREAD; ++ITEM)\n        {\n            // Get digit\n            unsigned int digit = BFE(keys[ITEM], current_bit, num_bits);\n\n            // Get sub-counter\n            unsigned int sub_counter = digit >> LOG_COUNTER_LANES;\n\n            // Get counter lane\n            unsigned int counter_lane = digit & (COUNTER_LANES - 1);\n\n            if (IS_DESCENDING)\n            {\n                sub_counter = PACKING_RATIO - 1 - sub_counter;\n                counter_lane = COUNTER_LANES - 1 - counter_lane;\n            }\n\n            // Pointer to smem digit counter\n            digit_counters[ITEM] = &temp_storage.aliasable.digit_counters[counter_lane][linear_tid][sub_counter];\n\n            // Load thread-exclusive prefix\n            thread_prefixes[ITEM] = *digit_counters[ITEM];\n\n            // Store inclusive prefix\n            *digit_counters[ITEM] = thread_prefixes[ITEM] + 1;\n        }\n\n        CTA_SYNC();\n\n        // Scan shared memory counters\n        ScanCounters();\n\n        CTA_SYNC();\n\n        // Extract the local ranks of each key\n        for (int ITEM = 0; ITEM < KEYS_PER_THREAD; ++ITEM)\n        {\n            // Add in thread block exclusive prefix\n            ranks[ITEM] = thread_prefixes[ITEM] + *digit_counters[ITEM];\n        }\n    }\n\n\n    /**\n     * \\brief Rank keys.  For the lower \\p RADIX_DIGITS threads, digit counts for each digit are provided for the corresponding thread.\n     */\n    template <\n        typename        UnsignedBits,\n        int             KEYS_PER_THREAD>\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&keys)[KEYS_PER_THREAD],           ///< [in] Keys for this tile\n        int             (&ranks)[KEYS_PER_THREAD],          ///< [out] For each key, the local rank within the tile (out parameter)\n        int             current_bit,                        ///< [in] The least-significant bit position of the current digit to extract\n        int             num_bits,                           ///< [in] The number of bits in the current digit\n        int             (&exclusive_digit_prefix)[BINS_TRACKED_PER_THREAD])            ///< [out] The exclusive prefix sum for the digits [(threadIdx.x * BINS_TRACKED_PER_THREAD) ... (threadIdx.x * BINS_TRACKED_PER_THREAD) + BINS_TRACKED_PER_THREAD - 1]\n    {\n        // Rank keys\n        RankKeys(keys, ranks, current_bit, num_bits);\n\n        // Get the inclusive and exclusive digit totals corresponding to the calling thread.\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (linear_tid * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                if (IS_DESCENDING)\n                    bin_idx = RADIX_DIGITS - bin_idx - 1;\n\n                // Obtain ex/inclusive digit counts.  (Unfortunately these all reside in the\n                // first counter column, resulting in unavoidable bank conflicts.)\n                unsigned int counter_lane   = (bin_idx & (COUNTER_LANES - 1));\n                unsigned int sub_counter    = bin_idx >> (LOG_COUNTER_LANES);\n\n                exclusive_digit_prefix[track] = temp_storage.aliasable.digit_counters[counter_lane][0][sub_counter];\n            }\n        }\n    }\n};\n\n\n\n\n\n/**\n * Radix-rank using match.any\n */\ntemplate <\n    int                     BLOCK_DIM_X,\n    int                     RADIX_BITS,\n    bool                    IS_DESCENDING,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM    = BLOCK_SCAN_WARP_SCANS,\n    int                     BLOCK_DIM_Y             = 1,\n    int                     BLOCK_DIM_Z             = 1,\n    int                     PTX_ARCH                = CUB_PTX_ARCH>\nclass BlockRadixRankMatch\n{\nprivate:\n\n    /******************************************************************************\n     * Type definitions and constants\n     ******************************************************************************/\n\n    typedef int32_t    RankT;\n    typedef int32_t    DigitCounterT;\n\n    enum\n    {\n        // The thread block size in threads\n        BLOCK_THREADS               = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        RADIX_DIGITS                = 1 << RADIX_BITS,\n\n        LOG_WARP_THREADS            = CUB_LOG_WARP_THREADS(PTX_ARCH),\n        WARP_THREADS                = 1 << LOG_WARP_THREADS,\n        WARPS                       = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        PADDED_WARPS            = ((WARPS & 0x1) == 0) ?\n                                    WARPS + 1 :\n                                    WARPS,\n\n        COUNTERS                = PADDED_WARPS * RADIX_DIGITS,\n        RAKING_SEGMENT          = (COUNTERS + BLOCK_THREADS - 1) / BLOCK_THREADS,\n        PADDED_RAKING_SEGMENT   = ((RAKING_SEGMENT & 0x1) == 0) ?\n                                    RAKING_SEGMENT + 1 :\n                                    RAKING_SEGMENT,\n    };\n\npublic:\n\n    enum\n    {\n        /// Number of bin-starting offsets tracked per thread\n        BINS_TRACKED_PER_THREAD = CUB_MAX(1, RADIX_DIGITS / BLOCK_THREADS),\n    };\n\nprivate:\n\n    /// BlockScan type\n    typedef BlockScan<\n            DigitCounterT,\n            BLOCK_THREADS,\n            INNER_SCAN_ALGORITHM,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        BlockScanT;\n\n\n    /// Shared memory storage layout type for BlockRadixRank\n    struct __align__(16) _TempStorage\n    {\n        typename BlockScanT::TempStorage            block_scan;\n\n        union __align__(16) Aliasable\n        {\n            volatile DigitCounterT                  warp_digit_counters[RADIX_DIGITS][PADDED_WARPS];\n            DigitCounterT                           raking_grid[BLOCK_THREADS][PADDED_RAKING_SEGMENT];\n\n        } aliasable;\n    };\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\n\npublic:\n\n    /// \\smemstorage{BlockScan}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockRadixRankMatch(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Raking\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Rank keys.\n     */\n    template <\n        typename        UnsignedBits,\n        int             KEYS_PER_THREAD>\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&keys)[KEYS_PER_THREAD],           ///< [in] Keys for this tile\n        int             (&ranks)[KEYS_PER_THREAD],          ///< [out] For each key, the local rank within the tile\n        int             current_bit,                        ///< [in] The least-significant bit position of the current digit to extract\n        int             num_bits)                           ///< [in] The number of bits in the current digit\n    {\n        // Initialize shared digit counters\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < PADDED_RAKING_SEGMENT; ++ITEM)\n            temp_storage.aliasable.raking_grid[linear_tid][ITEM] = 0;\n\n        CTA_SYNC();\n\n        // Each warp will strip-mine its section of input, one strip at a time\n\n        volatile DigitCounterT  *digit_counters[KEYS_PER_THREAD];\n        uint32_t                lane_id         = LaneId();\n        uint32_t                warp_id         = linear_tid >> LOG_WARP_THREADS;\n        uint32_t                lane_mask_lt    = LaneMaskLt();\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < KEYS_PER_THREAD; ++ITEM)\n        {\n            // My digit\n            uint32_t digit = BFE(keys[ITEM], current_bit, num_bits);\n\n            if (IS_DESCENDING)\n                digit = RADIX_DIGITS - digit - 1;\n\n            // Mask of peers who have same digit as me\n            uint32_t peer_mask = MatchAny<RADIX_BITS>(digit);\n\n            // Pointer to smem digit counter for this key\n            digit_counters[ITEM] = &temp_storage.aliasable.warp_digit_counters[digit][warp_id];\n\n            // Number of occurrences in previous strips\n            DigitCounterT warp_digit_prefix = *digit_counters[ITEM];\n\n            // Warp-sync\n            WARP_SYNC(0xFFFFFFFF);\n\n            // Number of peers having same digit as me\n            int32_t digit_count = __popc(peer_mask);\n\n            // Number of lower-ranked peers having same digit seen so far\n            int32_t peer_digit_prefix = __popc(peer_mask & lane_mask_lt);\n\n            if (peer_digit_prefix == 0)\n            {\n                // First thread for each digit updates the shared warp counter\n                *digit_counters[ITEM] = DigitCounterT(warp_digit_prefix + digit_count);\n            }\n\n            // Warp-sync\n            WARP_SYNC(0xFFFFFFFF);\n\n            // Number of prior keys having same digit\n            ranks[ITEM] = warp_digit_prefix + DigitCounterT(peer_digit_prefix);\n        }\n\n        CTA_SYNC();\n\n        // Scan warp counters\n\n        DigitCounterT scan_counters[PADDED_RAKING_SEGMENT];\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < PADDED_RAKING_SEGMENT; ++ITEM)\n            scan_counters[ITEM] = temp_storage.aliasable.raking_grid[linear_tid][ITEM];\n\n        BlockScanT(temp_storage.block_scan).ExclusiveSum(scan_counters, scan_counters);\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < PADDED_RAKING_SEGMENT; ++ITEM)\n            temp_storage.aliasable.raking_grid[linear_tid][ITEM] = scan_counters[ITEM];\n\n        CTA_SYNC();\n\n        // Seed ranks with counter values from previous warps\n        #pragma unroll\n        for (int ITEM = 0; ITEM < KEYS_PER_THREAD; ++ITEM)\n            ranks[ITEM] += *digit_counters[ITEM];\n    }\n\n\n    /**\n     * \\brief Rank keys.  For the lower \\p RADIX_DIGITS threads, digit counts for each digit are provided for the corresponding thread.\n     */\n    template <\n        typename        UnsignedBits,\n        int             KEYS_PER_THREAD>\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&keys)[KEYS_PER_THREAD],           ///< [in] Keys for this tile\n        int             (&ranks)[KEYS_PER_THREAD],          ///< [out] For each key, the local rank within the tile (out parameter)\n        int             current_bit,                        ///< [in] The least-significant bit position of the current digit to extract\n        int             num_bits,                           ///< [in] The number of bits in the current digit\n        int             (&exclusive_digit_prefix)[BINS_TRACKED_PER_THREAD])            ///< [out] The exclusive prefix sum for the digits [(threadIdx.x * BINS_TRACKED_PER_THREAD) ... (threadIdx.x * BINS_TRACKED_PER_THREAD) + BINS_TRACKED_PER_THREAD - 1]\n    {\n        RankKeys(keys, ranks, current_bit, num_bits);\n\n        // Get exclusive count for each digit\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (linear_tid * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n            {\n                if (IS_DESCENDING)\n                    bin_idx = RADIX_DIGITS - bin_idx - 1;\n\n                exclusive_digit_prefix[track] = temp_storage.aliasable.warp_digit_counters[bin_idx][0];\n            }\n        }\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/block/block_radix_sort.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockRadixSort class provides [<em>collective</em>](index.html#sec0) methods for radix sorting of items partitioned across a CUDA thread block.\n */\n\n\n#pragma once\n\n#include \"block_exchange.cuh\"\n#include \"block_radix_rank.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief The BlockRadixSort class provides [<em>collective</em>](index.html#sec0) methods for sorting items partitioned across a CUDA thread block using a radix sorting method.  ![](sorting_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam KeyT                 KeyT type\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam ITEMS_PER_THREAD     The number of items per thread\n * \\tparam ValueT               <b>[optional]</b> ValueT type (default: cub::NullType, which indicates a keys-only sort)\n * \\tparam RADIX_BITS           <b>[optional]</b> The number of radix bits per digit place (default: 4 bits)\n * \\tparam MEMOIZE_OUTER_SCAN   <b>[optional]</b> Whether or not to buffer outer raking scan partials to incur fewer shared memory reads at the expense of higher register pressure (default: true for architectures SM35 and newer, false otherwise).\n * \\tparam INNER_SCAN_ALGORITHM <b>[optional]</b> The cub::BlockScanAlgorithm algorithm to use (default: cub::BLOCK_SCAN_WARP_SCANS)\n * \\tparam SMEM_CONFIG          <b>[optional]</b> Shared memory bank mode (default: \\p cudaSharedMemBankSizeFourByte)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - The [<em>radix sorting method</em>](http://en.wikipedia.org/wiki/Radix_sort) arranges\n *   items into ascending order.  It relies upon a positional representation for\n *   keys, i.e., each key is comprised of an ordered sequence of symbols (e.g., digits,\n *   characters, etc.) specified from least-significant to most-significant.  For a\n *   given input sequence of keys and a set of rules specifying a total ordering\n *   of the symbolic alphabet, the radix sorting method produces a lexicographic\n *   ordering of those keys.\n * - BlockRadixSort can sort all of the built-in C++ numeric primitive types, e.g.:\n *   <tt>unsigned char</tt>, \\p int, \\p double, etc.  Within each key, the implementation treats fixed-length\n *   bit-sequences of \\p RADIX_BITS as radix digit places.  Although the direct radix sorting\n *   method can only be applied to unsigned integral types, BlockRadixSort\n *   is able to sort signed and floating-point types via simple bit-wise transformations\n *   that ensure lexicographic key ordering.\n * - \\rowmajor\n *\n * \\par Performance Considerations\n * - \\granularity\n *\n * \\par A Simple Example\n * \\blockcollective{BlockRadixSort}\n * \\par\n * The code snippet below illustrates a sort of 512 integer keys that\n * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n * where each thread owns 4 consecutive items.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer items each\n *     typedef cub::BlockRadixSort<int, 128, 4> BlockRadixSort;\n *\n *     // Allocate shared memory for BlockRadixSort\n *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n *\n *     // Obtain a segment of consecutive items that are blocked across threads\n *     int thread_keys[4];\n *     ...\n *\n *     // Collectively sort the keys\n *     BlockRadixSort(temp_storage).Sort(thread_keys);\n *\n *     ...\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_keys across the block of threads is\n * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n * corresponding output \\p thread_keys in those threads will be\n * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n *\n */\ntemplate <\n    typename                KeyT,\n    int                     BLOCK_DIM_X,\n    int                     ITEMS_PER_THREAD,\n    typename                ValueT                   = NullType,\n    int                     RADIX_BITS              = 4,\n    bool                    MEMOIZE_OUTER_SCAN      = (CUB_PTX_ARCH >= 350) ? true : false,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM    = BLOCK_SCAN_WARP_SCANS,\n    cudaSharedMemConfig     SMEM_CONFIG             = cudaSharedMemBankSizeFourByte,\n    int                     BLOCK_DIM_Y             = 1,\n    int                     BLOCK_DIM_Z             = 1,\n    int                     PTX_ARCH                = CUB_PTX_ARCH>\nclass BlockRadixSort\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    enum\n    {\n        // The thread block size in threads\n        BLOCK_THREADS               = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        // Whether or not there are values to be trucked along with keys\n        KEYS_ONLY                   = Equals<ValueT, NullType>::VALUE,\n    };\n\n    // KeyT traits and unsigned bits type\n    typedef Traits<KeyT>                        KeyTraits;\n    typedef typename KeyTraits::UnsignedBits    UnsignedBits;\n\n    /// Ascending BlockRadixRank utility type\n    typedef BlockRadixRank<\n            BLOCK_DIM_X,\n            RADIX_BITS,\n            false,\n            MEMOIZE_OUTER_SCAN,\n            INNER_SCAN_ALGORITHM,\n            SMEM_CONFIG,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        AscendingBlockRadixRank;\n\n    /// Descending BlockRadixRank utility type\n    typedef BlockRadixRank<\n            BLOCK_DIM_X,\n            RADIX_BITS,\n            true,\n            MEMOIZE_OUTER_SCAN,\n            INNER_SCAN_ALGORITHM,\n            SMEM_CONFIG,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        DescendingBlockRadixRank;\n\n    /// BlockExchange utility type for keys\n    typedef BlockExchange<KeyT, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchangeKeys;\n\n    /// BlockExchange utility type for values\n    typedef BlockExchange<ValueT, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchangeValues;\n\n    /// Shared memory storage layout type\n    union _TempStorage\n    {\n        typename AscendingBlockRadixRank::TempStorage  asending_ranking_storage;\n        typename DescendingBlockRadixRank::TempStorage descending_ranking_storage;\n        typename BlockExchangeKeys::TempStorage        exchange_keys;\n        typename BlockExchangeValues::TempStorage      exchange_values;\n    };\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n    /// Rank keys (specialized for ascending sort)\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&unsigned_keys)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        int             begin_bit,\n        int             pass_bits,\n        Int2Type<false> /*is_descending*/)\n    {\n        AscendingBlockRadixRank(temp_storage.asending_ranking_storage).RankKeys(\n            unsigned_keys,\n            ranks,\n            begin_bit,\n            pass_bits);\n    }\n\n    /// Rank keys (specialized for descending sort)\n    __device__ __forceinline__ void RankKeys(\n        UnsignedBits    (&unsigned_keys)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        int             begin_bit,\n        int             pass_bits,\n        Int2Type<true>  /*is_descending*/)\n    {\n        DescendingBlockRadixRank(temp_storage.descending_ranking_storage).RankKeys(\n            unsigned_keys,\n            ranks,\n            begin_bit,\n            pass_bits);\n    }\n\n    /// ExchangeValues (specialized for key-value sort, to-blocked arrangement)\n    __device__ __forceinline__ void ExchangeValues(\n        ValueT          (&values)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        Int2Type<false> /*is_keys_only*/,\n        Int2Type<true>  /*is_blocked*/)\n    {\n        CTA_SYNC();\n\n        // Exchange values through shared memory in blocked arrangement\n        BlockExchangeValues(temp_storage.exchange_values).ScatterToBlocked(values, ranks);\n    }\n\n    /// ExchangeValues (specialized for key-value sort, to-striped arrangement)\n    __device__ __forceinline__ void ExchangeValues(\n        ValueT          (&values)[ITEMS_PER_THREAD],\n        int             (&ranks)[ITEMS_PER_THREAD],\n        Int2Type<false> /*is_keys_only*/,\n        Int2Type<false> /*is_blocked*/)\n    {\n        CTA_SYNC();\n\n        // Exchange values through shared memory in blocked arrangement\n        BlockExchangeValues(temp_storage.exchange_values).ScatterToStriped(values, ranks);\n    }\n\n    /// ExchangeValues (specialized for keys-only sort)\n    template <int IS_BLOCKED>\n    __device__ __forceinline__ void ExchangeValues(\n        ValueT                  (&/*values*/)[ITEMS_PER_THREAD],\n        int                     (&/*ranks*/)[ITEMS_PER_THREAD],\n        Int2Type<true>          /*is_keys_only*/,\n        Int2Type<IS_BLOCKED>    /*is_blocked*/)\n    {}\n\n    /// Sort blocked arrangement\n    template <int DESCENDING, int KEYS_ONLY>\n    __device__ __forceinline__ void SortBlocked(\n        KeyT                    (&keys)[ITEMS_PER_THREAD],          ///< Keys to sort\n        ValueT                  (&values)[ITEMS_PER_THREAD],        ///< Values to sort\n        int                     begin_bit,                          ///< The beginning (least-significant) bit index needed for key comparison\n        int                     end_bit,                            ///< The past-the-end (most-significant) bit index needed for key comparison\n        Int2Type<DESCENDING>    is_descending,                      ///< Tag whether is a descending-order sort\n        Int2Type<KEYS_ONLY>     is_keys_only)                       ///< Tag whether is keys-only sort\n    {\n        UnsignedBits (&unsigned_keys)[ITEMS_PER_THREAD] =\n            reinterpret_cast<UnsignedBits (&)[ITEMS_PER_THREAD]>(keys);\n\n        // Twiddle bits if necessary\n        #pragma unroll\n        for (int KEY = 0; KEY < ITEMS_PER_THREAD; KEY++)\n        {\n            unsigned_keys[KEY] = KeyTraits::TwiddleIn(unsigned_keys[KEY]);\n        }\n\n        // Radix sorting passes\n        while (true)\n        {\n            int pass_bits = CUB_MIN(RADIX_BITS, end_bit - begin_bit);\n\n            // Rank the blocked keys\n            int ranks[ITEMS_PER_THREAD];\n            RankKeys(unsigned_keys, ranks, begin_bit, pass_bits, is_descending);\n            begin_bit += RADIX_BITS;\n\n            CTA_SYNC();\n\n            // Exchange keys through shared memory in blocked arrangement\n            BlockExchangeKeys(temp_storage.exchange_keys).ScatterToBlocked(keys, ranks);\n\n            // Exchange values through shared memory in blocked arrangement\n            ExchangeValues(values, ranks, is_keys_only, Int2Type<true>());\n\n            // Quit if done\n            if (begin_bit >= end_bit) break;\n\n            CTA_SYNC();\n        }\n\n        // Untwiddle bits if necessary\n        #pragma unroll\n        for (int KEY = 0; KEY < ITEMS_PER_THREAD; KEY++)\n        {\n            unsigned_keys[KEY] = KeyTraits::TwiddleOut(unsigned_keys[KEY]);\n        }\n    }\n\npublic:\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    /// Sort blocked -> striped arrangement\n    template <int DESCENDING, int KEYS_ONLY>\n    __device__ __forceinline__ void SortBlockedToStriped(\n        KeyT                    (&keys)[ITEMS_PER_THREAD],          ///< Keys to sort\n        ValueT                  (&values)[ITEMS_PER_THREAD],        ///< Values to sort\n        int                     begin_bit,                          ///< The beginning (least-significant) bit index needed for key comparison\n        int                     end_bit,                            ///< The past-the-end (most-significant) bit index needed for key comparison\n        Int2Type<DESCENDING>    is_descending,                      ///< Tag whether is a descending-order sort\n        Int2Type<KEYS_ONLY>     is_keys_only)                       ///< Tag whether is keys-only sort\n    {\n        UnsignedBits (&unsigned_keys)[ITEMS_PER_THREAD] =\n            reinterpret_cast<UnsignedBits (&)[ITEMS_PER_THREAD]>(keys);\n\n        // Twiddle bits if necessary\n        #pragma unroll\n        for (int KEY = 0; KEY < ITEMS_PER_THREAD; KEY++)\n        {\n            unsigned_keys[KEY] = KeyTraits::TwiddleIn(unsigned_keys[KEY]);\n        }\n\n        // Radix sorting passes\n        while (true)\n        {\n            int pass_bits = CUB_MIN(RADIX_BITS, end_bit - begin_bit);\n\n            // Rank the blocked keys\n            int ranks[ITEMS_PER_THREAD];\n            RankKeys(unsigned_keys, ranks, begin_bit, pass_bits, is_descending);\n            begin_bit += RADIX_BITS;\n\n            CTA_SYNC();\n\n            // Check if this is the last pass\n            if (begin_bit >= end_bit)\n            {\n                // Last pass exchanges keys through shared memory in striped arrangement\n                BlockExchangeKeys(temp_storage.exchange_keys).ScatterToStriped(keys, ranks);\n\n                // Last pass exchanges through shared memory in striped arrangement\n                ExchangeValues(values, ranks, is_keys_only, Int2Type<false>());\n\n                // Quit\n                break;\n            }\n\n            // Exchange keys through shared memory in blocked arrangement\n            BlockExchangeKeys(temp_storage.exchange_keys).ScatterToBlocked(keys, ranks);\n\n            // Exchange values through shared memory in blocked arrangement\n            ExchangeValues(values, ranks, is_keys_only, Int2Type<true>());\n\n            CTA_SYNC();\n        }\n\n        // Untwiddle bits if necessary\n        #pragma unroll\n        for (int KEY = 0; KEY < ITEMS_PER_THREAD; KEY++)\n        {\n            unsigned_keys[KEY] = KeyTraits::TwiddleOut(unsigned_keys[KEY]);\n        }\n    }\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n    /// \\smemstorage{BlockRadixSort}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockRadixSort()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockRadixSort(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Sorting (blocked arrangements)\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Performs an ascending block-wide radix sort over a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys.\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys each\n     *     typedef cub::BlockRadixSort<int, 128, 4> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     ...\n     *\n     *     // Collectively sort the keys\n     *     BlockRadixSort(temp_storage).Sort(thread_keys);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.\n     * The corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     */\n    __device__ __forceinline__ void Sort(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        NullType values[ITEMS_PER_THREAD];\n\n        SortBlocked(keys, values, begin_bit, end_bit, Int2Type<false>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    /**\n     * \\brief Performs an ascending block-wide radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys and values.\n     *\n     * \\par\n     * - BlockRadixSort can only accommodate one associated tile of values. To \"truck along\"\n     *   more than one tile of values, simply perform a key-value sort of the keys paired\n     *   with a temporary value array that enumerates the key indices.  The reordered indices\n     *   can then be used as a gather-vector for exchanging other associated tile data through\n     *   shared memory.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys and values that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive pairs.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys and values each\n     *     typedef cub::BlockRadixSort<int, 128, 4, int> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     int thread_values[4];\n     *     ...\n     *\n     *     // Collectively sort the keys and values among block threads\n     *     BlockRadixSort(temp_storage).Sort(thread_keys, thread_values);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [0,1,2,3], [4,5,6,7], [8,9,10,11], ..., [508,509,510,511] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void Sort(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        ValueT  (&values)[ITEMS_PER_THREAD],        ///< [in-out] Values to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        SortBlocked(keys, values, begin_bit, end_bit, Int2Type<false>(), Int2Type<KEYS_ONLY>());\n    }\n\n    /**\n     * \\brief Performs a descending block-wide radix sort over a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys.\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys each\n     *     typedef cub::BlockRadixSort<int, 128, 4> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     ...\n     *\n     *     // Collectively sort the keys\n     *     BlockRadixSort(temp_storage).Sort(thread_keys);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.\n     * The corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [511,510,509,508], [11,10,9,8], [7,6,5,4], ..., [3,2,1,0] }</tt>.\n     */\n    __device__ __forceinline__ void SortDescending(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        NullType values[ITEMS_PER_THREAD];\n\n        SortBlocked(keys, values, begin_bit, end_bit, Int2Type<true>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    /**\n     * \\brief Performs a descending block-wide radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys and values.\n     *\n     * \\par\n     * - BlockRadixSort can only accommodate one associated tile of values. To \"truck along\"\n     *   more than one tile of values, simply perform a key-value sort of the keys paired\n     *   with a temporary value array that enumerates the key indices.  The reordered indices\n     *   can then be used as a gather-vector for exchanging other associated tile data through\n     *   shared memory.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys and values that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive pairs.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys and values each\n     *     typedef cub::BlockRadixSort<int, 128, 4, int> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     int thread_values[4];\n     *     ...\n     *\n     *     // Collectively sort the keys and values among block threads\n     *     BlockRadixSort(temp_storage).Sort(thread_keys, thread_values);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [511,510,509,508], [11,10,9,8], [7,6,5,4], ..., [3,2,1,0] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void SortDescending(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        ValueT  (&values)[ITEMS_PER_THREAD],        ///< [in-out] Values to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        SortBlocked(keys, values, begin_bit, end_bit, Int2Type<true>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Sorting (blocked arrangement -> striped arrangement)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Performs an ascending radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys, leaving them in a [<em>striped arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys that\n     * are initially partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive keys.  The final partitioning is striped.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys each\n     *     typedef cub::BlockRadixSort<int, 128, 4> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     ...\n     *\n     *     // Collectively sort the keys\n     *     BlockRadixSort(temp_storage).SortBlockedToStriped(thread_keys);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [0,128,256,384], [1,129,257,385], [2,130,258,386], ..., [127,255,383,511] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void SortBlockedToStriped(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        NullType values[ITEMS_PER_THREAD];\n\n        SortBlockedToStriped(keys, values, begin_bit, end_bit, Int2Type<false>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    /**\n     * \\brief Performs an ascending radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys and values, leaving them in a [<em>striped arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par\n     * - BlockRadixSort can only accommodate one associated tile of values. To \"truck along\"\n     *   more than one tile of values, simply perform a key-value sort of the keys paired\n     *   with a temporary value array that enumerates the key indices.  The reordered indices\n     *   can then be used as a gather-vector for exchanging other associated tile data through\n     *   shared memory.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys and values that\n     * are initially partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive pairs.  The final partitioning is striped.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys and values each\n     *     typedef cub::BlockRadixSort<int, 128, 4, int> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     int thread_values[4];\n     *     ...\n     *\n     *     // Collectively sort the keys and values among block threads\n     *     BlockRadixSort(temp_storage).SortBlockedToStriped(thread_keys, thread_values);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [0,128,256,384], [1,129,257,385], [2,130,258,386], ..., [127,255,383,511] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void SortBlockedToStriped(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        ValueT  (&values)[ITEMS_PER_THREAD],        ///< [in-out] Values to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        SortBlockedToStriped(keys, values, begin_bit, end_bit, Int2Type<false>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    /**\n     * \\brief Performs a descending radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys, leaving them in a [<em>striped arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys that\n     * are initially partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive keys.  The final partitioning is striped.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys each\n     *     typedef cub::BlockRadixSort<int, 128, 4> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     ...\n     *\n     *     // Collectively sort the keys\n     *     BlockRadixSort(temp_storage).SortBlockedToStriped(thread_keys);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [511,383,255,127], [386,258,130,2], [385,257,128,1], ..., [384,256,128,0] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void SortDescendingBlockedToStriped(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        NullType values[ITEMS_PER_THREAD];\n\n        SortBlockedToStriped(keys, values, begin_bit, end_bit, Int2Type<true>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    /**\n     * \\brief Performs a descending radix sort across a [<em>blocked arrangement</em>](index.html#sec5sec3) of keys and values, leaving them in a [<em>striped arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par\n     * - BlockRadixSort can only accommodate one associated tile of values. To \"truck along\"\n     *   more than one tile of values, simply perform a key-value sort of the keys paired\n     *   with a temporary value array that enumerates the key indices.  The reordered indices\n     *   can then be used as a gather-vector for exchanging other associated tile data through\n     *   shared memory.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sort of 512 integer keys and values that\n     * are initially partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive pairs.  The final partitioning is striped.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_radix_sort.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockRadixSort for a 1D block of 128 threads owning 4 integer keys and values each\n     *     typedef cub::BlockRadixSort<int, 128, 4, int> BlockRadixSort;\n     *\n     *     // Allocate shared memory for BlockRadixSort\n     *     __shared__ typename BlockRadixSort::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_keys[4];\n     *     int thread_values[4];\n     *     ...\n     *\n     *     // Collectively sort the keys and values among block threads\n     *     BlockRadixSort(temp_storage).SortBlockedToStriped(thread_keys, thread_values);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_keys across the block of threads is\n     * <tt>{ [0,511,1,510], [2,509,3,508], [4,507,5,506], ..., [254,257,255,256] }</tt>.  The\n     * corresponding output \\p thread_keys in those threads will be\n     * <tt>{ [511,383,255,127], [386,258,130,2], [385,257,128,1], ..., [384,256,128,0] }</tt>.\n     *\n     */\n    __device__ __forceinline__ void SortDescendingBlockedToStriped(\n        KeyT    (&keys)[ITEMS_PER_THREAD],          ///< [in-out] Keys to sort\n        ValueT  (&values)[ITEMS_PER_THREAD],        ///< [in-out] Values to sort\n        int     begin_bit   = 0,                    ///< [in] <b>[optional]</b> The beginning (least-significant) bit index needed for key comparison\n        int     end_bit     = sizeof(KeyT) * 8)      ///< [in] <b>[optional]</b> The past-the-end (most-significant) bit index needed for key comparison\n    {\n        SortBlockedToStriped(keys, values, begin_bit, end_bit, Int2Type<true>(), Int2Type<KEYS_ONLY>());\n    }\n\n\n    //@}  end member group\n\n};\n\n/**\n * \\example example_block_radix_sort.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_raking_layout.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockRakingLayout provides a conflict-free shared memory layout abstraction for warp-raking across thread block data.\n */\n\n\n#pragma once\n\n#include \"../util_macro.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief BlockRakingLayout provides a conflict-free shared memory layout abstraction for 1D raking across thread block data.    ![](raking.png)\n * \\ingroup BlockModule\n *\n * \\par Overview\n * This type facilitates a shared memory usage pattern where a block of CUDA\n * threads places elements into shared memory and then reduces the active\n * parallelism to one \"raking\" warp of threads for serially aggregating consecutive\n * sequences of shared items.  Padding is inserted to eliminate bank conflicts\n * (for most data types).\n *\n * \\tparam T                        The data type to be exchanged.\n * \\tparam BLOCK_THREADS            The thread block size in threads.\n * \\tparam PTX_ARCH                 <b>[optional]</b> \\ptxversion\n */\ntemplate <\n    typename    T,\n    int         BLOCK_THREADS,\n    int         PTX_ARCH = CUB_PTX_ARCH>\nstruct BlockRakingLayout\n{\n    //---------------------------------------------------------------------\n    // Constants and type definitions\n    //---------------------------------------------------------------------\n\n    enum\n    {\n        /// The total number of elements that need to be cooperatively reduced\n        SHARED_ELEMENTS = BLOCK_THREADS,\n\n        /// Maximum number of warp-synchronous raking threads\n        MAX_RAKING_THREADS = CUB_MIN(BLOCK_THREADS, CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// Number of raking elements per warp-synchronous raking thread (rounded up)\n        SEGMENT_LENGTH = (SHARED_ELEMENTS + MAX_RAKING_THREADS - 1) / MAX_RAKING_THREADS,\n\n        /// Never use a raking thread that will have no valid data (e.g., when BLOCK_THREADS is 62 and SEGMENT_LENGTH is 2, we should only use 31 raking threads)\n        RAKING_THREADS = (SHARED_ELEMENTS + SEGMENT_LENGTH - 1) / SEGMENT_LENGTH,\n\n        /// Whether we will have bank conflicts (technically we should find out if the GCD is > 1)\n        HAS_CONFLICTS = (CUB_SMEM_BANKS(PTX_ARCH) % SEGMENT_LENGTH == 0),\n\n        /// Degree of bank conflicts (e.g., 4-way)\n        CONFLICT_DEGREE = (HAS_CONFLICTS) ?\n            (MAX_RAKING_THREADS * SEGMENT_LENGTH) / CUB_SMEM_BANKS(PTX_ARCH) :\n            1,\n\n        /// Pad each segment length with one element if segment length is not relatively prime to warp size and can't be optimized as a vector load\n        USE_SEGMENT_PADDING = ((SEGMENT_LENGTH & 1) == 0) && (SEGMENT_LENGTH > 2),\n\n        /// Total number of elements in the raking grid\n        GRID_ELEMENTS = RAKING_THREADS * (SEGMENT_LENGTH + USE_SEGMENT_PADDING),\n\n        /// Whether or not we need bounds checking during raking (the number of reduction elements is not a multiple of the number of raking threads)\n        UNGUARDED = (SHARED_ELEMENTS % RAKING_THREADS == 0),\n    };\n\n\n    /**\n     * \\brief Shared memory storage type\n     */\n    struct __align__(16) _TempStorage\n    {\n        T buff[BlockRakingLayout::GRID_ELEMENTS];\n    };\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /**\n     * \\brief Returns the location for the calling thread to place data into the grid\n     */\n    static __device__ __forceinline__ T* PlacementPtr(\n        TempStorage &temp_storage,\n        unsigned int linear_tid)\n    {\n        // Offset for partial\n        unsigned int offset = linear_tid;\n\n        // Add in one padding element for every segment\n        if (USE_SEGMENT_PADDING > 0)\n        {\n            offset += offset / SEGMENT_LENGTH;\n        }\n\n        // Incorporating a block of padding partials every shared memory segment\n        return temp_storage.Alias().buff + offset;\n    }\n\n\n    /**\n     * \\brief Returns the location for the calling thread to begin sequential raking\n     */\n    static __device__ __forceinline__ T* RakingPtr(\n        TempStorage &temp_storage,\n        unsigned int linear_tid)\n    {\n        return temp_storage.Alias().buff + (linear_tid * (SEGMENT_LENGTH + USE_SEGMENT_PADDING));\n    }\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_reduce.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockReduce class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel reduction of items partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"specializations/block_reduce_raking.cuh\"\n#include \"specializations/block_reduce_raking_commutative_only.cuh\"\n#include \"specializations/block_reduce_warp_reductions.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_type.cuh\"\n#include \"../thread/thread_operators.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n\n/******************************************************************************\n * Algorithmic variants\n ******************************************************************************/\n\n/**\n * BlockReduceAlgorithm enumerates alternative algorithms for parallel\n * reduction across a CUDA thread block.\n */\nenum BlockReduceAlgorithm\n{\n\n    /**\n     * \\par Overview\n     * An efficient \"raking\" reduction algorithm that only supports commutative\n     * reduction operators (true for most operations, e.g., addition).\n     *\n     * \\par\n     * Execution is comprised of three phases:\n     * -# Upsweep sequential reduction in registers (if threads contribute more\n     *    than one input each).  Threads in warps other than the first warp place\n     *    their partial reductions into shared memory.\n     * -# Upsweep sequential reduction in shared memory.  Threads within the first\n     *    warp continue to accumulate by raking across segments of shared partial reductions\n     * -# A warp-synchronous Kogge-Stone style reduction within the raking warp.\n     *\n     * \\par\n     * \\image html block_reduce.png\n     * <div class=\"centercaption\">\\p BLOCK_REDUCE_RAKING data flow for a hypothetical 16-thread thread block and 4-thread raking warp.</div>\n     *\n     * \\par Performance Considerations\n     * - This variant performs less communication than BLOCK_REDUCE_RAKING_NON_COMMUTATIVE\n     *   and is preferable when the reduction operator is commutative.  This variant\n     *   applies fewer reduction operators  than BLOCK_REDUCE_WARP_REDUCTIONS, and can provide higher overall\n     *   throughput across the GPU when suitably occupied.  However, turn-around latency may be\n     *   higher than to BLOCK_REDUCE_WARP_REDUCTIONS and thus less-desirable\n     *   when the GPU is under-occupied.\n     */\n    BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY,\n\n\n    /**\n     * \\par Overview\n     * An efficient \"raking\" reduction algorithm that supports commutative\n     * (e.g., addition) and non-commutative (e.g., string concatenation) reduction\n     * operators. \\blocked.\n     *\n     * \\par\n     * Execution is comprised of three phases:\n     * -# Upsweep sequential reduction in registers (if threads contribute more\n     *    than one input each).  Each thread then places the partial reduction\n     *    of its item(s) into shared memory.\n     * -# Upsweep sequential reduction in shared memory.  Threads within a\n     *    single warp rake across segments of shared partial reductions.\n     * -# A warp-synchronous Kogge-Stone style reduction within the raking warp.\n     *\n     * \\par\n     * \\image html block_reduce.png\n     * <div class=\"centercaption\">\\p BLOCK_REDUCE_RAKING data flow for a hypothetical 16-thread thread block and 4-thread raking warp.</div>\n     *\n     * \\par Performance Considerations\n     * - This variant performs more communication than BLOCK_REDUCE_RAKING\n     *   and is only preferable when the reduction operator is non-commutative.  This variant\n     *   applies fewer reduction operators than BLOCK_REDUCE_WARP_REDUCTIONS, and can provide higher overall\n     *   throughput across the GPU when suitably occupied.  However, turn-around latency may be\n     *   higher than to BLOCK_REDUCE_WARP_REDUCTIONS and thus less-desirable\n     *   when the GPU is under-occupied.\n     */\n    BLOCK_REDUCE_RAKING,\n\n\n    /**\n     * \\par Overview\n     * A quick \"tiled warp-reductions\" reduction algorithm that supports commutative\n     * (e.g., addition) and non-commutative (e.g., string concatenation) reduction\n     * operators.\n     *\n     * \\par\n     * Execution is comprised of four phases:\n     * -# Upsweep sequential reduction in registers (if threads contribute more\n     *    than one input each).  Each thread then places the partial reduction\n     *    of its item(s) into shared memory.\n     * -# Compute a shallow, but inefficient warp-synchronous Kogge-Stone style\n     *    reduction within each warp.\n     * -# A propagation phase where the warp reduction outputs in each warp are\n     *    updated with the aggregate from each preceding warp.\n     *\n     * \\par\n     * \\image html block_scan_warpscans.png\n     * <div class=\"centercaption\">\\p BLOCK_REDUCE_WARP_REDUCTIONS data flow for a hypothetical 16-thread thread block and 4-thread raking warp.</div>\n     *\n     * \\par Performance Considerations\n     * - This variant applies more reduction operators than BLOCK_REDUCE_RAKING\n     *   or BLOCK_REDUCE_RAKING_NON_COMMUTATIVE, which may result in lower overall\n     *   throughput across the GPU.  However turn-around latency may be lower and\n     *   thus useful when the GPU is under-occupied.\n     */\n    BLOCK_REDUCE_WARP_REDUCTIONS,\n};\n\n\n/******************************************************************************\n * Block reduce\n ******************************************************************************/\n\n/**\n * \\brief The BlockReduce class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel reduction of items partitioned across a CUDA thread block. ![](reduce_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam T                Data type being reduced\n * \\tparam BLOCK_DIM_X      The thread block length in threads along the X dimension\n * \\tparam ALGORITHM        <b>[optional]</b> cub::BlockReduceAlgorithm enumerator specifying the underlying algorithm to use (default: cub::BLOCK_REDUCE_WARP_REDUCTIONS)\n * \\tparam BLOCK_DIM_Y      <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z      <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH         <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - A <a href=\"http://en.wikipedia.org/wiki/Reduce_(higher-order_function)\"><em>reduction</em></a> (or <em>fold</em>)\n *   uses a binary combining operator to compute a single aggregate from a list of input elements.\n * - \\rowmajor\n * - BlockReduce can be optionally specialized by algorithm to accommodate different latency/throughput workload profiles:\n *   -# <b>cub::BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY</b>.  An efficient \"raking\" reduction algorithm that only supports commutative reduction operators. [More...](\\ref cub::BlockReduceAlgorithm)\n *   -# <b>cub::BLOCK_REDUCE_RAKING</b>.  An efficient \"raking\" reduction algorithm that supports commutative and non-commutative reduction operators. [More...](\\ref cub::BlockReduceAlgorithm)\n *   -# <b>cub::BLOCK_REDUCE_WARP_REDUCTIONS</b>.  A quick \"tiled warp-reductions\" reduction algorithm that supports commutative and non-commutative reduction operators. [More...](\\ref cub::BlockReduceAlgorithm)\n *\n * \\par Performance Considerations\n * - \\granularity\n * - Very efficient (only one synchronization barrier).\n * - Incurs zero bank conflicts for most types\n * - Computation is slightly more efficient (i.e., having lower instruction overhead) for:\n *   - Summation (<b><em>vs.</em></b> generic reduction)\n *   - \\p BLOCK_THREADS is a multiple of the architecture's warp size\n *   - Every thread has a valid input (i.e., full <b><em>vs.</em></b> partial-tiles)\n * - See cub::BlockReduceAlgorithm for performance details regarding algorithmic alternatives\n *\n * \\par A Simple Example\n * \\blockcollective{BlockReduce}\n * \\par\n * The code snippet below illustrates a sum reduction of 512 integer items that\n * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n * where each thread owns 4 consecutive items.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n *     typedef cub::BlockReduce<int, 128> BlockReduce;\n *\n *     // Allocate shared memory for BlockReduce\n *     __shared__ typename BlockReduce::TempStorage temp_storage;\n *\n *     // Obtain a segment of consecutive items that are blocked across threads\n *     int thread_data[4];\n *     ...\n *\n *     // Compute the block-wide sum for thread0\n *     int aggregate = BlockReduce(temp_storage).Sum(thread_data);\n *\n * \\endcode\n *\n */\ntemplate <\n    typename                T,\n    int                     BLOCK_DIM_X,\n    BlockReduceAlgorithm    ALGORITHM       = BLOCK_REDUCE_WARP_REDUCTIONS,\n    int                     BLOCK_DIM_Y     = 1,\n    int                     BLOCK_DIM_Z     = 1,\n    int                     PTX_ARCH        = CUB_PTX_ARCH>\nclass BlockReduce\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    typedef BlockReduceWarpReductions<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH>           WarpReductions;\n    typedef BlockReduceRakingCommutativeOnly<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH>    RakingCommutativeOnly;\n    typedef BlockReduceRaking<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH>                   Raking;\n\n    /// Internal specialization type\n    typedef typename If<(ALGORITHM == BLOCK_REDUCE_WARP_REDUCTIONS),\n        WarpReductions,\n        typename If<(ALGORITHM == BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY),\n            RakingCommutativeOnly,\n            Raking>::Type>::Type InternalBlockReduce;     // BlockReduceRaking\n\n    /// Shared memory storage layout type for BlockReduce\n    typedef typename InternalBlockReduce::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\npublic:\n\n    /// \\smemstorage{BlockReduce}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockReduce()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockReduce(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Generic reductions\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using the specified binary reduction functor.  Each thread contributes one input element.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a max reduction of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Each thread obtains an input item\n     *     int thread_data;\n     *     ...\n     *\n     *     // Compute the block-wide max for thread0\n     *     int aggregate = BlockReduce(temp_storage).Reduce(thread_data, cub::Max());\n     *\n     * \\endcode\n     *\n     * \\tparam ReductionOp          <b>[inferred]</b> Binary reduction functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T               input,                      ///< [in] Calling thread's input\n        ReductionOp     reduction_op)               ///< [in] Binary reduction functor \n    {\n        return InternalBlockReduce(temp_storage).template Reduce<true>(input, BLOCK_THREADS, reduction_op);\n    }\n\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using the specified binary reduction functor.  Each thread contributes an array of consecutive input elements.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a max reduction of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Compute the block-wide max for thread0\n     *     int aggregate = BlockReduce(temp_storage).Reduce(thread_data, cub::Max());\n     *\n     * \\endcode\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ReductionOp          <b>[inferred]</b> Binary reduction functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int ITEMS_PER_THREAD,\n        typename ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T               (&inputs)[ITEMS_PER_THREAD],    ///< [in] Calling thread's input segment\n        ReductionOp     reduction_op)                   ///< [in] Binary reduction functor \n    {\n        // Reduce partials\n        T partial = internal::ThreadReduce(inputs, reduction_op);\n        return Reduce(partial, reduction_op);\n    }\n\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using the specified binary reduction functor.  The first \\p num_valid threads each contribute one input element.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a max reduction of a partially-full tile of integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(int num_valid, ...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Each thread obtains an input item\n     *     int thread_data;\n     *     if (threadIdx.x < num_valid) thread_data = ...\n     *\n     *     // Compute the block-wide max for thread0\n     *     int aggregate = BlockReduce(temp_storage).Reduce(thread_data, cub::Max(), num_valid);\n     *\n     * \\endcode\n     *\n     * \\tparam ReductionOp          <b>[inferred]</b> Binary reduction functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   input,                  ///< [in] Calling thread's input\n        ReductionOp         reduction_op,           ///< [in] Binary reduction functor \n        int                 num_valid)              ///< [in] Number of threads containing valid elements (may be less than BLOCK_THREADS)\n    {\n        // Determine if we scan skip bounds checking\n        if (num_valid >= BLOCK_THREADS)\n        {\n            return InternalBlockReduce(temp_storage).template Reduce<true>(input, num_valid, reduction_op);\n        }\n        else\n        {\n            return InternalBlockReduce(temp_storage).template Reduce<false>(input, num_valid, reduction_op);\n        }\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Summation reductions\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using addition (+) as the reduction operator.  Each thread contributes one input element.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sum reduction of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Each thread obtains an input item\n     *     int thread_data;\n     *     ...\n     *\n     *     // Compute the block-wide sum for thread0\n     *     int aggregate = BlockReduce(temp_storage).Sum(thread_data);\n     *\n     * \\endcode\n     *\n     */\n    __device__ __forceinline__ T Sum(\n        T   input)                      ///< [in] Calling thread's input\n    {\n        return InternalBlockReduce(temp_storage).template Sum<true>(input, BLOCK_THREADS);\n    }\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using addition (+) as the reduction operator.  Each thread contributes an array of consecutive input elements.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sum reduction of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Compute the block-wide sum for thread0\n     *     int aggregate = BlockReduce(temp_storage).Sum(thread_data);\n     *\n     * \\endcode\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ T Sum(\n        T   (&inputs)[ITEMS_PER_THREAD])    ///< [in] Calling thread's input segment\n    {\n        // Reduce partials\n        T partial = internal::ThreadReduce(inputs, cub::Sum());\n        return Sum(partial);\n    }\n\n\n    /**\n     * \\brief Computes a block-wide reduction for thread<sub>0</sub> using addition (+) as the reduction operator.  The first \\p num_valid threads each contribute one input element.\n     *\n     * \\par\n     * - The return value is undefined in threads other than thread<sub>0</sub>.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sum reduction of a partially-full tile of integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_reduce.cuh>\n     *\n     * __global__ void ExampleKernel(int num_valid, ...)\n     * {\n     *     // Specialize BlockReduce for a 1D block of 128 threads on type int\n     *     typedef cub::BlockReduce<int, 128> BlockReduce;\n     *\n     *     // Allocate shared memory for BlockReduce\n     *     __shared__ typename BlockReduce::TempStorage temp_storage;\n     *\n     *     // Each thread obtains an input item (up to num_items)\n     *     int thread_data;\n     *     if (threadIdx.x < num_valid)\n     *         thread_data = ...\n     *\n     *     // Compute the block-wide sum for thread0\n     *     int aggregate = BlockReduce(temp_storage).Sum(thread_data, num_valid);\n     *\n     * \\endcode\n     *\n     */\n    __device__ __forceinline__ T Sum(\n        T   input,                  ///< [in] Calling thread's input\n        int num_valid)              ///< [in] Number of threads containing valid elements (may be less than BLOCK_THREADS)\n    {\n        // Determine if we scan skip bounds checking\n        if (num_valid >= BLOCK_THREADS)\n        {\n            return InternalBlockReduce(temp_storage).template Sum<true>(input, num_valid);\n        }\n        else\n        {\n            return InternalBlockReduce(temp_storage).template Sum<false>(input, num_valid);\n        }\n    }\n\n\n    //@}  end member group\n};\n\n/**\n * \\example example_block_reduce.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_scan.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockScan class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel prefix sum/scan of items partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"specializations/block_scan_raking.cuh\"\n#include \"specializations/block_scan_warp_scans.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Algorithmic variants\n ******************************************************************************/\n\n/**\n * \\brief BlockScanAlgorithm enumerates alternative algorithms for cub::BlockScan to compute a parallel prefix scan across a CUDA thread block.\n */\nenum BlockScanAlgorithm\n{\n\n    /**\n     * \\par Overview\n     * An efficient \"raking reduce-then-scan\" prefix scan algorithm.  Execution is comprised of five phases:\n     * -# Upsweep sequential reduction in registers (if threads contribute more than one input each).  Each thread then places the partial reduction of its item(s) into shared memory.\n     * -# Upsweep sequential reduction in shared memory.  Threads within a single warp rake across segments of shared partial reductions.\n     * -# A warp-synchronous Kogge-Stone style exclusive scan within the raking warp.\n     * -# Downsweep sequential exclusive scan in shared memory.  Threads within a single warp rake across segments of shared partial reductions, seeded with the warp-scan output.\n     * -# Downsweep sequential scan in registers (if threads contribute more than one input), seeded with the raking scan output.\n     *\n     * \\par\n     * \\image html block_scan_raking.png\n     * <div class=\"centercaption\">\\p BLOCK_SCAN_RAKING data flow for a hypothetical 16-thread thread block and 4-thread raking warp.</div>\n     *\n     * \\par Performance Considerations\n     * - Although this variant may suffer longer turnaround latencies when the\n     *   GPU is under-occupied, it can often provide higher overall throughput\n     *   across the GPU when suitably occupied.\n     */\n    BLOCK_SCAN_RAKING,\n\n\n    /**\n     * \\par Overview\n     * Similar to cub::BLOCK_SCAN_RAKING, but with fewer shared memory reads at\n     * the expense of higher register pressure.  Raking threads preserve their\n     * \"upsweep\" segment of values in registers while performing warp-synchronous\n     * scan, allowing the \"downsweep\" not to re-read them from shared memory.\n     */\n    BLOCK_SCAN_RAKING_MEMOIZE,\n\n\n    /**\n     * \\par Overview\n     * A quick \"tiled warpscans\" prefix scan algorithm.  Execution is comprised of four phases:\n     * -# Upsweep sequential reduction in registers (if threads contribute more than one input each).  Each thread then places the partial reduction of its item(s) into shared memory.\n     * -# Compute a shallow, but inefficient warp-synchronous Kogge-Stone style scan within each warp.\n     * -# A propagation phase where the warp scan outputs in each warp are updated with the aggregate from each preceding warp.\n     * -# Downsweep sequential scan in registers (if threads contribute more than one input), seeded with the raking scan output.\n     *\n     * \\par\n     * \\image html block_scan_warpscans.png\n     * <div class=\"centercaption\">\\p BLOCK_SCAN_WARP_SCANS data flow for a hypothetical 16-thread thread block and 4-thread raking warp.</div>\n     *\n     * \\par Performance Considerations\n     * - Although this variant may suffer lower overall throughput across the\n     *   GPU because due to a heavy reliance on inefficient warpscans, it can\n     *   often provide lower turnaround latencies when the GPU is under-occupied.\n     */\n    BLOCK_SCAN_WARP_SCANS,\n};\n\n\n/******************************************************************************\n * Block scan\n ******************************************************************************/\n\n/**\n * \\brief The BlockScan class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel prefix sum/scan of items partitioned across a CUDA thread block. ![](block_scan_logo.png)\n * \\ingroup BlockModule\n *\n * \\tparam T                Data type being scanned\n * \\tparam BLOCK_DIM_X      The thread block length in threads along the X dimension\n * \\tparam ALGORITHM        <b>[optional]</b> cub::BlockScanAlgorithm enumerator specifying the underlying algorithm to use (default: cub::BLOCK_SCAN_RAKING)\n * \\tparam BLOCK_DIM_Y      <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z      <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH         <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - Given a list of input elements and a binary reduction operator, a [<em>prefix scan</em>](http://en.wikipedia.org/wiki/Prefix_sum)\n *   produces an output list where each element is computed to be the reduction\n *   of the elements occurring earlier in the input list.  <em>Prefix sum</em>\n *   connotes a prefix scan with the addition operator. The term \\em inclusive indicates\n *   that the <em>i</em><sup>th</sup> output reduction incorporates the <em>i</em><sup>th</sup> input.\n *   The term \\em exclusive indicates the <em>i</em><sup>th</sup> input is not incorporated into\n *   the <em>i</em><sup>th</sup> output reduction.\n * - \\rowmajor\n * - BlockScan can be optionally specialized by algorithm to accommodate different workload profiles:\n *   -# <b>cub::BLOCK_SCAN_RAKING</b>.  An efficient (high throughput) \"raking reduce-then-scan\" prefix scan algorithm. [More...](\\ref cub::BlockScanAlgorithm)\n *   -# <b>cub::BLOCK_SCAN_RAKING_MEMOIZE</b>.  Similar to cub::BLOCK_SCAN_RAKING, but having higher throughput at the expense of additional register pressure for intermediate storage. [More...](\\ref cub::BlockScanAlgorithm)\n *   -# <b>cub::BLOCK_SCAN_WARP_SCANS</b>.  A quick (low latency) \"tiled warpscans\" prefix scan algorithm. [More...](\\ref cub::BlockScanAlgorithm)\n *\n * \\par Performance Considerations\n * - \\granularity\n * - Uses special instructions when applicable (e.g., warp \\p SHFL)\n * - Uses synchronization-free communication between warp lanes when applicable\n * - Invokes a minimal number of minimal block-wide synchronization barriers (only\n *   one or two depending on algorithm selection)\n * - Incurs zero bank conflicts for most types\n * - Computation is slightly more efficient (i.e., having lower instruction overhead) for:\n *   - Prefix sum variants (<b><em>vs.</em></b> generic scan)\n *   - \\blocksize\n * - See cub::BlockScanAlgorithm for performance details regarding algorithmic alternatives\n *\n * \\par A Simple Example\n * \\blockcollective{BlockScan}\n * \\par\n * The code snippet below illustrates an exclusive prefix sum of 512 integer items that\n * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n * where each thread owns 4 consecutive items.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize BlockScan for a 1D block of 128 threads on type int\n *     typedef cub::BlockScan<int, 128> BlockScan;\n *\n *     // Allocate shared memory for BlockScan\n *     __shared__ typename BlockScan::TempStorage temp_storage;\n *\n *     // Obtain a segment of consecutive items that are blocked across threads\n *     int thread_data[4];\n *     ...\n *\n *     // Collectively compute the block-wide exclusive prefix sum\n *     BlockScan(temp_storage).ExclusiveSum(thread_data, thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the block of threads is\n * <tt>{[1,1,1,1], [1,1,1,1], ..., [1,1,1,1]}</tt>.\n * The corresponding output \\p thread_data in those threads will be\n * <tt>{[0,1,2,3], [4,5,6,7], ..., [508,509,510,511]}</tt>.\n *\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_DIM_X,\n    BlockScanAlgorithm  ALGORITHM       = BLOCK_SCAN_RAKING,\n    int                 BLOCK_DIM_Y     = 1,\n    int                 BLOCK_DIM_Z     = 1,\n    int                 PTX_ARCH        = CUB_PTX_ARCH>\nclass BlockScan\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    /**\n     * Ensure the template parameterization meets the requirements of the\n     * specified algorithm. Currently, the BLOCK_SCAN_WARP_SCANS policy\n     * cannot be used with thread block sizes not a multiple of the\n     * architectural warp size.\n     */\n    static const BlockScanAlgorithm SAFE_ALGORITHM =\n        ((ALGORITHM == BLOCK_SCAN_WARP_SCANS) && (BLOCK_THREADS % CUB_WARP_THREADS(PTX_ARCH) != 0)) ?\n            BLOCK_SCAN_RAKING :\n            ALGORITHM;\n\n    typedef BlockScanWarpScans<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> WarpScans;\n    typedef BlockScanRaking<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, (SAFE_ALGORITHM == BLOCK_SCAN_RAKING_MEMOIZE), PTX_ARCH> Raking;\n\n    /// Define the delegate type for the desired algorithm\n    typedef typename If<(SAFE_ALGORITHM == BLOCK_SCAN_WARP_SCANS),\n        WarpScans,\n        Raking>::Type InternalBlockScan;\n\n    /// Shared memory storage layout type for BlockScan\n    typedef typename InternalBlockScan::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /******************************************************************************\n     * Public types\n     ******************************************************************************/\npublic:\n\n    /// \\smemstorage{BlockScan}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockScan()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockScan(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Exclusive prefix sum operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.  The value of 0 is applied as the initial value, and is assigned to \\p output in <em>thread</em><sub>0</sub>.\n     *\n     * \\par\n     * - \\identityzero\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix sum of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix sum\n     *     BlockScan(temp_storage).ExclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>1, 1, ..., 1</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>0, 1, ..., 127</tt>.\n     *\n     */\n    __device__ __forceinline__ void ExclusiveSum(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output)                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n    {\n        T initial_value = 0;\n        ExclusiveScan(input, output, initial_value, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.  The value of 0 is applied as the initial value, and is assigned to \\p output in <em>thread</em><sub>0</sub>.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\identityzero\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix sum of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix sum\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).ExclusiveSum(thread_data, thread_data, block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>1, 1, ..., 1</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>0, 1, ..., 127</tt>.\n     * Furthermore the value \\p 128 will be stored in \\p block_aggregate for all threads.\n     *\n     */\n    __device__ __forceinline__ void ExclusiveSum(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        T initial_value = 0;\n        ExclusiveScan(input, output, initial_value, cub::Sum(), block_aggregate);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.  Instead of using 0 as the block-wide prefix, the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\identityzero\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an exclusive prefix sum over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total += block_aggregate;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data = d_data[block_offset];\n     *\n     *         // Collectively compute the block-wide exclusive prefix sum\n     *         BlockScan(temp_storage).ExclusiveSum(\n     *             thread_data, thread_data, prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         d_data[block_offset] = thread_data;\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>1, 1, 1, 1, 1, 1, 1, 1, ...</tt>.\n     * The corresponding output for the first segment will be <tt>0, 1, ..., 127</tt>.\n     * The output for the second segment will be <tt>128, 129, ..., 255</tt>.\n     *\n     * \\tparam BlockPrefixCallbackOp        <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveSum(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        ExclusiveScan(input, output, cub::Sum(), block_prefix_callback_op);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Exclusive prefix sum operations (multiple data per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.  The value of 0 is applied as the initial value, and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>.\n     *\n     * \\par\n     * - \\identityzero\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix sum of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix sum\n     *     BlockScan(temp_storage).ExclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{ [1,1,1,1], [1,1,1,1], ..., [1,1,1,1] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void ExclusiveSum(\n        T                 (&input)[ITEMS_PER_THREAD],   ///< [in] Calling thread's input items\n        T                 (&output)[ITEMS_PER_THREAD])  ///< [out] Calling thread's output items (may be aliased to \\p input)\n    {\n        T initial_value = 0;\n        ExclusiveScan(input, output, initial_value, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.  The value of 0 is applied as the initial value, and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\identityzero\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix sum of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix sum\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).ExclusiveSum(thread_data, thread_data, block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{ [1,1,1,1], [1,1,1,1], ..., [1,1,1,1] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n     * Furthermore the value \\p 512 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void ExclusiveSum(\n        T                 (&input)[ITEMS_PER_THREAD],       ///< [in] Calling thread's input items\n        T                 (&output)[ITEMS_PER_THREAD],      ///< [out] Calling thread's output items (may be aliased to \\p input)\n        T                 &block_aggregate)                 ///< [out] block-wide aggregate reduction of input items\n    {\n        // Reduce consecutive thread items in registers\n        T initial_value = 0;\n        ExclusiveScan(input, output, initial_value, cub::Sum(), block_aggregate);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.  Instead of using 0 as the block-wide prefix, the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\identityzero\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an exclusive prefix sum over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 512 integer items that are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3)\n     * across 128 threads where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total += block_aggregate;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockLoad, BlockStore, and BlockScan for a 1D block of 128 threads, 4 ints per thread\n     *     typedef cub::BlockLoad<int*, 128, 4, BLOCK_LOAD_TRANSPOSE>   BlockLoad;\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_TRANSPOSE>  BlockStore;\n     *     typedef cub::BlockScan<int, 128>                             BlockScan;\n     *\n     *     // Allocate aliased shared memory for BlockLoad, BlockStore, and BlockScan\n     *     __shared__ union {\n     *         typename BlockLoad::TempStorage     load;\n     *         typename BlockScan::TempStorage     scan;\n     *         typename BlockStore::TempStorage    store;\n     *     } temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128 * 4)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data[4];\n     *         BlockLoad(temp_storage.load).Load(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *\n     *         // Collectively compute the block-wide exclusive prefix sum\n     *         int block_aggregate;\n     *         BlockScan(temp_storage.scan).ExclusiveSum(\n     *             thread_data, thread_data, prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         BlockStore(temp_storage.store).Store(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>1, 1, 1, 1, 1, 1, 1, 1, ...</tt>.\n     * The corresponding output for the first segment will be <tt>0, 1, 2, 3, ..., 510, 511</tt>.\n     * The output for the second segment will be <tt>512, 513, 514, 515, ..., 1022, 1023</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam BlockPrefixCallbackOp        <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        int ITEMS_PER_THREAD,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveSum(\n        T                       (&input)[ITEMS_PER_THREAD],   ///< [in] Calling thread's input items\n        T                       (&output)[ITEMS_PER_THREAD],  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        BlockPrefixCallbackOp   &block_prefix_callback_op)    ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        ExclusiveScan(input, output, cub::Sum(), block_prefix_callback_op);\n    }\n\n\n\n    //@}  end member group        // Exclusive prefix sums\n    /******************************************************************//**\n     * \\name Exclusive prefix scan operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix max scan of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix max scan\n     *     BlockScan(temp_storage).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>0, -1, 2, -3, ..., 126, -127</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>INT_MIN, 0, 0, 2, ..., 124, 126</tt>.\n     *\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        T               initial_value,                  ///< [in] Initial value to seed the exclusive scan (and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>)\n        ScanOp          scan_op)                        ///< [in] Binary scan functor \n    {\n        InternalBlockScan(temp_storage).ExclusiveScan(input, output, initial_value, scan_op);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix max scan of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix max scan\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max(), block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>0, -1, 2, -3, ..., 126, -127</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>INT_MIN, 0, 0, 2, ..., 124, 126</tt>.\n     * Furthermore the value \\p 126 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ScanOp   <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &output,            ///< [out] Calling thread's output items (may be aliased to \\p input)\n        T               initial_value,      ///< [in] Initial value to seed the exclusive scan (and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>)\n        ScanOp          scan_op,            ///< [in] Binary scan functor \n        T               &block_aggregate)   ///< [out] block-wide aggregate reduction of input items\n    {\n        InternalBlockScan(temp_storage).ExclusiveScan(input, output, initial_value, scan_op, block_aggregate);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an exclusive prefix max scan over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total = (block_aggregate > old_prefix) ? block_aggregate : old_prefix;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(INT_MIN);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data = d_data[block_offset];\n     *\n     *         // Collectively compute the block-wide exclusive prefix max scan\n     *         BlockScan(temp_storage).ExclusiveScan(\n     *             thread_data, thread_data, INT_MIN, cub::Max(), prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         d_data[block_offset] = thread_data;\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, -1, 2, -3, 4, -5, ...</tt>.\n     * The corresponding output for the first segment will be <tt>INT_MIN, 0, 0, 2, ..., 124, 126</tt>.\n     * The output for the second segment will be <tt>126, 128, 128, 130, ..., 252, 254</tt>.\n     *\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam BlockPrefixCallbackOp        <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan functor \n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        InternalBlockScan(temp_storage).ExclusiveScan(input, output, scan_op, block_prefix_callback_op);\n    }\n\n\n    //@}  end member group        // Inclusive prefix sums\n    /******************************************************************//**\n     * \\name Exclusive prefix scan operations (multiple data per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix max scan of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix max scan\n     *     BlockScan(temp_storage).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,-1,2,-3], [4,-5,6,-7], ..., [508,-509,510,-511] }</tt>.\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [INT_MIN,0,0,2], [2,4,4,6], ..., [506,508,508,510] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                 (&input)[ITEMS_PER_THREAD],   ///< [in] Calling thread's input items\n        T                 (&output)[ITEMS_PER_THREAD],  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        T                 initial_value,                ///< [in] Initial value to seed the exclusive scan (and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>)\n        ScanOp            scan_op)                      ///< [in] Binary scan functor\n    {\n        // Reduce consecutive thread items in registers\n        T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n        // Exclusive thread block-scan\n        ExclusiveScan(thread_prefix, thread_prefix, initial_value, scan_op);\n\n        // Exclusive scan in registers with prefix as seed\n        internal::ThreadScanExclusive(input, output, scan_op, thread_prefix);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an exclusive prefix max scan of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide exclusive prefix max scan\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max(), block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{ [0,-1,2,-3], [4,-5,6,-7], ..., [508,-509,510,-511] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>{ [INT_MIN,0,0,2], [2,4,4,6], ..., [506,508,508,510] }</tt>.\n     * Furthermore the value \\p 510 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                 (&input)[ITEMS_PER_THREAD],   ///< [in] Calling thread's input items\n        T                 (&output)[ITEMS_PER_THREAD],  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        T                 initial_value,                ///< [in] Initial value to seed the exclusive scan (and is assigned to \\p output[0] in <em>thread</em><sub>0</sub>)\n        ScanOp            scan_op,                      ///< [in] Binary scan functor\n        T                 &block_aggregate)             ///< [out] block-wide aggregate reduction of input items\n    {\n        // Reduce consecutive thread items in registers\n        T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n        // Exclusive thread block-scan\n        ExclusiveScan(thread_prefix, thread_prefix, initial_value, scan_op, block_aggregate);\n\n        // Exclusive scan in registers with prefix as seed\n        internal::ThreadScanExclusive(input, output, scan_op, thread_prefix);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an exclusive prefix max scan over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total = (block_aggregate > old_prefix) ? block_aggregate : old_prefix;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockLoad, BlockStore, and BlockScan for a 1D block of 128 threads, 4 ints per thread\n     *     typedef cub::BlockLoad<int*, 128, 4, BLOCK_LOAD_TRANSPOSE>   BlockLoad;\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_TRANSPOSE>  BlockStore;\n     *     typedef cub::BlockScan<int, 128>                             BlockScan;\n     *\n     *     // Allocate aliased shared memory for BlockLoad, BlockStore, and BlockScan\n     *     __shared__ union {\n     *         typename BlockLoad::TempStorage     load;\n     *         typename BlockScan::TempStorage     scan;\n     *         typename BlockStore::TempStorage    store;\n     *     } temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128 * 4)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data[4];\n     *         BlockLoad(temp_storage.load).Load(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *\n     *         // Collectively compute the block-wide exclusive prefix max scan\n     *         BlockScan(temp_storage.scan).ExclusiveScan(\n     *             thread_data, thread_data, INT_MIN, cub::Max(), prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         BlockStore(temp_storage.store).Store(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, -1, 2, -3, 4, -5, ...</tt>.\n     * The corresponding output for the first segment will be <tt>INT_MIN, 0, 0, 2, 2, 4, ..., 508, 510</tt>.\n     * The output for the second segment will be <tt>510, 512, 512, 514, 514, 516, ..., 1020, 1022</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD         <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp                   <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam BlockPrefixCallbackOp    <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp,\n        typename        BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T                       (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan functor\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        // Reduce consecutive thread items in registers\n        T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n        // Exclusive thread block-scan\n        ExclusiveScan(thread_prefix, thread_prefix, scan_op, block_prefix_callback_op);\n\n        // Exclusive scan in registers with prefix as seed\n        internal::ThreadScanExclusive(input, output, scan_op, thread_prefix);\n    }\n\n\n    //@}  end member group\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document no-initial-value scans\n\n    /******************************************************************//**\n     * \\name Exclusive prefix scan operations (no initial value, single datum per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan functor\n    {\n        InternalBlockScan(temp_storage).ExclusiveScan(input, output, scan_op);\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\tparam ScanOp   <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan functor\n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        InternalBlockScan(temp_storage).ExclusiveScan(input, output, scan_op, block_aggregate);\n    }\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Exclusive prefix scan operations (no initial value, multiple data per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                 (&input)[ITEMS_PER_THREAD],   ///< [in] Calling thread's input items\n        T                 (&output)[ITEMS_PER_THREAD],  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp            scan_op)                      ///< [in] Binary scan functor\n    {\n        // Reduce consecutive thread items in registers\n        T thread_partial = internal::ThreadReduce(input, scan_op);\n\n        // Exclusive thread block-scan\n        ExclusiveScan(thread_partial, thread_partial, scan_op);\n\n        // Exclusive scan in registers with prefix\n        internal::ThreadScanExclusive(input, output, scan_op, thread_partial, (linear_tid != 0));\n    }\n\n\n    /**\n     * \\brief Computes an exclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T               (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan functor\n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        // Reduce consecutive thread items in registers\n        T thread_partial = internal::ThreadReduce(input, scan_op);\n\n        // Exclusive thread block-scan\n        ExclusiveScan(thread_partial, thread_partial, scan_op, block_aggregate);\n\n        // Exclusive scan in registers with prefix\n        internal::ThreadScanExclusive(input, output, scan_op, thread_partial, (linear_tid != 0));\n    }\n\n\n    //@}  end member group\n#endif // DOXYGEN_SHOULD_SKIP_THIS  // Do not document no-initial-value scans\n\n    /******************************************************************//**\n     * \\name Inclusive prefix sum operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.\n     *\n     * \\par\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix sum of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix sum\n     *     BlockScan(temp_storage).InclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>1, 1, ..., 1</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>1, 2, ..., 128</tt>.\n     *\n     */\n    __device__ __forceinline__ void InclusiveSum(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output)                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n    {\n        InclusiveScan(input, output, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix sum of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix sum\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).InclusiveSum(thread_data, thread_data, block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>1, 1, ..., 1</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>1, 2, ..., 128</tt>.\n     * Furthermore the value \\p 128 will be stored in \\p block_aggregate for all threads.\n     *\n     */\n    __device__ __forceinline__ void InclusiveSum(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        InclusiveScan(input, output, cub::Sum(), block_aggregate);\n    }\n\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes one input element.  Instead of using 0 as the block-wide prefix, the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an inclusive prefix sum over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total += block_aggregate;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data = d_data[block_offset];\n     *\n     *         // Collectively compute the block-wide inclusive prefix sum\n     *         BlockScan(temp_storage).InclusiveSum(\n     *             thread_data, thread_data, prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         d_data[block_offset] = thread_data;\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>1, 1, 1, 1, 1, 1, 1, 1, ...</tt>.\n     * The corresponding output for the first segment will be <tt>1, 2, ..., 128</tt>.\n     * The output for the second segment will be <tt>129, 130, ..., 256</tt>.\n     *\n     * \\tparam BlockPrefixCallbackOp          <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveSum(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        InclusiveScan(input, output, cub::Sum(), block_prefix_callback_op);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive prefix sum operations (multiple data per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix sum of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix sum\n     *     BlockScan(temp_storage).InclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{ [1,1,1,1], [1,1,1,1], ..., [1,1,1,1] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>{ [1,2,3,4], [5,6,7,8], ..., [509,510,511,512] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void InclusiveSum(\n        T               (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T               (&output)[ITEMS_PER_THREAD])    ///< [out] Calling thread's output items (may be aliased to \\p input)\n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveSum(input[0], output[0]);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            Sum scan_op;\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan\n            ExclusiveSum(thread_prefix, thread_prefix);\n\n            // Inclusive scan in registers with prefix as seed\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix, (linear_tid != 0));\n        }\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix sum of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix sum\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).InclusiveSum(thread_data, thread_data, block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [1,1,1,1], [1,1,1,1], ..., [1,1,1,1] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be\n     * <tt>{ [1,2,3,4], [5,6,7,8], ..., [509,510,511,512] }</tt>.\n     * Furthermore the value \\p 512 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void InclusiveSum(\n        T               (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T               (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveSum(input[0], output[0], block_aggregate);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            Sum scan_op;\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan\n            ExclusiveSum(thread_prefix, thread_prefix, block_aggregate);\n\n            // Inclusive scan in registers with prefix as seed\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix, (linear_tid != 0));\n        }\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using addition (+) as the scan operator.  Each thread contributes an array of consecutive input elements.  Instead of using 0 as the block-wide prefix, the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an inclusive prefix sum over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 512 integer items that are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3)\n     * across 128 threads where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total += block_aggregate;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockLoad, BlockStore, and BlockScan for a 1D block of 128 threads, 4 ints per thread\n     *     typedef cub::BlockLoad<int*, 128, 4, BLOCK_LOAD_TRANSPOSE>   BlockLoad;\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_TRANSPOSE>  BlockStore;\n     *     typedef cub::BlockScan<int, 128>                             BlockScan;\n     *\n     *     // Allocate aliased shared memory for BlockLoad, BlockStore, and BlockScan\n     *     __shared__ union {\n     *         typename BlockLoad::TempStorage     load;\n     *         typename BlockScan::TempStorage     scan;\n     *         typename BlockStore::TempStorage    store;\n     *     } temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128 * 4)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data[4];\n     *         BlockLoad(temp_storage.load).Load(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *\n     *         // Collectively compute the block-wide inclusive prefix sum\n     *         BlockScan(temp_storage.scan).IncluisveSum(\n     *             thread_data, thread_data, prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         BlockStore(temp_storage.store).Store(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>1, 1, 1, 1, 1, 1, 1, 1, ...</tt>.\n     * The corresponding output for the first segment will be <tt>1, 2, 3, 4, ..., 511, 512</tt>.\n     * The output for the second segment will be <tt>513, 514, 515, 516, ..., 1023, 1024</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam BlockPrefixCallbackOp        <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        int ITEMS_PER_THREAD,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveSum(\n        T                       (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T                       (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveSum(input[0], output[0], block_prefix_callback_op);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            Sum scan_op;\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan\n            ExclusiveSum(thread_prefix, thread_prefix, block_prefix_callback_op);\n\n            // Inclusive scan in registers with prefix as seed\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix);\n        }\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive prefix scan operations\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix max scan of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix max scan\n     *     BlockScan(temp_storage).InclusiveScan(thread_data, thread_data, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>0, -1, 2, -3, ..., 126, -127</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>0, 0, 2, 2, ..., 126, 126</tt>.\n     *\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan functor \n    {\n        InternalBlockScan(temp_storage).InclusiveScan(input, output, scan_op);\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix max scan of 128 integer items that\n     * are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain input item for each thread\n     *     int thread_data;\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix max scan\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).InclusiveScan(thread_data, thread_data, cub::Max(), block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>0, -1, 2, -3, ..., 126, -127</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>0, 0, 2, 2, ..., 126, 126</tt>.\n     * Furthermore the value \\p 126 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ScanOp   <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan functor \n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        InternalBlockScan(temp_storage).InclusiveScan(input, output, scan_op, block_aggregate);\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - Supports non-commutative scan operators.\n     * - \\rowmajor\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an inclusive prefix max scan over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total = (block_aggregate > old_prefix) ? block_aggregate : old_prefix;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(INT_MIN);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data = d_data[block_offset];\n     *\n     *         // Collectively compute the block-wide inclusive prefix max scan\n     *         BlockScan(temp_storage).InclusiveScan(\n     *             thread_data, thread_data, cub::Max(), prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         d_data[block_offset] = thread_data;\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, -1, 2, -3, 4, -5, ...</tt>.\n     * The corresponding output for the first segment will be <tt>0, 0, 2, 2, ..., 126, 126</tt>.\n     * The output for the second segment will be <tt>128, 128, 130, 130, ..., 254, 254</tt>.\n     *\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam BlockPrefixCallbackOp        <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan functor \n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        InternalBlockScan(temp_storage).InclusiveScan(input, output, scan_op, block_prefix_callback_op);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive prefix scan operations (multiple data per thread)\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix max scan of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix max scan\n     *     BlockScan(temp_storage).InclusiveScan(thread_data, thread_data, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{ [0,-1,2,-3], [4,-5,6,-7], ..., [508,-509,510,-511] }</tt>.  The\n     * corresponding output \\p thread_data in those threads will be <tt>{ [0,0,2,2], [4,4,6,6], ..., [508,508,510,510] }</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T               (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan functor \n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveScan(input[0], output[0], scan_op);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan\n            ExclusiveScan(thread_prefix, thread_prefix, scan_op);\n\n            // Inclusive scan in registers with prefix as seed (first thread does not seed)\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix, (linear_tid != 0));\n        }\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates an inclusive prefix max scan of 512 integer items that\n     * are partitioned in a [<em>blocked arrangement</em>](index.html#sec5sec3) across 128 threads\n     * where each thread owns 4 consecutive items.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize BlockScan for a 1D block of 128 threads on type int\n     *     typedef cub::BlockScan<int, 128> BlockScan;\n     *\n     *     // Allocate shared memory for BlockScan\n     *     __shared__ typename BlockScan::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Collectively compute the block-wide inclusive prefix max scan\n     *     int block_aggregate;\n     *     BlockScan(temp_storage).InclusiveScan(thread_data, thread_data, cub::Max(), block_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is\n     * <tt>{ [0,-1,2,-3], [4,-5,6,-7], ..., [508,-509,510,-511] }</tt>.\n     * The corresponding output \\p thread_data in those threads will be\n     * <tt>{ [0,0,2,2], [4,4,6,6], ..., [508,508,510,510] }</tt>.\n     * Furthermore the value \\p 510 will be stored in \\p block_aggregate for all threads.\n     *\n     * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp               <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename         ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T               (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan functor \n        T               &block_aggregate)               ///< [out] block-wide aggregate reduction of input items\n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveScan(input[0], output[0], scan_op, block_aggregate);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan (with no initial value)\n            ExclusiveScan(thread_prefix, thread_prefix, scan_op, block_aggregate);\n\n            // Inclusive scan in registers with prefix as seed (first thread does not seed)\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix, (linear_tid != 0));\n        }\n    }\n\n\n    /**\n     * \\brief Computes an inclusive block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes an array of consecutive input elements.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n     *\n     * \\par\n     * - The \\p block_prefix_callback_op functor must implement a member function <tt>T operator()(T block_aggregate)</tt>.\n     *   The functor's input parameter \\p block_aggregate is the same value also returned by the scan operation.\n     *   The functor will be invoked by the first warp of threads in the block, however only the return value from\n     *   <em>lane</em><sub>0</sub> is applied as the block-wide prefix.  Can be stateful.\n     * - Supports non-commutative scan operators.\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a single thread block that progressively\n     * computes an inclusive prefix max scan over multiple \"tiles\" of input using a\n     * prefix functor to maintain a running total between block-wide scans.  Each tile consists\n     * of 128 integer items that are partitioned across 128 threads.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_scan.cuh>\n     *\n     * // A stateful callback functor that maintains a running prefix to be applied\n     * // during consecutive scan operations.\n     * struct BlockPrefixCallbackOp\n     * {\n     *     // Running prefix\n     *     int running_total;\n     *\n     *     // Constructor\n     *     __device__ BlockPrefixCallbackOp(int running_total) : running_total(running_total) {}\n     *\n     *     // Callback operator to be entered by the first warp of threads in the block.\n     *     // Thread-0 is responsible for returning a value for seeding the block-wide scan.\n     *     __device__ int operator()(int block_aggregate)\n     *     {\n     *         int old_prefix = running_total;\n     *         running_total = (block_aggregate > old_prefix) ? block_aggregate : old_prefix;\n     *         return old_prefix;\n     *     }\n     * };\n     *\n     * __global__ void ExampleKernel(int *d_data, int num_items, ...)\n     * {\n     *     // Specialize BlockLoad, BlockStore, and BlockScan for a 1D block of 128 threads, 4 ints per thread\n     *     typedef cub::BlockLoad<int*, 128, 4, BLOCK_LOAD_TRANSPOSE>   BlockLoad;\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_TRANSPOSE>  BlockStore;\n     *     typedef cub::BlockScan<int, 128>                             BlockScan;\n     *\n     *     // Allocate aliased shared memory for BlockLoad, BlockStore, and BlockScan\n     *     __shared__ union {\n     *         typename BlockLoad::TempStorage     load;\n     *         typename BlockScan::TempStorage     scan;\n     *         typename BlockStore::TempStorage    store;\n     *     } temp_storage;\n     *\n     *     // Initialize running total\n     *     BlockPrefixCallbackOp prefix_op(0);\n     *\n     *     // Have the block iterate over segments of items\n     *     for (int block_offset = 0; block_offset < num_items; block_offset += 128 * 4)\n     *     {\n     *         // Load a segment of consecutive items that are blocked across threads\n     *         int thread_data[4];\n     *         BlockLoad(temp_storage.load).Load(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *\n     *         // Collectively compute the block-wide inclusive prefix max scan\n     *         BlockScan(temp_storage.scan).InclusiveScan(\n     *             thread_data, thread_data, cub::Max(), prefix_op);\n     *         CTA_SYNC();\n     *\n     *         // Store scanned items to output segment\n     *         BlockStore(temp_storage.store).Store(d_data + block_offset, thread_data);\n     *         CTA_SYNC();\n     *     }\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>0, -1, 2, -3, 4, -5, ...</tt>.\n     * The corresponding output for the first segment will be <tt>0, 0, 2, 2, 4, 4, ..., 510, 510</tt>.\n     * The output for the second segment will be <tt>512, 512, 514, 514, 516, 516, ..., 1022, 1022</tt>.\n     *\n     * \\tparam ITEMS_PER_THREAD         <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n     * \\tparam ScanOp                   <b>[inferred]</b> Binary scan functor  type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam BlockPrefixCallbackOp    <b>[inferred]</b> Call-back functor type having member <tt>T operator()(T block_aggregate)</tt>\n     */\n    template <\n        int             ITEMS_PER_THREAD,\n        typename        ScanOp,\n        typename        BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       (&input)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input items\n        T                       (&output)[ITEMS_PER_THREAD],    ///< [out] Calling thread's output items (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan functor \n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a block-wide prefix to be applied to the logical input sequence.\n    {\n        if (ITEMS_PER_THREAD == 1)\n        {\n            InclusiveScan(input[0], output[0], scan_op, block_prefix_callback_op);\n        }\n        else\n        {\n            // Reduce consecutive thread items in registers\n            T thread_prefix = internal::ThreadReduce(input, scan_op);\n\n            // Exclusive thread block-scan\n            ExclusiveScan(thread_prefix, thread_prefix, scan_op, block_prefix_callback_op);\n\n            // Inclusive scan in registers with prefix as seed\n            internal::ThreadScanInclusive(input, output, scan_op, thread_prefix);\n        }\n    }\n\n    //@}  end member group\n\n\n};\n\n/**\n * \\example example_block_scan.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_shuffle.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockShuffle class provides [<em>collective</em>](index.html#sec0) methods for shuffling data partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../util_arch.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_macro.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief The BlockShuffle class provides [<em>collective</em>](index.html#sec0) methods for shuffling data partitioned across a CUDA thread block.\n * \\ingroup BlockModule\n *\n * \\tparam T                    The data type to be exchanged.\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * It is commonplace for blocks of threads to rearrange data items between\n * threads.  The BlockShuffle abstraction allows threads to efficiently shift items\n * either (a) up to their successor or (b) down to their predecessor.\n *\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_DIM_X,\n    int                 BLOCK_DIM_Y         = 1,\n    int                 BLOCK_DIM_Z         = 1,\n    int                 PTX_ARCH            = CUB_PTX_ARCH>\nclass BlockShuffle\n{\nprivate:\n\n    /******************************************************************************\n     * Constants\n     ******************************************************************************/\n\n    enum\n    {\n        BLOCK_THREADS               = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        LOG_WARP_THREADS            = CUB_LOG_WARP_THREADS(PTX_ARCH),\n        WARP_THREADS                = 1 << LOG_WARP_THREADS,\n        WARPS                       = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n    };\n\n    /******************************************************************************\n     * Type definitions\n     ******************************************************************************/\n\n    /// Shared memory storage layout type (last element from each thread's input)\n    struct _TempStorage\n    {\n        T prev[BLOCK_THREADS];\n        T next[BLOCK_THREADS];\n    };\n\n\npublic:\n\n    /// \\smemstorage{BlockShuffle}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\nprivate:\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    unsigned int linear_tid;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\npublic:\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockShuffle()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockShuffle(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Shuffle movement\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Each <em>thread<sub>i</sub></em> obtains the \\p input provided by <em>thread</em><sub><em>i</em>+<tt>distance</tt></sub>. The offset \\p distance may be negative.\n     *\n     * \\par\n     * - \\smemreuse\n     */\n    __device__ __forceinline__ void Offset(\n        T   input,                  ///< [in] The input item from the calling thread (<em>thread<sub>i</sub></em>)\n        T&  output,                 ///< [out] The \\p input item from the successor (or predecessor) thread <em>thread</em><sub><em>i</em>+<tt>distance</tt></sub> (may be aliased to \\p input).  This value is only updated for for <em>thread<sub>i</sub></em> when 0 <= (<em>i</em> + \\p distance) < <tt>BLOCK_THREADS-1</tt>\n        int distance = 1)           ///< [in] Offset distance (may be negative)\n    {\n        temp_storage[linear_tid].prev = input;\n\n        CTA_SYNC();\n\n        if ((linear_tid + distance >= 0) && (linear_tid + distance < BLOCK_THREADS))\n            output = temp_storage[linear_tid + distance].prev;\n    }\n\n\n    /**\n     * \\brief Each <em>thread<sub>i</sub></em> obtains the \\p input provided by <em>thread</em><sub><em>i</em>+<tt>distance</tt></sub>.\n     *\n     * \\par\n     * - \\smemreuse\n     */\n    __device__ __forceinline__ void Rotate(\n        T   input,                  ///< [in] The calling thread's input item\n        T&  output,                 ///< [out] The \\p input item from thread <em>thread</em><sub>(<em>i</em>+<tt>distance></tt>)%<tt><BLOCK_THREADS></tt></sub> (may be aliased to \\p input).  This value is not updated for <em>thread</em><sub>BLOCK_THREADS-1</sub>\n        unsigned int distance = 1)  ///< [in] Offset distance (0 < \\p distance < <tt>BLOCK_THREADS</tt>)\n    {\n        temp_storage[linear_tid].prev = input;\n\n        CTA_SYNC();\n\n        unsigned int offset = threadIdx.x + distance;\n        if (offset >= BLOCK_THREADS)\n            offset -= BLOCK_THREADS;\n\n        output = temp_storage[offset].prev;\n    }\n\n\n    /**\n     * \\brief The thread block rotates its [<em>blocked arrangement</em>](index.html#sec5sec3) of \\p input items, shifting it up by one item\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void Up(\n        T (&input)[ITEMS_PER_THREAD],   ///< [in] The calling thread's input items\n        T (&prev)[ITEMS_PER_THREAD])    ///< [out] The corresponding predecessor items (may be aliased to \\p input).  The item \\p prev[0] is not updated for <em>thread</em><sub>0</sub>.\n    {\n        temp_storage[linear_tid].prev = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = ITEMS_PER_THREAD - 1; ITEM > 0; --ITEM)\n            prev[ITEM] = input[ITEM - 1];\n\n\n        if (linear_tid > 0)\n            prev[0] = temp_storage[linear_tid - 1].prev;\n    }\n\n\n    /**\n     * \\brief The thread block rotates its [<em>blocked arrangement</em>](index.html#sec5sec3) of \\p input items, shifting it up by one item.  All threads receive the \\p input provided by <em>thread</em><sub><tt>BLOCK_THREADS-1</tt></sub>.\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void Up(\n        T (&input)[ITEMS_PER_THREAD],   ///< [in] The calling thread's input items\n        T (&prev)[ITEMS_PER_THREAD],    ///< [out] The corresponding predecessor items (may be aliased to \\p input).  The item \\p prev[0] is not updated for <em>thread</em><sub>0</sub>.\n        T &block_suffix)                ///< [out] The item \\p input[ITEMS_PER_THREAD-1] from <em>thread</em><sub><tt>BLOCK_THREADS-1</tt></sub>, provided to all threads\n    {\n        Up(input, prev);\n        block_suffix = temp_storage[BLOCK_THREADS - 1].prev;\n    }\n\n\n    /**\n     * \\brief The thread block rotates its [<em>blocked arrangement</em>](index.html#sec5sec3) of \\p input items, shifting it down by one item\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void Down(\n        T (&input)[ITEMS_PER_THREAD],   ///< [in] The calling thread's input items\n        T (&prev)[ITEMS_PER_THREAD])    ///< [out] The corresponding predecessor items (may be aliased to \\p input).  The value \\p prev[0] is not updated for <em>thread</em><sub>BLOCK_THREADS-1</sub>.\n    {\n        temp_storage[linear_tid].prev = input[ITEMS_PER_THREAD - 1];\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int ITEM = ITEMS_PER_THREAD - 1; ITEM > 0; --ITEM)\n            prev[ITEM] = input[ITEM - 1];\n\n        if (linear_tid > 0)\n            prev[0] = temp_storage[linear_tid - 1].prev;\n    }\n\n\n    /**\n     * \\brief The thread block rotates its [<em>blocked arrangement</em>](index.html#sec5sec3) of input items, shifting it down by one item.  All threads receive \\p input[0] provided by <em>thread</em><sub><tt>0</tt></sub>.\n     *\n     * \\par\n     * - \\blocked\n     * - \\granularity\n     * - \\smemreuse\n     */\n    template <int ITEMS_PER_THREAD>\n    __device__ __forceinline__ void Down(\n        T (&input)[ITEMS_PER_THREAD],   ///< [in] The calling thread's input items\n        T (&prev)[ITEMS_PER_THREAD],    ///< [out] The corresponding predecessor items (may be aliased to \\p input).  The value \\p prev[0] is not updated for <em>thread</em><sub>BLOCK_THREADS-1</sub>.\n        T &block_prefix)                ///< [out] The item \\p input[0] from <em>thread</em><sub><tt>0</tt></sub>, provided to all threads\n    {\n        Up(input, prev);\n        block_prefix = temp_storage[BLOCK_THREADS - 1].prev;\n    }\n\n    //@}  end member group\n\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/block_store.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Operations for writing linear segments of data from the CUDA thread block\n */\n\n#pragma once\n\n#include <iterator>\n\n#include \"block_exchange.cuh\"\n#include \"../util_ptx.cuh\"\n#include \"../util_macro.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIo\n * @{\n */\n\n\n/******************************************************************//**\n * \\name Blocked arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n/**\n * \\brief Store a blocked arrangement of items across a thread block into a linear segment of items.\n *\n * \\blocked\n *\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectBlocked(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n{\n    OutputIteratorT thread_itr = block_itr + (linear_tid * ITEMS_PER_THREAD);\n\n    // Store directly in thread-blocked order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        thread_itr[ITEM] = items[ITEM];\n    }\n}\n\n\n/**\n * \\brief Store a blocked arrangement of items across a thread block into a linear segment of items, guarded by range\n *\n * \\blocked\n *\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectBlocked(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n    int                 valid_items)                ///< [in] Number of valid items to write\n{\n    OutputIteratorT thread_itr = block_itr + (linear_tid * ITEMS_PER_THREAD);\n\n    // Store directly in thread-blocked order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if (ITEM + (linear_tid * ITEMS_PER_THREAD) < valid_items)\n        {\n            thread_itr[ITEM] = items[ITEM];\n        }\n    }\n}\n\n\n/**\n * \\brief Store a blocked arrangement of items across a thread block into a linear segment of items.\n *\n * \\blocked\n *\n * The output offset (\\p block_ptr + \\p block_offset) must be quad-item aligned,\n * which is the default starting offset returned by \\p cudaMalloc()\n *\n * \\par\n * The following conditions will prevent vectorization and storing will fall back to cub::BLOCK_STORE_DIRECT:\n *   - \\p ITEMS_PER_THREAD is odd\n *   - The data type \\p T is not a built-in primitive or CUDA vector type (e.g., \\p short, \\p int2, \\p double, \\p float2, etc.)\n *\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n *\n */\ntemplate <\n    typename            T,\n    int                 ITEMS_PER_THREAD>\n__device__ __forceinline__ void StoreDirectBlockedVectorized(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    T                   *block_ptr,                 ///< [in] Input pointer for storing from\n    T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n{\n    enum\n    {\n        // Maximum CUDA vector size is 4 elements\n        MAX_VEC_SIZE = CUB_MIN(4, ITEMS_PER_THREAD),\n\n        // Vector size must be a power of two and an even divisor of the items per thread\n        VEC_SIZE = ((((MAX_VEC_SIZE - 1) & MAX_VEC_SIZE) == 0) && ((ITEMS_PER_THREAD % MAX_VEC_SIZE) == 0)) ?\n            MAX_VEC_SIZE :\n            1,\n\n        VECTORS_PER_THREAD = ITEMS_PER_THREAD / VEC_SIZE,\n    };\n\n    // Vector type\n    typedef typename CubVector<T, VEC_SIZE>::Type Vector;\n\n    // Alias global pointer\n    Vector *block_ptr_vectors = reinterpret_cast<Vector*>(const_cast<T*>(block_ptr));\n\n    // Alias pointers (use \"raw\" array here which should get optimized away to prevent conservative PTXAS lmem spilling)\n    Vector raw_vector[VECTORS_PER_THREAD];\n    T *raw_items = reinterpret_cast<T*>(raw_vector);\n\n    // Copy\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        raw_items[ITEM] = items[ITEM];\n    }\n\n    // Direct-store using vector types\n    StoreDirectBlocked(linear_tid, block_ptr_vectors, raw_vector);\n}\n\n\n\n//@}  end member group\n/******************************************************************//**\n * \\name Striped arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n\n/**\n * \\brief Store a striped arrangement of data across the thread block into a linear segment of items.\n *\n * \\striped\n *\n * \\tparam BLOCK_THREADS        The thread block size in threads\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectStriped(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n{\n    OutputIteratorT thread_itr = block_itr + linear_tid;\n\n    // Store directly in striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        thread_itr[(ITEM * BLOCK_THREADS)] = items[ITEM];\n    }\n}\n\n\n/**\n * \\brief Store a striped arrangement of data across the thread block into a linear segment of items, guarded by range\n *\n * \\striped\n *\n * \\tparam BLOCK_THREADS        The thread block size in threads\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectStriped(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n    int                 valid_items)                ///< [in] Number of valid items to write\n{\n    OutputIteratorT thread_itr = block_itr + linear_tid;\n\n    // Store directly in striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if ((ITEM * BLOCK_THREADS) + linear_tid < valid_items)\n        {\n            thread_itr[(ITEM * BLOCK_THREADS)] = items[ITEM];\n        }\n    }\n}\n\n\n\n//@}  end member group\n/******************************************************************//**\n * \\name Warp-striped arrangement I/O (direct)\n *********************************************************************/\n//@{\n\n\n/**\n * \\brief Store a warp-striped arrangement of data across the thread block into a linear segment of items.\n *\n * \\warpstriped\n *\n * \\par Usage Considerations\n * The number of threads in the thread block must be a multiple of the architecture's warp size.\n *\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectWarpStriped(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD]) ///< [out] Data to load\n{\n    int tid         = linear_tid & (CUB_PTX_WARP_THREADS - 1);\n    int wid         = linear_tid >> CUB_PTX_LOG_WARP_THREADS;\n    int warp_offset = wid * CUB_PTX_WARP_THREADS * ITEMS_PER_THREAD;\n\n    OutputIteratorT thread_itr = block_itr + warp_offset + tid;\n\n    // Store directly in warp-striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        thread_itr[(ITEM * CUB_PTX_WARP_THREADS)] = items[ITEM];\n    }\n}\n\n\n/**\n * \\brief Store a warp-striped arrangement of data across the thread block into a linear segment of items, guarded by range\n *\n * \\warpstriped\n *\n * \\par Usage Considerations\n * The number of threads in the thread block must be a multiple of the architecture's warp size.\n *\n * \\tparam T                    <b>[inferred]</b> The data type to store.\n * \\tparam ITEMS_PER_THREAD     <b>[inferred]</b> The number of consecutive items partitioned onto each thread.\n * \\tparam OutputIteratorT      <b>[inferred]</b> The random-access iterator type for output \\iterator.\n */\ntemplate <\n    typename            T,\n    int                 ITEMS_PER_THREAD,\n    typename            OutputIteratorT>\n__device__ __forceinline__ void StoreDirectWarpStriped(\n    int                 linear_tid,                 ///< [in] A suitable 1D thread-identifier for the calling thread (e.g., <tt>(threadIdx.y * blockDim.x) + linear_tid</tt> for 2D thread blocks)\n    OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n    T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n    int                 valid_items)                ///< [in] Number of valid items to write\n{\n    int tid         = linear_tid & (CUB_PTX_WARP_THREADS - 1);\n    int wid         = linear_tid >> CUB_PTX_LOG_WARP_THREADS;\n    int warp_offset = wid * CUB_PTX_WARP_THREADS * ITEMS_PER_THREAD;\n\n    OutputIteratorT thread_itr = block_itr + warp_offset + tid;\n\n    // Store directly in warp-striped order\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n    {\n        if (warp_offset + tid + (ITEM * CUB_PTX_WARP_THREADS) < valid_items)\n        {\n            thread_itr[(ITEM * CUB_PTX_WARP_THREADS)] = items[ITEM];\n        }\n    }\n}\n\n\n//@}  end member group\n\n\n/** @} */       // end group UtilIo\n\n\n//-----------------------------------------------------------------------------\n// Generic BlockStore abstraction\n//-----------------------------------------------------------------------------\n\n/**\n * \\brief cub::BlockStoreAlgorithm enumerates alternative algorithms for cub::BlockStore to write a blocked arrangement of items across a CUDA thread block to a linear segment of memory.\n */\nenum BlockStoreAlgorithm\n{\n    /**\n     * \\par Overview\n     *\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) of data is written\n     * directly to memory.\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) decreases as the\n     *   access stride between threads increases (i.e., the number items per thread).\n     */\n    BLOCK_STORE_DIRECT,\n\n    /**\n     * \\par Overview\n     *\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) of data is written directly\n     * to memory using CUDA's built-in vectorized stores as a coalescing optimization.\n     * For example, <tt>st.global.v4.s32</tt> instructions will be generated\n     * when \\p T = \\p int and \\p ITEMS_PER_THREAD % 4 == 0.\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high until the the\n     *   access stride between threads (i.e., the number items per thread) exceeds the\n     *   maximum vector store width (typically 4 items or 64B, whichever is lower).\n     * - The following conditions will prevent vectorization and writing will fall back to cub::BLOCK_STORE_DIRECT:\n     *   - \\p ITEMS_PER_THREAD is odd\n     *   - The \\p OutputIteratorT is not a simple pointer type\n     *   - The block output offset is not quadword-aligned\n     *   - The data type \\p T is not a built-in primitive or CUDA vector type (e.g., \\p short, \\p int2, \\p double, \\p float2, etc.)\n     */\n    BLOCK_STORE_VECTORIZE,\n\n    /**\n     * \\par Overview\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) is locally\n     * transposed and then efficiently written to memory as a [<em>striped arrangement</em>](index.html#sec5sec3).\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items written per thread.\n     * - The local reordering incurs slightly longer latencies and throughput than the\n     *   direct cub::BLOCK_STORE_DIRECT and cub::BLOCK_STORE_VECTORIZE alternatives.\n     */\n    BLOCK_STORE_TRANSPOSE,\n\n    /**\n     * \\par Overview\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) is locally\n     * transposed and then efficiently written to memory as a\n     * [<em>warp-striped arrangement</em>](index.html#sec5sec3)\n     *\n     * \\par Usage Considerations\n     * - BLOCK_THREADS must be a multiple of WARP_THREADS\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items written per thread.\n     * - The local reordering incurs slightly longer latencies and throughput than the\n     *   direct cub::BLOCK_STORE_DIRECT and cub::BLOCK_STORE_VECTORIZE alternatives.\n     */\n    BLOCK_STORE_WARP_TRANSPOSE,\n\n    /**\n     * \\par Overview\n     * A [<em>blocked arrangement</em>](index.html#sec5sec3) is locally\n     * transposed and then efficiently written to memory as a\n     * [<em>warp-striped arrangement</em>](index.html#sec5sec3)\n     * To reduce the shared memory requirement, only one warp's worth of shared\n     * memory is provisioned and is subsequently time-sliced among warps.\n     *\n     * \\par Usage Considerations\n     * - BLOCK_THREADS must be a multiple of WARP_THREADS\n     *\n     * \\par Performance Considerations\n     * - The utilization of memory transactions (coalescing) remains high regardless\n     *   of items written per thread.\n     * - Provisions less shared memory temporary storage, but incurs larger\n     *   latencies than the BLOCK_STORE_WARP_TRANSPOSE alternative.\n     */\n    BLOCK_STORE_WARP_TRANSPOSE_TIMESLICED,\n\n};\n\n\n/**\n * \\brief The BlockStore class provides [<em>collective</em>](index.html#sec0) data movement methods for writing a [<em>blocked arrangement</em>](index.html#sec5sec3) of items partitioned across a CUDA thread block to a linear segment of memory.  ![](block_store_logo.png)\n * \\ingroup BlockModule\n * \\ingroup UtilIo\n *\n * \\tparam T                    The type of data to be written.\n * \\tparam BLOCK_DIM_X          The thread block length in threads along the X dimension\n * \\tparam ITEMS_PER_THREAD     The number of consecutive items partitioned onto each thread.\n * \\tparam ALGORITHM            <b>[optional]</b> cub::BlockStoreAlgorithm tuning policy enumeration.  default: cub::BLOCK_STORE_DIRECT.\n * \\tparam WARP_TIME_SLICING    <b>[optional]</b> Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage). (default: false)\n * \\tparam BLOCK_DIM_Y          <b>[optional]</b> The thread block length in threads along the Y dimension (default: 1)\n * \\tparam BLOCK_DIM_Z          <b>[optional]</b> The thread block length in threads along the Z dimension (default: 1)\n * \\tparam PTX_ARCH             <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - The BlockStore class provides a single data movement abstraction that can be specialized\n *   to implement different cub::BlockStoreAlgorithm strategies.  This facilitates different\n *   performance policies for different architectures, data types, granularity sizes, etc.\n * - BlockStore can be optionally specialized by different data movement strategies:\n *   -# <b>cub::BLOCK_STORE_DIRECT</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3) of data is written\n *      directly to memory. [More...](\\ref cub::BlockStoreAlgorithm)\n *   -# <b>cub::BLOCK_STORE_VECTORIZE</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3)\n *      of data is written directly to memory using CUDA's built-in vectorized stores as a\n *      coalescing optimization.  [More...](\\ref cub::BlockStoreAlgorithm)\n *   -# <b>cub::BLOCK_STORE_TRANSPOSE</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3)\n *      is locally transposed into a [<em>striped arrangement</em>](index.html#sec5sec3) which is\n *      then written to memory.  [More...](\\ref cub::BlockStoreAlgorithm)\n *   -# <b>cub::BLOCK_STORE_WARP_TRANSPOSE</b>.  A [<em>blocked arrangement</em>](index.html#sec5sec3)\n *      is locally transposed into a [<em>warp-striped arrangement</em>](index.html#sec5sec3) which is\n *      then written to memory.  [More...](\\ref cub::BlockStoreAlgorithm)\n * - \\rowmajor\n *\n * \\par A Simple Example\n * \\blockcollective{BlockStore}\n * \\par\n * The code snippet below illustrates the storing of a \"blocked\" arrangement\n * of 512 integers across 128 threads (where each thread owns 4 consecutive items)\n * into a linear segment of memory.  The store is specialized for \\p BLOCK_STORE_WARP_TRANSPOSE,\n * meaning items are locally reordered among threads so that memory references will be\n * efficiently coalesced using a warp-striped access pattern.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/block/block_store.cuh>\n *\n * __global__ void ExampleKernel(int *d_data, ...)\n * {\n *     // Specialize BlockStore for a 1D block of 128 threads owning 4 integer items each\n *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_WARP_TRANSPOSE> BlockStore;\n *\n *     // Allocate shared memory for BlockStore\n *     __shared__ typename BlockStore::TempStorage temp_storage;\n *\n *     // Obtain a segment of consecutive items that are blocked across threads\n *     int thread_data[4];\n *     ...\n *\n *     // Store items to linear memory\n *     int thread_data[4];\n *     BlockStore(temp_storage).Store(d_data, thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of \\p thread_data across the block of threads is\n * <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n * The output \\p d_data will be <tt>0, 1, 2, 3, 4, 5, ...</tt>.\n *\n */\ntemplate <\n    typename                T,\n    int                     BLOCK_DIM_X,\n    int                     ITEMS_PER_THREAD,\n    BlockStoreAlgorithm     ALGORITHM           = BLOCK_STORE_DIRECT,\n    int                     BLOCK_DIM_Y         = 1,\n    int                     BLOCK_DIM_Z         = 1,\n    int                     PTX_ARCH            = CUB_PTX_ARCH>\nclass BlockStore\n{\nprivate:\n    /******************************************************************************\n     * Constants and typed definitions\n     ******************************************************************************/\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n\n    /******************************************************************************\n     * Algorithmic variants\n     ******************************************************************************/\n\n    /// Store helper\n    template <BlockStoreAlgorithm _POLICY, int DUMMY>\n    struct StoreInternal;\n\n\n    /**\n     * BLOCK_STORE_DIRECT specialization of store helper\n     */\n    template <int DUMMY>\n    struct StoreInternal<BLOCK_STORE_DIRECT, DUMMY>\n    {\n        /// Shared memory storage layout type\n        typedef NullType TempStorage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ StoreInternal(\n            TempStorage &/*temp_storage*/,\n            int linear_tid)\n        :\n            linear_tid(linear_tid)\n        {}\n\n        /// Store items into a linear segment of memory\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n        {\n            StoreDirectBlocked(linear_tid, block_itr, items);\n        }\n\n        /// Store items into a linear segment of memory, guarded by range\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n            int                 valid_items)                ///< [in] Number of valid items to write\n        {\n            StoreDirectBlocked(linear_tid, block_itr, items, valid_items);\n        }\n    };\n\n\n    /**\n     * BLOCK_STORE_VECTORIZE specialization of store helper\n     */\n    template <int DUMMY>\n    struct StoreInternal<BLOCK_STORE_VECTORIZE, DUMMY>\n    {\n        /// Shared memory storage layout type\n        typedef NullType TempStorage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ StoreInternal(\n            TempStorage &/*temp_storage*/,\n            int linear_tid)\n        :\n            linear_tid(linear_tid)\n        {}\n\n        /// Store items into a linear segment of memory, specialized for native pointer types (attempts vectorization)\n        __device__ __forceinline__ void Store(\n            T                   *block_ptr,                 ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n        {\n            StoreDirectBlockedVectorized(linear_tid, block_ptr, items);\n        }\n\n        /// Store items into a linear segment of memory, specialized for opaque input iterators (skips vectorization)\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT    block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n        {\n            StoreDirectBlocked(linear_tid, block_itr, items);\n        }\n\n        /// Store items into a linear segment of memory, guarded by range\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n            int                 valid_items)                ///< [in] Number of valid items to write\n        {\n            StoreDirectBlocked(linear_tid, block_itr, items, valid_items);\n        }\n    };\n\n\n    /**\n     * BLOCK_STORE_TRANSPOSE specialization of store helper\n     */\n    template <int DUMMY>\n    struct StoreInternal<BLOCK_STORE_TRANSPOSE, DUMMY>\n    {\n        // BlockExchange utility type for keys\n        typedef BlockExchange<T, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ StoreInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Store items into a linear segment of memory\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n        {\n            BlockExchange(temp_storage).BlockedToStriped(items);\n            StoreDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items);\n        }\n\n        /// Store items into a linear segment of memory, guarded by range\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT   block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n            int                 valid_items)                ///< [in] Number of valid items to write\n        {\n            BlockExchange(temp_storage).BlockedToStriped(items);\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            StoreDirectStriped<BLOCK_THREADS>(linear_tid, block_itr, items, temp_storage.valid_items);\n        }\n    };\n\n\n    /**\n     * BLOCK_STORE_WARP_TRANSPOSE specialization of store helper\n     */\n    template <int DUMMY>\n    struct StoreInternal<BLOCK_STORE_WARP_TRANSPOSE, DUMMY>\n    {\n        enum\n        {\n            WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH)\n        };\n\n        // Assert BLOCK_THREADS must be a multiple of WARP_THREADS\n        CUB_STATIC_ASSERT((BLOCK_THREADS % WARP_THREADS == 0), \"BLOCK_THREADS must be a multiple of WARP_THREADS\");\n\n        // BlockExchange utility type for keys\n        typedef BlockExchange<T, BLOCK_DIM_X, ITEMS_PER_THREAD, false, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ StoreInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Store items into a linear segment of memory\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT   block_itr,                    ///< [in] The thread block's base output iterator for storing to\n            T                 (&items)[ITEMS_PER_THREAD])   ///< [in] Data to store\n        {\n            BlockExchange(temp_storage).BlockedToWarpStriped(items);\n            StoreDirectWarpStriped(linear_tid, block_itr, items);\n        }\n\n        /// Store items into a linear segment of memory, guarded by range\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT   block_itr,                    ///< [in] The thread block's base output iterator for storing to\n            T                 (&items)[ITEMS_PER_THREAD],   ///< [in] Data to store\n            int               valid_items)                  ///< [in] Number of valid items to write\n        {\n            BlockExchange(temp_storage).BlockedToWarpStriped(items);\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            StoreDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items);\n        }\n    };\n\n\n    /**\n     * BLOCK_STORE_WARP_TRANSPOSE_TIMESLICED specialization of store helper\n     */\n    template <int DUMMY>\n    struct StoreInternal<BLOCK_STORE_WARP_TRANSPOSE_TIMESLICED, DUMMY>\n    {\n        enum\n        {\n            WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH)\n        };\n\n        // Assert BLOCK_THREADS must be a multiple of WARP_THREADS\n        CUB_STATIC_ASSERT((BLOCK_THREADS % WARP_THREADS == 0), \"BLOCK_THREADS must be a multiple of WARP_THREADS\");\n\n        // BlockExchange utility type for keys\n        typedef BlockExchange<T, BLOCK_DIM_X, ITEMS_PER_THREAD, true, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> BlockExchange;\n\n        /// Shared memory storage layout type\n        struct _TempStorage : BlockExchange::TempStorage\n        {\n            /// Temporary storage for partially-full block guard\n            volatile int valid_items;\n        };\n\n        /// Alias wrapper allowing storage to be unioned\n        struct TempStorage : Uninitialized<_TempStorage> {};\n\n        /// Thread reference to shared storage\n        _TempStorage &temp_storage;\n\n        /// Linear thread-id\n        int linear_tid;\n\n        /// Constructor\n        __device__ __forceinline__ StoreInternal(\n            TempStorage &temp_storage,\n            int linear_tid)\n        :\n            temp_storage(temp_storage.Alias()),\n            linear_tid(linear_tid)\n        {}\n\n        /// Store items into a linear segment of memory\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n        {\n            BlockExchange(temp_storage).BlockedToWarpStriped(items);\n            StoreDirectWarpStriped(linear_tid, block_itr, items);\n        }\n\n        /// Store items into a linear segment of memory, guarded by range\n        template <typename OutputIteratorT>\n        __device__ __forceinline__ void Store(\n            OutputIteratorT   block_itr,                  ///< [in] The thread block's base output iterator for storing to\n            T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n            int                 valid_items)                ///< [in] Number of valid items to write\n        {\n            BlockExchange(temp_storage).BlockedToWarpStriped(items);\n            if (linear_tid == 0)\n                temp_storage.valid_items = valid_items;     // Move through volatile smem as a workaround to prevent RF spilling on subsequent loads\n            CTA_SYNC();\n            StoreDirectWarpStriped(linear_tid, block_itr, items, temp_storage.valid_items);\n        }\n    };\n\n    /******************************************************************************\n     * Type definitions\n     ******************************************************************************/\n\n    /// Internal load implementation to use\n    typedef StoreInternal<ALGORITHM, 0> InternalStore;\n\n\n    /// Shared memory storage layout type\n    typedef typename InternalStore::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Internal storage allocator\n    __device__ __forceinline__ _TempStorage& PrivateStorage()\n    {\n        __shared__ _TempStorage private_storage;\n        return private_storage;\n    }\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Thread reference to shared storage\n    _TempStorage &temp_storage;\n\n    /// Linear thread-id\n    int linear_tid;\n\npublic:\n\n\n    /// \\smemstorage{BlockStore}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using a private static allocation of shared memory as temporary storage.\n     */\n    __device__ __forceinline__ BlockStore()\n    :\n        temp_storage(PrivateStorage()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.\n     */\n    __device__ __forceinline__ BlockStore(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Data movement\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Store items into a linear segment of memory.\n     *\n     * \\par\n     * - \\blocked\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the storing of a \"blocked\" arrangement\n     * of 512 integers across 128 threads (where each thread owns 4 consecutive items)\n     * into a linear segment of memory.  The store is specialized for \\p BLOCK_STORE_WARP_TRANSPOSE,\n     * meaning items are locally reordered among threads so that memory references will be\n     * efficiently coalesced using a warp-striped access pattern.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_store.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, ...)\n     * {\n     *     // Specialize BlockStore for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_WARP_TRANSPOSE> BlockStore;\n     *\n     *     // Allocate shared memory for BlockStore\n     *     __shared__ typename BlockStore::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Store items to linear memory\n     *     int thread_data[4];\n     *     BlockStore(temp_storage).Store(d_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of \\p thread_data across the block of threads is\n     * <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt>.\n     * The output \\p d_data will be <tt>0, 1, 2, 3, 4, 5, ...</tt>.\n     *\n     */\n    template <typename OutputIteratorT>\n    __device__ __forceinline__ void Store(\n        OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n        T                   (&items)[ITEMS_PER_THREAD]) ///< [in] Data to store\n    {\n        InternalStore(temp_storage, linear_tid).Store(block_itr, items);\n    }\n\n    /**\n     * \\brief Store items into a linear segment of memory, guarded by range.\n     *\n     * \\par\n     * - \\blocked\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the guarded storing of a \"blocked\" arrangement\n     * of 512 integers across 128 threads (where each thread owns 4 consecutive items)\n     * into a linear segment of memory.  The store is specialized for \\p BLOCK_STORE_WARP_TRANSPOSE,\n     * meaning items are locally reordered among threads so that memory references will be\n     * efficiently coalesced using a warp-striped access pattern.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/block/block_store.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, int valid_items, ...)\n     * {\n     *     // Specialize BlockStore for a 1D block of 128 threads owning 4 integer items each\n     *     typedef cub::BlockStore<int, 128, 4, BLOCK_STORE_WARP_TRANSPOSE> BlockStore;\n     *\n     *     // Allocate shared memory for BlockStore\n     *     __shared__ typename BlockStore::TempStorage temp_storage;\n     *\n     *     // Obtain a segment of consecutive items that are blocked across threads\n     *     int thread_data[4];\n     *     ...\n     *\n     *     // Store items to linear memory\n     *     int thread_data[4];\n     *     BlockStore(temp_storage).Store(d_data, thread_data, valid_items);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of \\p thread_data across the block of threads is\n     * <tt>{ [0,1,2,3], [4,5,6,7], ..., [508,509,510,511] }</tt> and \\p valid_items is \\p 5.\n     * The output \\p d_data will be <tt>0, 1, 2, 3, 4, ?, ?, ?, ...</tt>, with\n     * only the first two threads being unmasked to store portions of valid data.\n     *\n     */\n    template <typename OutputIteratorT>\n    __device__ __forceinline__ void Store(\n        OutputIteratorT     block_itr,                  ///< [in] The thread block's base output iterator for storing to\n        T                   (&items)[ITEMS_PER_THREAD], ///< [in] Data to store\n        int                 valid_items)                ///< [in] Number of valid items to write\n    {\n        InternalStore(temp_storage, linear_tid).Store(block_itr, items, valid_items);\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_histogram_atomic.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockHistogramAtomic class provides atomic-based methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief The BlockHistogramAtomic class provides atomic-based methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block.\n */\ntemplate <int BINS>\nstruct BlockHistogramAtomic\n{\n    /// Shared memory storage layout type\n    struct TempStorage {};\n\n\n    /// Constructor\n    __device__ __forceinline__ BlockHistogramAtomic(\n        TempStorage &temp_storage)\n    {}\n\n\n    /// Composite data onto an existing histogram\n    template <\n        typename            T,\n        typename            CounterT,     \n        int                 ITEMS_PER_THREAD>\n    __device__ __forceinline__ void Composite(\n        T                   (&items)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input values to histogram\n        CounterT             histogram[BINS])                 ///< [out] Reference to shared/device-accessible memory histogram\n    {\n        // Update histogram\n        #pragma unroll\n        for (int i = 0; i < ITEMS_PER_THREAD; ++i)\n        {\n              atomicAdd(histogram + items[i], 1);\n        }\n    }\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_histogram_sort.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::BlockHistogramSort class provides sorting-based methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../block/block_radix_sort.cuh\"\n#include \"../../block/block_discontinuity.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n\n/**\n * \\brief The BlockHistogramSort class provides sorting-based methods for constructing block-wide histograms from data samples partitioned across a CUDA thread block.\n */\ntemplate <\n    typename    T,                  ///< Sample type\n    int         BLOCK_DIM_X,        ///< The thread block length in threads along the X dimension\n    int         ITEMS_PER_THREAD,   ///< The number of samples per thread\n    int         BINS,               ///< The number of bins into which histogram samples may fall\n    int         BLOCK_DIM_Y,        ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,        ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>           ///< The PTX compute capability for which to to specialize this collective\nstruct BlockHistogramSort\n{\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    // Parameterize BlockRadixSort type for our thread block\n    typedef BlockRadixSort<\n            T,\n            BLOCK_DIM_X,\n            ITEMS_PER_THREAD,\n            NullType,\n            4,\n            (PTX_ARCH >= 350) ? true : false,\n            BLOCK_SCAN_WARP_SCANS,\n            cudaSharedMemBankSizeFourByte,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        BlockRadixSortT;\n\n    // Parameterize BlockDiscontinuity type for our thread block\n    typedef BlockDiscontinuity<\n            T,\n            BLOCK_DIM_X,\n            BLOCK_DIM_Y,\n            BLOCK_DIM_Z,\n            PTX_ARCH>\n        BlockDiscontinuityT;\n\n    /// Shared memory\n    union _TempStorage\n    {\n        // Storage for sorting bin values\n        typename BlockRadixSortT::TempStorage sort;\n\n        struct\n        {\n            // Storage for detecting discontinuities in the tile of sorted bin values\n            typename BlockDiscontinuityT::TempStorage flag;\n\n            // Storage for noting begin/end offsets of bin runs in the tile of sorted bin values\n            unsigned int run_begin[BINS];\n            unsigned int run_end[BINS];\n        };\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    // Thread fields\n    _TempStorage &temp_storage;\n    unsigned int linear_tid;\n\n\n    /// Constructor\n    __device__ __forceinline__ BlockHistogramSort(\n        TempStorage     &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    // Discontinuity functor\n    struct DiscontinuityOp\n    {\n        // Reference to temp_storage\n        _TempStorage &temp_storage;\n\n        // Constructor\n        __device__ __forceinline__ DiscontinuityOp(_TempStorage &temp_storage) :\n            temp_storage(temp_storage)\n        {}\n\n        // Discontinuity predicate\n        __device__ __forceinline__ bool operator()(const T &a, const T &b, int b_index)\n        {\n            if (a != b)\n            {\n                // Note the begin/end offsets in shared storage\n                temp_storage.run_begin[b] = b_index;\n                temp_storage.run_end[a] = b_index;\n\n                return true;\n            }\n            else\n            {\n                return false;\n            }\n        }\n    };\n\n\n    // Composite data onto an existing histogram\n    template <\n        typename            CounterT     >\n    __device__ __forceinline__ void Composite(\n        T                   (&items)[ITEMS_PER_THREAD],     ///< [in] Calling thread's input values to histogram\n        CounterT            histogram[BINS])                 ///< [out] Reference to shared/device-accessible memory histogram\n    {\n        enum { TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD };\n\n        // Sort bytes in blocked arrangement\n        BlockRadixSortT(temp_storage.sort).Sort(items);\n\n        CTA_SYNC();\n\n        // Initialize the shared memory's run_begin and run_end for each bin\n        int histo_offset = 0;\n\n        #pragma unroll\n        for(; histo_offset + BLOCK_THREADS <= BINS; histo_offset += BLOCK_THREADS)\n        {\n            temp_storage.run_begin[histo_offset + linear_tid] = TILE_SIZE;\n            temp_storage.run_end[histo_offset + linear_tid] = TILE_SIZE;\n        }\n        // Finish up with guarded initialization if necessary\n        if ((BINS % BLOCK_THREADS != 0) && (histo_offset + linear_tid < BINS))\n        {\n            temp_storage.run_begin[histo_offset + linear_tid] = TILE_SIZE;\n            temp_storage.run_end[histo_offset + linear_tid] = TILE_SIZE;\n        }\n\n        CTA_SYNC();\n\n        int flags[ITEMS_PER_THREAD];    // unused\n\n        // Compute head flags to demarcate contiguous runs of the same bin in the sorted tile\n        DiscontinuityOp flag_op(temp_storage);\n        BlockDiscontinuityT(temp_storage.flag).FlagHeads(flags, items, flag_op);\n\n        // Update begin for first item\n        if (linear_tid == 0) temp_storage.run_begin[items[0]] = 0;\n\n        CTA_SYNC();\n\n        // Composite into histogram\n        histo_offset = 0;\n\n        #pragma unroll\n        for(; histo_offset + BLOCK_THREADS <= BINS; histo_offset += BLOCK_THREADS)\n        {\n            int thread_offset = histo_offset + linear_tid;\n            CounterT      count = temp_storage.run_end[thread_offset] - temp_storage.run_begin[thread_offset];\n            histogram[thread_offset] += count;\n        }\n\n        // Finish up with guarded composition if necessary\n        if ((BINS % BLOCK_THREADS != 0) && (histo_offset + linear_tid < BINS))\n        {\n            int thread_offset = histo_offset + linear_tid;\n            CounterT      count = temp_storage.run_end[thread_offset] - temp_storage.run_begin[thread_offset];\n            histogram[thread_offset] += count;\n        }\n    }\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_reduce_raking.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockReduceRaking provides raking-based methods of parallel reduction across a CUDA thread block.  Supports non-commutative reduction operators.\n */\n\n#pragma once\n\n#include \"../../block/block_raking_layout.cuh\"\n#include \"../../warp/warp_reduce.cuh\"\n#include \"../../thread/thread_reduce.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief BlockReduceRaking provides raking-based methods of parallel reduction across a CUDA thread block.  Supports non-commutative reduction operators.\n *\n * Supports non-commutative binary reduction operators.  Unlike commutative\n * reduction operators (e.g., addition), the application of a non-commutative\n * reduction operator (e.g, string concatenation) across a sequence of inputs must\n * honor the relative ordering of items and partial reductions when applying the\n * reduction operator.\n *\n * Compared to the implementation of BlockReduceRaking (which does not support\n * non-commutative operators), this implementation requires a few extra\n * rounds of inter-thread communication.\n */\ntemplate <\n    typename    T,              ///< Data type being reduced\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockReduceRaking\n{\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    /// Layout type for padded thread block raking grid\n    typedef BlockRakingLayout<T, BLOCK_THREADS, PTX_ARCH> BlockRakingLayout;\n\n    ///  WarpReduce utility type\n    typedef typename WarpReduce<T, BlockRakingLayout::RAKING_THREADS, PTX_ARCH>::InternalWarpReduce WarpReduce;\n\n    /// Constants\n    enum\n    {\n        /// Number of raking threads\n        RAKING_THREADS = BlockRakingLayout::RAKING_THREADS,\n\n        /// Number of raking elements per warp synchronous raking thread\n        SEGMENT_LENGTH = BlockRakingLayout::SEGMENT_LENGTH,\n\n        /// Cooperative work can be entirely warp synchronous\n        WARP_SYNCHRONOUS = (RAKING_THREADS == BLOCK_THREADS),\n\n        /// Whether or not warp-synchronous reduction should be unguarded (i.e., the warp-reduction elements is a power of two\n        WARP_SYNCHRONOUS_UNGUARDED = PowerOfTwo<RAKING_THREADS>::VALUE,\n\n        /// Whether or not accesses into smem are unguarded\n        RAKING_UNGUARDED = BlockRakingLayout::UNGUARDED,\n\n    };\n\n\n    /// Shared memory storage layout type\n    union _TempStorage\n    {\n        typename WarpReduce::TempStorage            warp_storage;        ///< Storage for warp-synchronous reduction\n        typename BlockRakingLayout::TempStorage     raking_grid;         ///< Padded thread block raking grid\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    // Thread fields\n    _TempStorage &temp_storage;\n    unsigned int linear_tid;\n\n\n    /// Constructor\n    __device__ __forceinline__ BlockReduceRaking(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    template <bool IS_FULL_TILE, typename ReductionOp, int ITERATION>\n    __device__ __forceinline__ T RakingReduction(\n        ReductionOp                 reduction_op,       ///< [in] Binary scan operator\n        T                           *raking_segment,\n        T                           partial,            ///< [in] <b>[<em>lane</em><sub>0</sub> only]</b> Warp-wide aggregate reduction of input items\n        int                         num_valid,          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        Int2Type<ITERATION>         /*iteration*/)\n    {\n        // Update partial if addend is in range\n        if ((IS_FULL_TILE && RAKING_UNGUARDED) || ((linear_tid * SEGMENT_LENGTH) + ITERATION < num_valid))\n        {\n            T addend = raking_segment[ITERATION];\n            partial = reduction_op(partial, addend);\n        }\n        return RakingReduction<IS_FULL_TILE>(reduction_op, raking_segment, partial, num_valid, Int2Type<ITERATION + 1>());\n    }\n\n    template <bool IS_FULL_TILE, typename ReductionOp>\n    __device__ __forceinline__ T RakingReduction(\n        ReductionOp                 /*reduction_op*/,   ///< [in] Binary scan operator\n        T                           * /*raking_segment*/,\n        T                           partial,            ///< [in] <b>[<em>lane</em><sub>0</sub> only]</b> Warp-wide aggregate reduction of input items\n        int                         /*num_valid*/,      ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        Int2Type<SEGMENT_LENGTH>    /*iteration*/)\n    {\n        return partial;\n    }\n\n\n\n    /// Computes a thread block-wide reduction using the specified reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <\n        bool                IS_FULL_TILE,\n        typename            ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   partial,            ///< [in] Calling thread's input partial reductions\n        int                 num_valid,          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        ReductionOp         reduction_op)       ///< [in] Binary reduction operator\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp synchronous reduction (unguarded if active threads is a power-of-two)\n            partial = WarpReduce(temp_storage.warp_storage).template Reduce<IS_FULL_TILE, SEGMENT_LENGTH>(\n                partial,\n                num_valid,\n                reduction_op);\n        }\n        else\n        {\n            // Place partial into shared memory grid.\n            *BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid) = partial;\n\n            CTA_SYNC();\n\n            // Reduce parallelism to one warp\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking reduction in grid\n                T *raking_segment = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n                partial = raking_segment[0];\n\n                partial = RakingReduction<IS_FULL_TILE>(reduction_op, raking_segment, partial, num_valid, Int2Type<1>());\n\n                partial = WarpReduce(temp_storage.warp_storage).template Reduce<IS_FULL_TILE && RAKING_UNGUARDED, SEGMENT_LENGTH>(\n                    partial,\n                    num_valid,\n                    reduction_op);\n\n            }\n        }\n\n        return partial;\n    }\n\n\n    /// Computes a thread block-wide reduction using addition (+) as the reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <bool IS_FULL_TILE>\n    __device__ __forceinline__ T Sum(\n        T                   partial,            ///< [in] Calling thread's input partial reductions\n        int                 num_valid)          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n    {\n        cub::Sum reduction_op;\n\n        return Reduce<IS_FULL_TILE>(partial, num_valid, reduction_op);\n    }\n\n\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_reduce_raking_commutative_only.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockReduceRakingCommutativeOnly provides raking-based methods of parallel reduction across a CUDA thread block.  Does not support non-commutative reduction operators.\n */\n\n#pragma once\n\n#include \"block_reduce_raking.cuh\"\n#include \"../../warp/warp_reduce.cuh\"\n#include \"../../thread/thread_reduce.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief BlockReduceRakingCommutativeOnly provides raking-based methods of parallel reduction across a CUDA thread block.  Does not support non-commutative reduction operators.  Does not support block sizes that are not a multiple of the warp size.\n */\ntemplate <\n    typename    T,              ///< Data type being reduced\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockReduceRakingCommutativeOnly\n{\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    // The fall-back implementation to use when BLOCK_THREADS is not a multiple of the warp size or not all threads have valid values\n    typedef BlockReduceRaking<T, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, PTX_ARCH> FallBack;\n\n    /// Constants\n    enum\n    {\n        /// Number of warp threads\n        WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH),\n\n        /// Whether or not to use fall-back\n        USE_FALLBACK = ((BLOCK_THREADS % WARP_THREADS != 0) || (BLOCK_THREADS <= WARP_THREADS)),\n\n        /// Number of raking threads\n        RAKING_THREADS = WARP_THREADS,\n\n        /// Number of threads actually sharing items with the raking threads\n        SHARING_THREADS = CUB_MAX(1, BLOCK_THREADS - RAKING_THREADS),\n\n        /// Number of raking elements per warp synchronous raking thread\n        SEGMENT_LENGTH = SHARING_THREADS / WARP_THREADS,\n    };\n\n    ///  WarpReduce utility type\n    typedef WarpReduce<T, RAKING_THREADS, PTX_ARCH> WarpReduce;\n\n    /// Layout type for padded thread block raking grid\n    typedef BlockRakingLayout<T, SHARING_THREADS, PTX_ARCH> BlockRakingLayout;\n\n    /// Shared memory storage layout type\n    union _TempStorage\n    {\n        struct\n        {\n            typename WarpReduce::TempStorage        warp_storage;        ///< Storage for warp-synchronous reduction\n            typename BlockRakingLayout::TempStorage raking_grid;         ///< Padded thread block raking grid\n        };\n        typename FallBack::TempStorage              fallback_storage;    ///< Fall-back storage for non-commutative block scan\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    // Thread fields\n    _TempStorage &temp_storage;\n    unsigned int linear_tid;\n\n\n    /// Constructor\n    __device__ __forceinline__ BlockReduceRakingCommutativeOnly(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    /// Computes a thread block-wide reduction using addition (+) as the reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <bool FULL_TILE>\n    __device__ __forceinline__ T Sum(\n        T                   partial,            ///< [in] Calling thread's input partial reductions\n        int                 num_valid)          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n    {\n        if (USE_FALLBACK || !FULL_TILE)\n        {\n            return FallBack(temp_storage.fallback_storage).template Sum<FULL_TILE>(partial, num_valid);\n        }\n        else\n        {\n            // Place partial into shared memory grid\n            if (linear_tid >= RAKING_THREADS)\n                *BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid - RAKING_THREADS) = partial;\n\n            CTA_SYNC();\n\n            // Reduce parallelism to one warp\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking reduction in grid\n                T *raking_segment = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n                partial = internal::ThreadReduce<SEGMENT_LENGTH>(raking_segment, cub::Sum(), partial);\n\n                // Warpscan\n                partial = WarpReduce(temp_storage.warp_storage).Sum(partial);\n            }\n        }\n\n        return partial;\n    }\n\n\n    /// Computes a thread block-wide reduction using the specified reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <\n        bool                FULL_TILE,\n        typename            ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   partial,            ///< [in] Calling thread's input partial reductions\n        int                 num_valid,          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        ReductionOp         reduction_op)       ///< [in] Binary reduction operator\n    {\n        if (USE_FALLBACK || !FULL_TILE)\n        {\n            return FallBack(temp_storage.fallback_storage).template Reduce<FULL_TILE>(partial, num_valid, reduction_op);\n        }\n        else\n        {\n            // Place partial into shared memory grid\n            if (linear_tid >= RAKING_THREADS)\n                *BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid - RAKING_THREADS) = partial;\n\n            CTA_SYNC();\n\n            // Reduce parallelism to one warp\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking reduction in grid\n                T *raking_segment = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n                partial = internal::ThreadReduce<SEGMENT_LENGTH>(raking_segment, reduction_op, partial);\n\n                // Warpscan\n                partial = WarpReduce(temp_storage.warp_storage).Reduce(partial, reduction_op);\n            }\n        }\n\n        return partial;\n    }\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_reduce_warp_reductions.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockReduceWarpReductions provides variants of warp-reduction-based parallel reduction across a CUDA thread block.  Supports non-commutative reduction operators.\n */\n\n#pragma once\n\n#include \"../../warp/warp_reduce.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_arch.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief BlockReduceWarpReductions provides variants of warp-reduction-based parallel reduction across a CUDA thread block.  Supports non-commutative reduction operators.\n */\ntemplate <\n    typename    T,              ///< Data type being reduced\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockReduceWarpReductions\n{\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        /// Number of warp threads\n        WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH),\n\n        /// Number of active warps\n        WARPS = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n\n        /// The logical warp size for warp reductions\n        LOGICAL_WARP_SIZE = CUB_MIN(BLOCK_THREADS, WARP_THREADS),\n\n        /// Whether or not the logical warp size evenly divides the thread block size\n        EVEN_WARP_MULTIPLE = (BLOCK_THREADS % LOGICAL_WARP_SIZE == 0)\n    };\n\n\n    ///  WarpReduce utility type\n    typedef typename WarpReduce<T, LOGICAL_WARP_SIZE, PTX_ARCH>::InternalWarpReduce WarpReduce;\n\n\n    /// Shared memory storage layout type\n    struct _TempStorage\n    {\n        typename WarpReduce::TempStorage    warp_reduce[WARPS];                ///< Buffer for warp-synchronous scan\n        T                                   warp_aggregates[WARPS];     ///< Shared totals from each warp-synchronous scan\n        T                                   block_prefix;               ///< Shared prefix for the entire thread block\n    };\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    // Thread fields\n    _TempStorage &temp_storage;\n    unsigned int linear_tid;\n    unsigned int warp_id;\n    unsigned int lane_id;\n\n\n    /// Constructor\n    __device__ __forceinline__ BlockReduceWarpReductions(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        warp_id((WARPS == 1) ? 0 : linear_tid / WARP_THREADS),\n        lane_id(LaneId())\n    {}\n\n\n    template <bool FULL_TILE, typename ReductionOp, int SUCCESSOR_WARP>\n    __device__ __forceinline__ T ApplyWarpAggregates(\n        ReductionOp                 reduction_op,       ///< [in] Binary scan operator\n        T                           warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>0</sub> only]</b> Warp-wide aggregate reduction of input items\n        int                         num_valid,          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        Int2Type<SUCCESSOR_WARP>    /*successor_warp*/)\n    {\n        if (FULL_TILE || (SUCCESSOR_WARP * LOGICAL_WARP_SIZE < num_valid))\n        {\n            T addend = temp_storage.warp_aggregates[SUCCESSOR_WARP];\n            warp_aggregate = reduction_op(warp_aggregate, addend);\n        }\n        return ApplyWarpAggregates<FULL_TILE>(reduction_op, warp_aggregate, num_valid, Int2Type<SUCCESSOR_WARP + 1>());\n    }\n\n    template <bool FULL_TILE, typename ReductionOp>\n    __device__ __forceinline__ T ApplyWarpAggregates(\n        ReductionOp         /*reduction_op*/,   ///< [in] Binary scan operator\n        T                   warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>0</sub> only]</b> Warp-wide aggregate reduction of input items\n        int                 /*num_valid*/,      ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        Int2Type<WARPS>     /*successor_warp*/)\n    {\n        return warp_aggregate;\n    }\n\n\n    /// Returns block-wide aggregate in <em>thread</em><sub>0</sub>.\n    template <\n        bool                FULL_TILE,\n        typename            ReductionOp>\n    __device__ __forceinline__ T ApplyWarpAggregates(\n        ReductionOp         reduction_op,       ///< [in] Binary scan operator\n        T                   warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>0</sub> only]</b> Warp-wide aggregate reduction of input items\n        int                 num_valid)          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n    {\n        // Share lane aggregates\n        if (lane_id == 0)\n        {\n            temp_storage.warp_aggregates[warp_id] = warp_aggregate;\n        }\n\n        CTA_SYNC();\n\n        // Update total aggregate in warp 0, lane 0\n        if (linear_tid == 0)\n        {\n            warp_aggregate = ApplyWarpAggregates<FULL_TILE>(reduction_op, warp_aggregate, num_valid, Int2Type<1>());\n        }\n\n        return warp_aggregate;\n    }\n\n\n    /// Computes a thread block-wide reduction using addition (+) as the reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <bool FULL_TILE>\n    __device__ __forceinline__ T Sum(\n        T                   input,          ///< [in] Calling thread's input partial reductions\n        int                 num_valid)      ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n    {\n        cub::Sum        reduction_op;\n        unsigned int    warp_offset = warp_id * LOGICAL_WARP_SIZE;\n        unsigned int    warp_num_valid = (FULL_TILE && EVEN_WARP_MULTIPLE) ?\n                            LOGICAL_WARP_SIZE :\n                            (warp_offset < num_valid) ?\n                                num_valid - warp_offset :\n                                0;\n\n        // Warp reduction in every warp\n        T warp_aggregate = WarpReduce(temp_storage.warp_reduce[warp_id]).template Reduce<(FULL_TILE && EVEN_WARP_MULTIPLE), 1>(\n            input,\n            warp_num_valid,\n            cub::Sum());\n\n        // Update outputs and block_aggregate with warp-wide aggregates from lane-0s\n        return ApplyWarpAggregates<FULL_TILE>(reduction_op, warp_aggregate, num_valid);\n    }\n\n\n    /// Computes a thread block-wide reduction using the specified reduction operator. The first num_valid threads each contribute one reduction partial.  The return value is only valid for thread<sub>0</sub>.\n    template <\n        bool                FULL_TILE,\n        typename            ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   input,              ///< [in] Calling thread's input partial reductions\n        int                 num_valid,          ///< [in] Number of valid elements (may be less than BLOCK_THREADS)\n        ReductionOp         reduction_op)       ///< [in] Binary reduction operator\n    {\n        unsigned int    warp_offset = warp_id * LOGICAL_WARP_SIZE;\n        unsigned int    warp_num_valid = (FULL_TILE && EVEN_WARP_MULTIPLE) ?\n                            LOGICAL_WARP_SIZE :\n                            (warp_offset < static_cast<unsigned int>(num_valid)) ?\n                                num_valid - warp_offset :\n                                0;\n\n        // Warp reduction in every warp\n        T warp_aggregate = WarpReduce(temp_storage.warp_reduce[warp_id]).template Reduce<(FULL_TILE && EVEN_WARP_MULTIPLE), 1>(\n            input,\n            warp_num_valid,\n            reduction_op);\n\n        // Update outputs and block_aggregate with warp-wide aggregates from lane-0s\n        return ApplyWarpAggregates<FULL_TILE>(reduction_op, warp_aggregate, num_valid);\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_scan_raking.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n\n/**\n * \\file\n * cub::BlockScanRaking provides variants of raking-based parallel prefix scan across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../util_ptx.cuh\"\n#include \"../../util_arch.cuh\"\n#include \"../../block/block_raking_layout.cuh\"\n#include \"../../thread/thread_reduce.cuh\"\n#include \"../../thread/thread_scan.cuh\"\n#include \"../../warp/warp_scan.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief BlockScanRaking provides variants of raking-based parallel prefix scan across a CUDA thread block.\n */\ntemplate <\n    typename    T,              ///< Data type being scanned\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    bool        MEMOIZE,        ///< Whether or not to buffer outer raking scan partials to incur fewer shared memory reads at the expense of higher register pressure\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockScanRaking\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n    };\n\n    /// Layout type for padded thread block raking grid\n    typedef BlockRakingLayout<T, BLOCK_THREADS, PTX_ARCH> BlockRakingLayout;\n\n    /// Constants\n    enum\n    {\n        /// Number of raking threads\n        RAKING_THREADS = BlockRakingLayout::RAKING_THREADS,\n\n        /// Number of raking elements per warp synchronous raking thread\n        SEGMENT_LENGTH = BlockRakingLayout::SEGMENT_LENGTH,\n\n        /// Cooperative work can be entirely warp synchronous\n        WARP_SYNCHRONOUS = (BLOCK_THREADS == RAKING_THREADS),\n    };\n\n    ///  WarpScan utility type\n    typedef WarpScan<T, RAKING_THREADS, PTX_ARCH> WarpScan;\n\n    /// Shared memory storage layout type\n    struct _TempStorage\n    {\n        typename WarpScan::TempStorage              warp_scan;          ///< Buffer for warp-synchronous scan\n        typename BlockRakingLayout::TempStorage     raking_grid;        ///< Padded thread block raking grid\n        T                                           block_aggregate;    ///< Block aggregate\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    // Thread fields\n    _TempStorage    &temp_storage;\n    unsigned int    linear_tid;\n    T               cached_segment[SEGMENT_LENGTH];\n\n\n    //---------------------------------------------------------------------\n    // Utility methods\n    //---------------------------------------------------------------------\n\n    /// Templated reduction\n    template <int ITERATION, typename ScanOp>\n    __device__ __forceinline__ T GuardedReduce(\n        T*                  raking_ptr,         ///< [in] Input array\n        ScanOp              scan_op,            ///< [in] Binary reduction operator\n        T                   raking_partial,     ///< [in] Prefix to seed reduction with\n        Int2Type<ITERATION> /*iteration*/)\n    {\n        if ((BlockRakingLayout::UNGUARDED) || (((linear_tid * SEGMENT_LENGTH) + ITERATION) < BLOCK_THREADS))\n        {\n            T addend = raking_ptr[ITERATION];\n            raking_partial = scan_op(raking_partial, addend);\n        }\n\n        return GuardedReduce(raking_ptr, scan_op, raking_partial, Int2Type<ITERATION + 1>());\n    }\n\n\n    /// Templated reduction (base case)\n    template <typename ScanOp>\n    __device__ __forceinline__ T GuardedReduce(\n        T*                          /*raking_ptr*/,    ///< [in] Input array\n        ScanOp                      /*scan_op*/,       ///< [in] Binary reduction operator\n        T                           raking_partial,    ///< [in] Prefix to seed reduction with\n        Int2Type<SEGMENT_LENGTH>    /*iteration*/)\n    {\n        return raking_partial;\n    }\n\n\n    /// Templated copy\n    template <int ITERATION>\n    __device__ __forceinline__ void CopySegment(\n        T*                  out,            ///< [out] Out array\n        T*                  in,             ///< [in] Input array\n        Int2Type<ITERATION> /*iteration*/)\n    {\n        out[ITERATION] = in[ITERATION];\n        CopySegment(out, in, Int2Type<ITERATION + 1>());\n    }\n\n \n    /// Templated copy (base case)\n    __device__ __forceinline__ void CopySegment(\n        T*                  /*out*/,            ///< [out] Out array\n        T*                  /*in*/,             ///< [in] Input array\n        Int2Type<SEGMENT_LENGTH> /*iteration*/)\n    {}\n\n\n    /// Performs upsweep raking reduction, returning the aggregate\n    template <typename ScanOp>\n    __device__ __forceinline__ T Upsweep(\n        ScanOp scan_op)\n    {\n        T *smem_raking_ptr = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n\n        // Read data into registers\n        CopySegment(cached_segment, smem_raking_ptr, Int2Type<0>());\n\n        T raking_partial = cached_segment[0];\n\n        return GuardedReduce(cached_segment, scan_op, raking_partial, Int2Type<1>());\n    }\n\n\n    /// Performs exclusive downsweep raking scan\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveDownsweep(\n        ScanOp          scan_op,\n        T               raking_partial,\n        bool            apply_prefix = true)\n    {\n        T *smem_raking_ptr = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n\n        // Read data back into registers\n        if (!MEMOIZE)\n        {\n            CopySegment(cached_segment, smem_raking_ptr, Int2Type<0>());\n        }\n\n        internal::ThreadScanExclusive(cached_segment, cached_segment, scan_op, raking_partial, apply_prefix);\n\n        // Write data back to smem\n        CopySegment(smem_raking_ptr, cached_segment, Int2Type<0>());\n    }\n\n\n    /// Performs inclusive downsweep raking scan\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveDownsweep(\n        ScanOp          scan_op,\n        T               raking_partial,\n        bool            apply_prefix = true)\n    {\n        T *smem_raking_ptr = BlockRakingLayout::RakingPtr(temp_storage.raking_grid, linear_tid);\n\n        // Read data back into registers\n        if (!MEMOIZE)\n        {\n            CopySegment(cached_segment, smem_raking_ptr, Int2Type<0>());\n        }\n\n        internal::ThreadScanInclusive(cached_segment, cached_segment, scan_op, raking_partial, apply_prefix);\n\n        // Write data back to smem\n        CopySegment(smem_raking_ptr, cached_segment, Int2Type<0>());\n    }\n\n\n    //---------------------------------------------------------------------\n    // Constructors\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanRaking(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z))\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Exclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &exclusive_output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).ExclusiveScan(input, exclusive_output, scan_op);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).ExclusiveScan(upsweep_partial, exclusive_partial, scan_op);\n\n                // Exclusive raking downsweep scan\n                ExclusiveDownsweep(scan_op, exclusive_partial, (linear_tid != 0));\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            exclusive_output = *placement_ptr;\n        }\n    }\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &output,            ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).ExclusiveScan(input, output, initial_value, scan_op);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Exclusive Warp-synchronous scan\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).ExclusiveScan(upsweep_partial, exclusive_partial, initial_value, scan_op);\n\n                // Exclusive raking downsweep scan\n                ExclusiveDownsweep(scan_op, exclusive_partial);\n            }\n\n            CTA_SYNC();\n\n            // Grab exclusive partial from shared memory\n            output = *placement_ptr;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan operator\n        T               &block_aggregate)               ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).ExclusiveScan(input, output, scan_op, block_aggregate);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial= Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T inclusive_partial;\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).Scan(upsweep_partial, inclusive_partial, exclusive_partial, scan_op);\n\n                // Exclusive raking downsweep scan\n                ExclusiveDownsweep(scan_op, exclusive_partial, (linear_tid != 0));\n\n                // Broadcast aggregate to all threads\n                if (linear_tid == RAKING_THREADS - 1)\n                    temp_storage.block_aggregate = inclusive_partial;\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            output = *placement_ptr;\n\n            // Retrieve block aggregate\n            block_aggregate = temp_storage.block_aggregate;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &output,            ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).ExclusiveScan(input, output, initial_value, scan_op, block_aggregate);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).ExclusiveScan(upsweep_partial, exclusive_partial, initial_value, scan_op, block_aggregate);\n\n                // Exclusive raking downsweep scan\n                ExclusiveDownsweep(scan_op, exclusive_partial);\n\n                // Broadcast aggregate to other threads\n                if (linear_tid == 0)\n                    temp_storage.block_aggregate = block_aggregate;\n            }\n\n            CTA_SYNC();\n\n            // Grab exclusive partial from shared memory\n            output = *placement_ptr;\n\n            // Retrieve block aggregate\n            block_aggregate = temp_storage.block_aggregate;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            T block_aggregate;\n            WarpScan warp_scan(temp_storage.warp_scan);\n            warp_scan.ExclusiveScan(input, output, scan_op, block_aggregate);\n\n            // Obtain warp-wide prefix in lane0, then broadcast to other lanes\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            block_prefix = warp_scan.Broadcast(block_prefix, 0);\n\n            output = scan_op(block_prefix, output);\n            if (linear_tid == 0)\n                output = block_prefix;\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                WarpScan warp_scan(temp_storage.warp_scan);\n\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T exclusive_partial, block_aggregate;\n                warp_scan.ExclusiveScan(upsweep_partial, exclusive_partial, scan_op, block_aggregate);\n\n                // Obtain block-wide prefix in lane0, then broadcast to other lanes\n                T block_prefix = block_prefix_callback_op(block_aggregate);\n                block_prefix = warp_scan.Broadcast(block_prefix, 0);\n\n                // Update prefix with warpscan exclusive partial\n                T downsweep_prefix = scan_op(block_prefix, exclusive_partial);\n                if (linear_tid == 0)\n                    downsweep_prefix = block_prefix;\n\n                // Exclusive raking downsweep scan\n                ExclusiveDownsweep(scan_op, downsweep_prefix);\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            output = *placement_ptr;\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).InclusiveScan(input, output, scan_op);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Exclusive Warp-synchronous scan\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).ExclusiveScan(upsweep_partial, exclusive_partial, scan_op);\n\n                // Inclusive raking downsweep scan\n                InclusiveDownsweep(scan_op, exclusive_partial, (linear_tid != 0));\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            output = *placement_ptr;\n        }\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan operator\n        T               &block_aggregate)               ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            WarpScan(temp_storage.warp_scan).InclusiveScan(input, output, scan_op, block_aggregate);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T inclusive_partial;\n                T exclusive_partial;\n                WarpScan(temp_storage.warp_scan).Scan(upsweep_partial, inclusive_partial, exclusive_partial, scan_op);\n\n                // Inclusive raking downsweep scan\n                InclusiveDownsweep(scan_op, exclusive_partial, (linear_tid != 0));\n\n                // Broadcast aggregate to all threads\n                if (linear_tid == RAKING_THREADS - 1)\n                    temp_storage.block_aggregate = inclusive_partial;\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            output = *placement_ptr;\n\n            // Retrieve block aggregate\n            block_aggregate = temp_storage.block_aggregate;\n        }\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &output,                        ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        if (WARP_SYNCHRONOUS)\n        {\n            // Short-circuit directly to warp-synchronous scan\n            T block_aggregate;\n            WarpScan warp_scan(temp_storage.warp_scan);\n            warp_scan.InclusiveScan(input, output, scan_op, block_aggregate);\n\n            // Obtain warp-wide prefix in lane0, then broadcast to other lanes\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            block_prefix = warp_scan.Broadcast(block_prefix, 0);\n\n            // Update prefix with exclusive warpscan partial\n            output = scan_op(block_prefix, output);\n        }\n        else\n        {\n            // Place thread partial into shared memory raking grid\n            T *placement_ptr = BlockRakingLayout::PlacementPtr(temp_storage.raking_grid, linear_tid);\n            *placement_ptr = input;\n\n            CTA_SYNC();\n\n            // Reduce parallelism down to just raking threads\n            if (linear_tid < RAKING_THREADS)\n            {\n                WarpScan warp_scan(temp_storage.warp_scan);\n\n                // Raking upsweep reduction across shared partials\n                T upsweep_partial = Upsweep(scan_op);\n\n                // Warp-synchronous scan\n                T exclusive_partial, block_aggregate;\n                warp_scan.ExclusiveScan(upsweep_partial, exclusive_partial, scan_op, block_aggregate);\n\n                // Obtain block-wide prefix in lane0, then broadcast to other lanes\n                T block_prefix = block_prefix_callback_op(block_aggregate);\n                block_prefix = warp_scan.Broadcast(block_prefix, 0);\n\n                // Update prefix with warpscan exclusive partial\n                T downsweep_prefix = scan_op(block_prefix, exclusive_partial);\n                if (linear_tid == 0)\n                    downsweep_prefix = block_prefix;\n\n                // Inclusive raking downsweep scan\n                InclusiveDownsweep(scan_op, downsweep_prefix);\n            }\n\n            CTA_SYNC();\n\n            // Grab thread prefix from shared memory\n            output = *placement_ptr;\n        }\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_scan_warp_scans.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockScanWarpscans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../util_arch.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../warp/warp_scan.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief BlockScanWarpScans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\ntemplate <\n    typename    T,\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockScanWarpScans\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// Constants\n    enum\n    {\n        /// Number of warp threads\n        WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH),\n\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        /// Number of active warps\n        WARPS = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n    };\n\n    ///  WarpScan utility type\n    typedef WarpScan<T, WARP_THREADS, PTX_ARCH> WarpScanT;\n\n    ///  WarpScan utility type\n    typedef WarpScan<T, WARPS, PTX_ARCH> WarpAggregateScan;\n\n    /// Shared memory storage layout type\n\n    struct __align__(32) _TempStorage\n    {\n        T                               warp_aggregates[WARPS];\n        typename WarpScanT::TempStorage warp_scan[WARPS];           ///< Buffer for warp-synchronous scans\n        T                               block_prefix;               ///< Shared prefix for the entire thread block\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    // Thread fields\n    _TempStorage    &temp_storage;\n    unsigned int    linear_tid;\n    unsigned int    warp_id;\n    unsigned int    lane_id;\n\n\n    //---------------------------------------------------------------------\n    // Constructors\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanWarpScans(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        warp_id((WARPS == 1) ? 0 : linear_tid / WARP_THREADS),\n        lane_id(LaneId())\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Utility methods\n    //---------------------------------------------------------------------\n\n    template <typename ScanOp, int WARP>\n    __device__ __forceinline__ void ApplyWarpAggregates(\n        T               &warp_prefix,           ///< [out] The calling thread's partial reduction\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate,   ///< [out] Threadblock-wide aggregate reduction of input items\n        Int2Type<WARP>  /*addend_warp*/)\n    {\n        if (warp_id == WARP)\n            warp_prefix = block_aggregate;\n\n        T addend = temp_storage.warp_aggregates[WARP];\n        block_aggregate = scan_op(block_aggregate, addend);\n\n        ApplyWarpAggregates(warp_prefix, scan_op, block_aggregate, Int2Type<WARP + 1>());\n    }\n\n    template <typename ScanOp>\n    __device__ __forceinline__ void ApplyWarpAggregates(\n        T               &/*warp_prefix*/,       ///< [out] The calling thread's partial reduction\n        ScanOp          /*scan_op*/,            ///< [in] Binary scan operator\n        T               &/*block_aggregate*/,   ///< [out] Threadblock-wide aggregate reduction of input items\n        Int2Type<WARPS> /*addend_warp*/)\n    {}\n\n\n    /// Use the warp-wide aggregates to compute the calling warp's prefix.  Also returns block-wide aggregate in all threads.\n    template <typename ScanOp>\n    __device__ __forceinline__ T ComputeWarpPrefix(\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>WARP_THREADS - 1</sub> only]</b> Warp-wide aggregate reduction of input items\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Last lane in each warp shares its warp-aggregate\n        if (lane_id == WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = warp_aggregate;\n\n        CTA_SYNC();\n\n        // Accumulate block aggregates and save the one that is our warp's prefix\n        T warp_prefix;\n        block_aggregate = temp_storage.warp_aggregates[0];\n\n        // Use template unrolling (since the PTX backend can't handle unrolling it for SM1x)\n        ApplyWarpAggregates(warp_prefix, scan_op, block_aggregate, Int2Type<1>());\n/*\n        #pragma unroll\n        for (int WARP = 1; WARP < WARPS; ++WARP)\n        {\n            if (warp_id == WARP)\n                warp_prefix = block_aggregate;\n\n            T addend = temp_storage.warp_aggregates[WARP];\n            block_aggregate = scan_op(block_aggregate, addend);\n        }\n*/\n\n        return warp_prefix;\n    }\n\n\n    /// Use the warp-wide aggregates and initial-value to compute the calling warp's prefix.  Also returns block-wide aggregate in all threads.\n    template <typename ScanOp>\n    __device__ __forceinline__ T ComputeWarpPrefix(\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>WARP_THREADS - 1</sub> only]</b> Warp-wide aggregate reduction of input items\n        T               &block_aggregate,   ///< [out] Threadblock-wide aggregate reduction of input items\n        const T         &initial_value)     ///< [in] Initial value to seed the exclusive scan\n    {\n        T warp_prefix = ComputeWarpPrefix(scan_op, warp_aggregate, block_aggregate);\n\n        warp_prefix = scan_op(initial_value, warp_prefix);\n\n        if (warp_id == 0)\n            warp_prefix = initial_value;\n\n        return warp_prefix;\n    }\n\n    //---------------------------------------------------------------------\n    // Exclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        // Compute block-wide exclusive scan.  The exclusive output from tid0 is invalid.\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, initial_value, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item\n        T               &exclusive_output,  ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        WarpScanT(temp_storage.warp_scan[warp_id]).Scan(input, inclusive_output, exclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp.  Warp prefix for warp0 is invalid.\n        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate);\n\n        // Apply warp prefix to our lane's partial\n        if (warp_id != 0)\n        {\n            exclusive_output = scan_op(warp_prefix, exclusive_output);\n            if (lane_id == 0)\n                exclusive_output = warp_prefix;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        WarpScanT(temp_storage.warp_scan[warp_id]).Scan(input, inclusive_output, exclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp\n        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate, initial_value);\n\n        // Apply warp prefix to our lane's partial\n        exclusive_output = scan_op(warp_prefix, exclusive_output);\n        if (lane_id == 0)\n            exclusive_output = warp_prefix;\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        // Compute block-wide exclusive scan.  The exclusive output from tid0 is invalid.\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n\n        // Use the first warp to determine the thread block prefix, returning the result in lane0\n        if (warp_id == 0)\n        {\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            if (lane_id == 0)\n            {\n                // Share the prefix with all threads\n                temp_storage.block_prefix = block_prefix;\n                exclusive_output = block_prefix;                // The block prefix is the exclusive output for tid0\n            }\n        }\n\n        CTA_SYNC();\n\n        // Incorporate thread block prefix into outputs\n        T block_prefix = temp_storage.block_prefix;\n        if (linear_tid > 0)\n        {\n            exclusive_output = scan_op(block_prefix, exclusive_output);\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        InclusiveScan(input, inclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan operator\n        T               &block_aggregate)               ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        WarpScanT(temp_storage.warp_scan[warp_id]).InclusiveScan(input, inclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp.  Warp prefix for warp0 is invalid.\n        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate);\n\n        // Apply warp prefix to our lane's partial\n        if (warp_id != 0)\n        {\n            inclusive_output = scan_op(warp_prefix, inclusive_output);\n        }\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        T block_aggregate;\n        InclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n\n        // Use the first warp to determine the thread block prefix, returning the result in lane0\n        if (warp_id == 0)\n        {\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            if (lane_id == 0)\n            {\n                // Share the prefix with all threads\n                temp_storage.block_prefix = block_prefix;\n            }\n        }\n\n        CTA_SYNC();\n\n        // Incorporate thread block prefix into outputs\n        T block_prefix = temp_storage.block_prefix;\n        exclusive_output = scan_op(block_prefix, exclusive_output);\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_scan_warp_scans2.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockScanWarpscans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../util_arch.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../warp/warp_scan.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief BlockScanWarpScans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\ntemplate <\n    typename    T,\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockScanWarpScans\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// Constants\n    enum\n    {\n        /// Number of warp threads\n        WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH),\n\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        /// Number of active warps\n        WARPS = (BLOCK_THREADS + WARP_THREADS - 1) / WARP_THREADS,\n    };\n\n    ///  WarpScan utility type\n    typedef WarpScan<T, WARP_THREADS, PTX_ARCH> WarpScanT;\n\n    ///  WarpScan utility type\n    typedef WarpScan<T, WARPS, PTX_ARCH> WarpAggregateScanT;\n\n    /// Shared memory storage layout type\n    struct _TempStorage\n    {\n        typename WarpAggregateScanT::TempStorage    inner_scan[WARPS];          ///< Buffer for warp-synchronous scans\n        typename WarpScanT::TempStorage             warp_scan[WARPS];           ///< Buffer for warp-synchronous scans\n        T                                           warp_aggregates[WARPS];\n        T                                           block_prefix;               ///< Shared prefix for the entire thread block\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    // Thread fields\n    _TempStorage    &temp_storage;\n    unsigned int    linear_tid;\n    unsigned int    warp_id;\n    unsigned int    lane_id;\n\n\n    //---------------------------------------------------------------------\n    // Constructors\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanWarpScans(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        warp_id((WARPS == 1) ? 0 : linear_tid / WARP_THREADS),\n        lane_id(LaneId())\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Utility methods\n    //---------------------------------------------------------------------\n\n    template <typename ScanOp, int WARP>\n    __device__ __forceinline__ void ApplyWarpAggregates(\n        T               &warp_prefix,           ///< [out] The calling thread's partial reduction\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate,   ///< [out] Threadblock-wide aggregate reduction of input items\n        Int2Type<WARP>  addend_warp)\n    {\n        if (warp_id == WARP)\n            warp_prefix = block_aggregate;\n\n        T addend = temp_storage.warp_aggregates[WARP];\n        block_aggregate = scan_op(block_aggregate, addend);\n\n        ApplyWarpAggregates(warp_prefix, scan_op, block_aggregate, Int2Type<WARP + 1>());\n    }\n\n    template <typename ScanOp>\n    __device__ __forceinline__ void ApplyWarpAggregates(\n        T               &warp_prefix,           ///< [out] The calling thread's partial reduction\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate,   ///< [out] Threadblock-wide aggregate reduction of input items\n        Int2Type<WARPS> addend_warp)\n    {}\n\n\n    /// Use the warp-wide aggregates to compute the calling warp's prefix.  Also returns block-wide aggregate in all threads.\n    template <typename ScanOp>\n    __device__ __forceinline__ T ComputeWarpPrefix(\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>WARP_THREADS - 1</sub> only]</b> Warp-wide aggregate reduction of input items\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Last lane in each warp shares its warp-aggregate\n        if (lane_id == WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = warp_aggregate;\n\n        CTA_SYNC();\n\n        // Accumulate block aggregates and save the one that is our warp's prefix\n        T warp_prefix;\n        block_aggregate = temp_storage.warp_aggregates[0];\n\n        // Use template unrolling (since the PTX backend can't handle unrolling it for SM1x)\n        ApplyWarpAggregates(warp_prefix, scan_op, block_aggregate, Int2Type<1>());\n/*\n        #pragma unroll\n        for (int WARP = 1; WARP < WARPS; ++WARP)\n        {\n            if (warp_id == WARP)\n                warp_prefix = block_aggregate;\n\n            T addend = temp_storage.warp_aggregates[WARP];\n            block_aggregate = scan_op(block_aggregate, addend);\n        }\n*/\n\n        return warp_prefix;\n    }\n\n\n    /// Use the warp-wide aggregates and initial-value to compute the calling warp's prefix.  Also returns block-wide aggregate in all threads.\n    template <typename ScanOp>\n    __device__ __forceinline__ T ComputeWarpPrefix(\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               warp_aggregate,     ///< [in] <b>[<em>lane</em><sub>WARP_THREADS - 1</sub> only]</b> Warp-wide aggregate reduction of input items\n        T               &block_aggregate,   ///< [out] Threadblock-wide aggregate reduction of input items\n        const T         &initial_value)     ///< [in] Initial value to seed the exclusive scan\n    {\n        T warp_prefix = ComputeWarpPrefix(scan_op, warp_aggregate, block_aggregate);\n\n        warp_prefix = scan_op(initial_value, warp_prefix);\n\n        if (warp_id == 0)\n            warp_prefix = initial_value;\n\n        return warp_prefix;\n    }\n\n    //---------------------------------------------------------------------\n    // Exclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        // Compute block-wide exclusive scan.  The exclusive output from tid0 is invalid.\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, initial_value, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item\n        T               &exclusive_output,  ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        WarpScanT my_warp_scan(temp_storage.warp_scan[warp_id]);\n\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        my_warp_scan.Scan(input, inclusive_output, exclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp.  Warp prefix for warp0 is invalid.\n//        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate);\n\n//--------------------------------------------------\n        // Last lane in each warp shares its warp-aggregate\n        if (lane_id == WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        // Get the warp scan partial\n        T warp_inclusive, warp_prefix;\n        if (lane_id < WARPS)\n        {\n            // Scan the warpscan partials\n            T warp_val = temp_storage.warp_aggregates[lane_id];\n            WarpAggregateScanT(temp_storage.inner_scan[warp_id]).Scan(warp_val, warp_inclusive, warp_prefix, scan_op);\n        }\n\n        warp_prefix         = my_warp_scan.Broadcast(warp_prefix, warp_id);\n        block_aggregate     = my_warp_scan.Broadcast(warp_inclusive, WARPS - 1);\n//--------------------------------------------------\n\n        // Apply warp prefix to our lane's partial\n        if (warp_id != 0)\n        {\n            exclusive_output = scan_op(warp_prefix, exclusive_output);\n            if (lane_id == 0)\n                exclusive_output = warp_prefix;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        WarpScanT my_warp_scan(temp_storage.warp_scan[warp_id]);\n\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        my_warp_scan.Scan(input, inclusive_output, exclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp\n//        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate, initial_value);\n\n//--------------------------------------------------\n        // Last lane in each warp shares its warp-aggregate\n        if (lane_id == WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        // Get the warp scan partial\n        T warp_inclusive, warp_prefix;\n        if (lane_id < WARPS)\n        {\n            // Scan the warpscan partials\n            T warp_val = temp_storage.warp_aggregates[lane_id];\n            WarpAggregateScanT(temp_storage.inner_scan[warp_id]).Scan(warp_val, warp_inclusive, warp_prefix, initial_value, scan_op);\n        }\n\n        warp_prefix         = my_warp_scan.Broadcast(warp_prefix, warp_id);\n        block_aggregate     = my_warp_scan.Broadcast(warp_inclusive, WARPS - 1);\n//--------------------------------------------------\n\n        // Apply warp prefix to our lane's partial\n        exclusive_output = scan_op(warp_prefix, exclusive_output);\n        if (lane_id == 0)\n            exclusive_output = warp_prefix;\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        // Compute block-wide exclusive scan.  The exclusive output from tid0 is invalid.\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n\n        // Use the first warp to determine the thread block prefix, returning the result in lane0\n        if (warp_id == 0)\n        {\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            if (lane_id == 0)\n            {\n                // Share the prefix with all threads\n                temp_storage.block_prefix = block_prefix;\n                exclusive_output = block_prefix;                // The block prefix is the exclusive output for tid0\n            }\n        }\n\n        CTA_SYNC();\n\n        // Incorporate thread block prefix into outputs\n        T block_prefix = temp_storage.block_prefix;\n        if (linear_tid > 0)\n        {\n            exclusive_output = scan_op(block_prefix, exclusive_output);\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        InclusiveScan(input, inclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan operator\n        T               &block_aggregate)               ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        WarpScanT(temp_storage.warp_scan[warp_id]).InclusiveScan(input, inclusive_output, scan_op);\n\n        // Compute the warp-wide prefix and block-wide aggregate for each warp.  Warp prefix for warp0 is invalid.\n        T warp_prefix = ComputeWarpPrefix(scan_op, inclusive_output, block_aggregate);\n\n        // Apply warp prefix to our lane's partial\n        if (warp_id != 0)\n        {\n            inclusive_output = scan_op(warp_prefix, inclusive_output);\n        }\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        T block_aggregate;\n        InclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n\n        // Use the first warp to determine the thread block prefix, returning the result in lane0\n        if (warp_id == 0)\n        {\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            if (lane_id == 0)\n            {\n                // Share the prefix with all threads\n                temp_storage.block_prefix = block_prefix;\n            }\n        }\n\n        CTA_SYNC();\n\n        // Incorporate thread block prefix into outputs\n        T block_prefix = temp_storage.block_prefix;\n        exclusive_output = scan_op(block_prefix, exclusive_output);\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/block/specializations/block_scan_warp_scans3.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::BlockScanWarpscans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\n\n#pragma once\n\n#include \"../../util_arch.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../warp/warp_scan.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief BlockScanWarpScans provides warpscan-based variants of parallel prefix scan across a CUDA thread block.\n */\ntemplate <\n    typename    T,\n    int         BLOCK_DIM_X,    ///< The thread block length in threads along the X dimension\n    int         BLOCK_DIM_Y,    ///< The thread block length in threads along the Y dimension\n    int         BLOCK_DIM_Z,    ///< The thread block length in threads along the Z dimension\n    int         PTX_ARCH>       ///< The PTX compute capability for which to to specialize this collective\nstruct BlockScanWarpScans\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// Constants\n    enum\n    {\n        /// The thread block size in threads\n        BLOCK_THREADS = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z,\n\n        /// Number of warp threads\n        INNER_WARP_THREADS = CUB_WARP_THREADS(PTX_ARCH),\n        OUTER_WARP_THREADS = BLOCK_THREADS / INNER_WARP_THREADS,\n\n        /// Number of outer scan warps\n        OUTER_WARPS = INNER_WARP_THREADS\n    };\n\n    ///  Outer WarpScan utility type\n    typedef WarpScan<T, OUTER_WARP_THREADS, PTX_ARCH> OuterWarpScanT;\n\n    ///  Inner WarpScan utility type\n    typedef WarpScan<T, INNER_WARP_THREADS, PTX_ARCH> InnerWarpScanT;\n\n    typedef typename OuterWarpScanT::TempStorage OuterScanArray[OUTER_WARPS];\n\n\n    /// Shared memory storage layout type\n    struct _TempStorage\n    {\n        union Aliasable\n        {\n            Uninitialized<OuterScanArray>           outer_warp_scan;  ///< Buffer for warp-synchronous outer scans\n            typename InnerWarpScanT::TempStorage    inner_warp_scan;  ///< Buffer for warp-synchronous inner scan\n\n        } aliasable;\n\n        T                               warp_aggregates[OUTER_WARPS];\n\n        T                               block_aggregate;                           ///< Shared prefix for the entire thread block\n    };\n\n\n    /// Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Per-thread fields\n    //---------------------------------------------------------------------\n\n    // Thread fields\n    _TempStorage    &temp_storage;\n    unsigned int    linear_tid;\n    unsigned int    warp_id;\n    unsigned int    lane_id;\n\n\n    //---------------------------------------------------------------------\n    // Constructors\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ BlockScanWarpScans(\n        TempStorage &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n        linear_tid(RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z)),\n        warp_id((OUTER_WARPS == 1) ? 0 : linear_tid / OUTER_WARP_THREADS),\n        lane_id((OUTER_WARPS == 1) ? linear_tid : linear_tid % OUTER_WARP_THREADS)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Exclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        // Compute block-wide exclusive scan.  The exclusive output from tid0 is invalid.\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        ExclusiveScan(input, exclusive_output, initial_value, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.  With no initial value, the output computed for <em>thread</em><sub>0</sub> is undefined.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item\n        T               &exclusive_output,  ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        OuterWarpScanT(temp_storage.aliasable.outer_warp_scan.Alias()[warp_id]).Scan(\n            input, inclusive_output, exclusive_output, scan_op);\n\n        // Share outer warp total\n        if (lane_id == OUTER_WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        if (linear_tid < INNER_WARP_THREADS)\n        {\n            T outer_warp_input = temp_storage.warp_aggregates[linear_tid];\n            T outer_warp_exclusive;\n\n            InnerWarpScanT(temp_storage.aliasable.inner_warp_scan).ExclusiveScan(\n                outer_warp_input, outer_warp_exclusive, scan_op, block_aggregate);\n\n            temp_storage.block_aggregate                = block_aggregate;\n            temp_storage.warp_aggregates[linear_tid]    = outer_warp_exclusive;\n        }\n\n        CTA_SYNC();\n\n        if (warp_id != 0)\n        {\n            // Retrieve block aggregate\n            block_aggregate = temp_storage.block_aggregate;\n\n            // Apply warp prefix to our lane's partial\n            T outer_warp_exclusive = temp_storage.warp_aggregates[warp_id];\n            exclusive_output = scan_op(outer_warp_exclusive, exclusive_output);\n            if (lane_id == 0)\n                exclusive_output = outer_warp_exclusive;\n        }\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input items\n        T               &exclusive_output,  ///< [out] Calling thread's output items (may be aliased to \\p input)\n        const T         &initial_value,     ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &block_aggregate)   ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        OuterWarpScanT(temp_storage.aliasable.outer_warp_scan.Alias()[warp_id]).Scan(\n            input, inclusive_output, exclusive_output, scan_op);\n\n        // Share outer warp total\n        if (lane_id == OUTER_WARP_THREADS - 1)\n        {\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n        }\n\n        CTA_SYNC();\n\n        if (linear_tid < INNER_WARP_THREADS)\n        {\n            T outer_warp_input = temp_storage.warp_aggregates[linear_tid];\n            T outer_warp_exclusive;\n\n            InnerWarpScanT(temp_storage.aliasable.inner_warp_scan).ExclusiveScan(\n                outer_warp_input, outer_warp_exclusive, initial_value, scan_op, block_aggregate);\n\n            temp_storage.block_aggregate                = block_aggregate;\n            temp_storage.warp_aggregates[linear_tid]    = outer_warp_exclusive;\n        }\n\n        CTA_SYNC();\n\n        // Retrieve block aggregate\n        block_aggregate = temp_storage.block_aggregate;\n\n        // Apply warp prefix to our lane's partial\n        T outer_warp_exclusive = temp_storage.warp_aggregates[warp_id];\n        exclusive_output = scan_op(outer_warp_exclusive, exclusive_output);\n        if (lane_id == 0)\n            exclusive_output = outer_warp_exclusive;\n    }\n\n\n    /// Computes an exclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  The call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &exclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        T inclusive_output;\n        OuterWarpScanT(temp_storage.aliasable.outer_warp_scan.Alias()[warp_id]).Scan(\n            input, inclusive_output, exclusive_output, scan_op);\n\n        // Share outer warp total\n        if (lane_id == OUTER_WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        if (linear_tid < INNER_WARP_THREADS)\n        {\n            InnerWarpScanT inner_scan(temp_storage.aliasable.inner_warp_scan);\n\n            T upsweep = temp_storage.warp_aggregates[linear_tid];\n            T downsweep_prefix, block_aggregate;\n\n            inner_scan.ExclusiveScan(upsweep, downsweep_prefix, scan_op, block_aggregate);\n\n            // Use callback functor to get block prefix in lane0 and then broadcast to other lanes\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            block_prefix = inner_scan.Broadcast(block_prefix, 0);\n\n            downsweep_prefix = scan_op(block_prefix, downsweep_prefix);\n            if (linear_tid == 0)\n                downsweep_prefix = block_prefix;\n\n            temp_storage.warp_aggregates[linear_tid] = downsweep_prefix;\n        }\n\n        CTA_SYNC();\n\n        // Apply warp prefix to our lane's partial (or assign it if partial is invalid)\n        T outer_warp_exclusive = temp_storage.warp_aggregates[warp_id];\n        exclusive_output = scan_op(outer_warp_exclusive, exclusive_output);\n        if (lane_id == 0)\n            exclusive_output = outer_warp_exclusive;\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive scans\n    //---------------------------------------------------------------------\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op)                        ///< [in] Binary scan operator\n    {\n        T block_aggregate;\n        InclusiveScan(input, inclusive_output, scan_op, block_aggregate);\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  Also provides every thread with the block-wide \\p block_aggregate of all inputs.\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,                          ///< [in] Calling thread's input item\n        T               &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp          scan_op,                        ///< [in] Binary scan operator\n        T               &block_aggregate)               ///< [out] Threadblock-wide aggregate reduction of input items\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        OuterWarpScanT(temp_storage.aliasable.outer_warp_scan.Alias()[warp_id]).InclusiveScan(\n            input, inclusive_output, scan_op);\n\n        // Share outer warp total\n        if (lane_id == OUTER_WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        if (linear_tid < INNER_WARP_THREADS)\n        {\n            T outer_warp_input = temp_storage.warp_aggregates[linear_tid];\n            T outer_warp_exclusive;\n\n            InnerWarpScanT(temp_storage.aliasable.inner_warp_scan).ExclusiveScan(\n                outer_warp_input, outer_warp_exclusive, scan_op, block_aggregate);\n\n            temp_storage.block_aggregate                = block_aggregate;\n            temp_storage.warp_aggregates[linear_tid]    = outer_warp_exclusive;\n        }\n\n        CTA_SYNC();\n\n        if (warp_id != 0)\n        {\n            // Retrieve block aggregate\n            block_aggregate = temp_storage.block_aggregate;\n\n            // Apply warp prefix to our lane's partial\n            T outer_warp_exclusive = temp_storage.warp_aggregates[warp_id];\n            inclusive_output = scan_op(outer_warp_exclusive, inclusive_output);\n        }\n    }\n\n\n    /// Computes an inclusive thread block-wide prefix scan using the specified binary \\p scan_op functor.  Each thread contributes one input element.  the call-back functor \\p block_prefix_callback_op is invoked by the first warp in the block, and the value returned by <em>lane</em><sub>0</sub> in that warp is used as the \"seed\" value that logically prefixes the thread block's scan inputs.\n    template <\n        typename ScanOp,\n        typename BlockPrefixCallbackOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,                          ///< [in] Calling thread's input item\n        T                       &inclusive_output,              ///< [out] Calling thread's output item (may be aliased to \\p input)\n        ScanOp                  scan_op,                        ///< [in] Binary scan operator\n        BlockPrefixCallbackOp   &block_prefix_callback_op)      ///< [in-out] <b>[<em>warp</em><sub>0</sub> only]</b> Call-back functor for specifying a thread block-wide prefix to be applied to all inputs.\n    {\n        // Compute warp scan in each warp.  The exclusive output from each lane0 is invalid.\n        OuterWarpScanT(temp_storage.aliasable.outer_warp_scan.Alias()[warp_id]).InclusiveScan(\n            input, inclusive_output, scan_op);\n\n        // Share outer warp total\n        if (lane_id == OUTER_WARP_THREADS - 1)\n            temp_storage.warp_aggregates[warp_id] = inclusive_output;\n\n        CTA_SYNC();\n\n        if (linear_tid < INNER_WARP_THREADS)\n        {\n            InnerWarpScanT inner_scan(temp_storage.aliasable.inner_warp_scan);\n\n            T upsweep = temp_storage.warp_aggregates[linear_tid];\n            T downsweep_prefix, block_aggregate;\n            inner_scan.ExclusiveScan(upsweep, downsweep_prefix, scan_op, block_aggregate);\n\n            // Use callback functor to get block prefix in lane0 and then broadcast to other lanes\n            T block_prefix = block_prefix_callback_op(block_aggregate);\n            block_prefix = inner_scan.Broadcast(block_prefix, 0);\n\n            downsweep_prefix = scan_op(block_prefix, downsweep_prefix);\n            if (linear_tid == 0)\n                downsweep_prefix = block_prefix;\n\n            temp_storage.warp_aggregates[linear_tid]    = downsweep_prefix;\n        }\n\n        CTA_SYNC();\n\n        // Apply warp prefix to our lane's partial\n        T outer_warp_exclusive = temp_storage.warp_aggregates[warp_id];\n        inclusive_output = scan_op(outer_warp_exclusive, inclusive_output);\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/cub.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * CUB umbrella include file\n */\n\n#pragma once\n\n\n// Block\n#include \"block/block_histogram.cuh\"\n#include \"block/block_discontinuity.cuh\"\n#include \"block/block_exchange.cuh\"\n#include \"block/block_load.cuh\"\n#include \"block/block_radix_rank.cuh\"\n#include \"block/block_radix_sort.cuh\"\n#include \"block/block_reduce.cuh\"\n#include \"block/block_scan.cuh\"\n#include \"block/block_store.cuh\"\n//#include \"block/block_shift.cuh\"\n\n// Device\n#include \"device/device_histogram.cuh\"\n#include \"device/device_partition.cuh\"\n#include \"device/device_radix_sort.cuh\"\n#include \"device/device_reduce.cuh\"\n#include \"device/device_run_length_encode.cuh\"\n#include \"device/device_scan.cuh\"\n#include \"device/device_segmented_radix_sort.cuh\"\n#include \"device/device_segmented_reduce.cuh\"\n#include \"device/device_select.cuh\"\n#include \"device/device_spmv.cuh\"\n\n// Grid\n//#include \"grid/grid_barrier.cuh\"\n#include \"grid/grid_even_share.cuh\"\n#include \"grid/grid_mapping.cuh\"\n#include \"grid/grid_queue.cuh\"\n\n// Thread\n#include \"thread/thread_load.cuh\"\n#include \"thread/thread_operators.cuh\"\n#include \"thread/thread_reduce.cuh\"\n#include \"thread/thread_scan.cuh\"\n#include \"thread/thread_store.cuh\"\n\n// Warp\n#include \"warp/warp_reduce.cuh\"\n#include \"warp/warp_scan.cuh\"\n\n// Iterator\n#include \"iterator/arg_index_input_iterator.cuh\"\n#include \"iterator/cache_modified_input_iterator.cuh\"\n#include \"iterator/cache_modified_output_iterator.cuh\"\n#include \"iterator/constant_input_iterator.cuh\"\n#include \"iterator/counting_input_iterator.cuh\"\n#include \"iterator/tex_obj_input_iterator.cuh\"\n#include \"iterator/tex_ref_input_iterator.cuh\"\n#include \"iterator/transform_input_iterator.cuh\"\n\n// Util\n#include \"util_arch.cuh\"\n#include \"util_debug.cuh\"\n#include \"util_device.cuh\"\n#include \"util_macro.cuh\"\n#include \"util_ptx.cuh\"\n#include \"util_type.cuh\"\n\n"
  },
  {
    "path": "external/cub/cub/device/device_histogram.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceHistogram provides device-wide parallel operations for constructing histogram(s) from a sequence of samples data residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n#include <limits>\n\n#include \"dispatch/dispatch_histogram.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceHistogram provides device-wide parallel operations for constructing histogram(s) from a sequence of samples data residing within device-accessible memory. ![](histogram_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * A <a href=\"http://en.wikipedia.org/wiki/Histogram\"><em>histogram</em></a>\n * counts the number of observations that fall into each of the disjoint categories (known as <em>bins</em>).\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceHistogram}\n *\n */\nstruct DeviceHistogram\n{\n    /******************************************************************//**\n     * \\name Evenly-segmented bin ranges\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes an intensity histogram from a sequence of data samples using equal-width bins.\n     *\n     * \\par\n     * - The number of histogram bins is (\\p num_levels - 1)\n     * - All bins comprise the same width of sample values: (\\p upper_level - \\p lower_level) / (\\p num_levels - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of a six-bin histogram\n     * from a sequence of float samples\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples and\n     * // output histogram\n     * int      num_samples;    // e.g., 10\n     * float*   d_samples;      // e.g., [2.2, 6.0, 7.1, 2.9, 3.5, 0.3, 2.9, 2.0, 6.1, 999.5]\n     * int*     d_histogram;    // e.g., [ -, -, -, -, -, -, -, -]\n     * int      num_levels;     // e.g., 7       (seven level boundaries for six bins)\n     * float    lower_level;    // e.g., 0.0     (lower sample value boundary of lowest bin)\n     * float    upper_level;    // e.g., 12.0    (upper sample value boundary of upper bin)\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::HistogramEven(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level, num_samples);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::HistogramEven(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level, num_samples);\n     *\n     * // d_histogram   <-- [1, 0, 5, 0, 3, 0, 0, 0];\n     *\n     * \\endcode\n     *\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t HistogramEven(\n        void*               d_temp_storage,                             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the input sequence of data samples.\n        CounterT*           d_histogram,                                ///< [out] The pointer to the histogram counter output array of length <tt>num_levels</tt> - 1.\n        int                 num_levels,                                 ///< [in] The number of boundaries (levels) for delineating histogram samples.  Implies that the number of bins is <tt>num_levels</tt> - 1.\n        LevelT              lower_level,                                ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin.\n        LevelT              upper_level,                                ///< [in] The upper sample value bound (exclusive) for the highest histogram bin.\n        OffsetT             num_samples,                                ///< [in] The number of input samples (i.e., the length of \\p d_samples)\n        cudaStream_t        stream                  = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous       = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n        CounterT*           d_histogram1[1]     = {d_histogram};\n        int                 num_levels1[1]      = {num_levels};\n        LevelT              lower_level1[1]     = {lower_level};\n        LevelT              upper_level1[1]     = {upper_level};\n\n        return MultiHistogramEven<1, 1>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram1,\n            num_levels1,\n            lower_level1,\n            upper_level1,\n            num_samples,\n            1,\n            sizeof(SampleT) * num_samples,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes an intensity histogram from a sequence of data samples using equal-width bins.\n     *\n     * \\par\n     * - A two-dimensional <em>region of interest</em> within \\p d_samples can be specified\n     *   using the \\p num_row_samples, num_rows, and \\p row_stride_bytes parameters.\n     * - The row stride must be a whole multiple of the sample data type\n     *   size, i.e., <tt>(row_stride_bytes % sizeof(SampleT)) == 0</tt>.\n     * - The number of histogram bins is (\\p num_levels - 1)\n     * - All bins comprise the same width of sample values: (\\p upper_level - \\p lower_level) / (\\p num_levels - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of a six-bin histogram\n     * from a 2x5 region of interest within a flattened 2x7 array of float samples.\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples and\n     * // output histogram\n     * int      num_row_samples;    // e.g., 5\n     * int      num_rows;           // e.g., 2;\n     * size_t   row_stride_bytes;   // e.g., 7 * sizeof(float)\n     * float*   d_samples;          // e.g., [2.2, 6.0, 7.1, 2.9, 3.5,   -, -,\n     *                              //        0.3, 2.9, 2.0, 6.1, 999.5, -, -]\n     * int*     d_histogram;        // e.g., [ -, -, -, -, -, -, -, -]\n     * int      num_levels;         // e.g., 7       (seven level boundaries for six bins)\n     * float    lower_level;        // e.g., 0.0     (lower sample value boundary of lowest bin)\n     * float    upper_level;        // e.g., 12.0    (upper sample value boundary of upper bin)\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage  = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::HistogramEven(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level,\n     *     num_row_samples, num_rows, row_stride_bytes);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::HistogramEven(d_temp_storage, temp_storage_bytes, d_samples, d_histogram,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level,\n     *     num_row_samples, num_rows, row_stride_bytes);\n     *\n     * // d_histogram   <-- [1, 0, 5, 0, 3, 0, 0, 0];\n     *\n     * \\endcode\n     *\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t HistogramEven(\n        void*               d_temp_storage,                             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the input sequence of data samples.\n        CounterT*           d_histogram,                                ///< [out] The pointer to the histogram counter output array of length <tt>num_levels</tt> - 1.\n        int                 num_levels,                                 ///< [in] The number of boundaries (levels) for delineating histogram samples.  Implies that the number of bins is <tt>num_levels</tt> - 1.\n        LevelT              lower_level,                                ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin.\n        LevelT              upper_level,                                ///< [in] The upper sample value bound (exclusive) for the highest histogram bin.\n        OffsetT             num_row_samples,                            ///< [in] The number of data samples per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        size_t              row_stride_bytes,                           ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n        cudaStream_t        stream                  = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous       = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        CounterT*           d_histogram1[1]     = {d_histogram};\n        int                 num_levels1[1]      = {num_levels};\n        LevelT              lower_level1[1]     = {lower_level};\n        LevelT              upper_level1[1]     = {upper_level};\n\n        return MultiHistogramEven<1, 1>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram1,\n            num_levels1,\n            lower_level1,\n            upper_level1,\n            num_row_samples,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n\n    /**\n     * \\brief Computes per-channel intensity histograms from a sequence of multi-channel \"pixel\" data samples using equal-width bins.\n     *\n     * \\par\n     * - The input is a sequence of <em>pixel</em> structures, where each pixel comprises\n     *   a record of \\p NUM_CHANNELS consecutive data samples (e.g., an <em>RGBA</em> pixel).\n     * - Of the \\p NUM_CHANNELS specified, the function will only compute histograms\n     *   for the first \\p NUM_ACTIVE_CHANNELS (e.g., only <em>RGB</em> histograms from <em>RGBA</em>\n     *   pixel samples).\n     * - The number of histogram bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n     * - For channel<sub><em>i</em></sub>, the range of values for all histogram bins\n     *   have the same width: (<tt>upper_level[i]</tt> - <tt>lower_level[i]</tt>) / (<tt> num_levels[i]</tt> - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of three 256-bin <em>RGB</em> histograms\n     * from a quad-channel sequence of <em>RGBA</em> pixels (8 bits per channel per pixel)\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples\n     * // and output histograms\n     * int              num_pixels;         // e.g., 5\n     * unsigned char*   d_samples;          // e.g., [(2, 6, 7, 5), (3, 0, 2, 1), (7, 0, 6, 2),\n     *                                      //        (0, 6, 7, 5), (3, 0, 2, 6)]\n     * int*             d_histogram[3];     // e.g., three device pointers to three device buffers,\n     *                                      //       each allocated with 256 integer counters\n     * int              num_levels[3];      // e.g., {257, 257, 257};\n     * unsigned int     lower_level[3];     // e.g., {0, 0, 0};\n     * unsigned int     upper_level[3];     // e.g., {256, 256, 256};\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::MultiHistogramEven<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level, num_pixels);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::MultiHistogramEven<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level, num_pixels);\n     *\n     * // d_histogram   <-- [ [1, 0, 1, 2, 0, 0, 0, 1, 0, 0, 0, ..., 0],\n     * //                     [0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, ..., 0],\n     * //                     [0, 0, 2, 0, 0, 0, 1, 2, 0, 0, 0, ..., 0] ]\n     *\n     * \\endcode\n     *\n     * \\tparam NUM_CHANNELS             Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n     * \\tparam NUM_ACTIVE_CHANNELS      <b>[inferred]</b> Number of channels actively being histogrammed\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        int                 NUM_CHANNELS,\n        int                 NUM_ACTIVE_CHANNELS,\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t MultiHistogramEven(\n        void*               d_temp_storage,                             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four <em>RGBA</em> 8-bit samples).\n        CounterT*           d_histogram[NUM_ACTIVE_CHANNELS],           ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histogram[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n        int                 num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n        LevelT              lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n        LevelT              upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n        OffsetT             num_pixels,                                 ///< [in] The number of multi-channel pixels (i.e., the length of \\p d_samples / NUM_CHANNELS)\n        cudaStream_t        stream                  = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous       = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n        return MultiHistogramEven<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram,\n            num_levels,\n            lower_level,\n            upper_level,\n            num_pixels,\n            1,\n            sizeof(SampleT) * NUM_CHANNELS * num_pixels,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes per-channel intensity histograms from a sequence of multi-channel \"pixel\" data samples using equal-width bins.\n     *\n     * \\par\n     * - The input is a sequence of <em>pixel</em> structures, where each pixel comprises\n     *   a record of \\p NUM_CHANNELS consecutive data samples (e.g., an <em>RGBA</em> pixel).\n     * - Of the \\p NUM_CHANNELS specified, the function will only compute histograms\n     *   for the first \\p NUM_ACTIVE_CHANNELS (e.g., only <em>RGB</em> histograms from <em>RGBA</em>\n     *   pixel samples).\n     * - A two-dimensional <em>region of interest</em> within \\p d_samples can be specified\n     *   using the \\p num_row_samples, num_rows, and \\p row_stride_bytes parameters.\n     * - The row stride must be a whole multiple of the sample data type\n     *   size, i.e., <tt>(row_stride_bytes % sizeof(SampleT)) == 0</tt>.\n     * - The number of histogram bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n     * - For channel<sub><em>i</em></sub>, the range of values for all histogram bins\n     *   have the same width: (<tt>upper_level[i]</tt> - <tt>lower_level[i]</tt>) / (<tt> num_levels[i]</tt> - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of three 256-bin <em>RGB</em> histograms from a 2x3 region of\n     * interest of within a flattened 2x4 array of quad-channel <em>RGBA</em> pixels (8 bits per channel per pixel).\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples\n     * // and output histograms\n     * int              num_row_pixels;     // e.g., 3\n     * int              num_rows;           // e.g., 2\n     * size_t           row_stride_bytes;   // e.g., 4 * sizeof(unsigned char) * NUM_CHANNELS\n     * unsigned char*   d_samples;          // e.g., [(2, 6, 7, 5), (3, 0, 2, 1), (7, 0, 6, 2), (-, -, -, -),\n     *                                      //        (0, 6, 7, 5), (3, 0, 2, 6), (1, 1, 1, 1), (-, -, -, -)]\n     * int*             d_histogram[3];     // e.g., three device pointers to three device buffers,\n     *                                      //       each allocated with 256 integer counters\n     * int              num_levels[3];      // e.g., {257, 257, 257};\n     * unsigned int     lower_level[3];     // e.g., {0, 0, 0};\n     * unsigned int     upper_level[3];     // e.g., {256, 256, 256};\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::MultiHistogramEven<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level,\n     *     num_row_pixels, num_rows, row_stride_bytes);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::MultiHistogramEven<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, lower_level, upper_level,\n     *     num_row_pixels, num_rows, row_stride_bytes);\n     *\n     * // d_histogram   <-- [ [1, 1, 1, 2, 0, 0, 0, 1, 0, 0, 0, ..., 0],\n     * //                     [0, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, ..., 0],\n     * //                     [0, 1, 2, 0, 0, 0, 1, 2, 0, 0, 0, ..., 0] ]\n     *\n     * \\endcode\n     *\n     * \\tparam NUM_CHANNELS             Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n     * \\tparam NUM_ACTIVE_CHANNELS      <b>[inferred]</b> Number of channels actively being histogrammed\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        int                 NUM_CHANNELS,\n        int                 NUM_ACTIVE_CHANNELS,\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t MultiHistogramEven(\n        void*               d_temp_storage,                             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four <em>RGBA</em> 8-bit samples).\n        CounterT*           d_histogram[NUM_ACTIVE_CHANNELS],           ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histogram[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n        int                 num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n        LevelT              lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n        LevelT              upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n        OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        size_t              row_stride_bytes,                           ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n        cudaStream_t        stream                  = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous       = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n        Int2Type<sizeof(SampleT) == 1> is_byte_sample;\n\n        if ((sizeof(OffsetT) > sizeof(int)) &&\n            ((unsigned long long) (num_rows * row_stride_bytes) < (unsigned long long) std::numeric_limits<int>::max()))\n        {\n            // Down-convert OffsetT data type\n\n\n            return DipatchHistogram<NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, LevelT, int>::DispatchEven(\n                d_temp_storage, temp_storage_bytes, d_samples, d_histogram, num_levels, lower_level, upper_level,\n                (int) num_row_pixels, (int) num_rows, (int) (row_stride_bytes / sizeof(SampleT)),\n                stream, debug_synchronous, is_byte_sample);\n        }\n\n        return DipatchHistogram<NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, LevelT, OffsetT>::DispatchEven(\n            d_temp_storage, temp_storage_bytes, d_samples, d_histogram, num_levels, lower_level, upper_level,\n            num_row_pixels, num_rows, (OffsetT) (row_stride_bytes / sizeof(SampleT)),\n            stream, debug_synchronous, is_byte_sample);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Custom bin ranges\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes an intensity histogram from a sequence of data samples using the specified bin boundary levels.\n     *\n     * \\par\n     * - The number of histogram bins is (\\p num_levels - 1)\n     * - The value range for bin<sub><em>i</em></sub> is [<tt>level[i]</tt>, <tt>level[i+1]</tt>)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of an six-bin histogram\n     * from a sequence of float samples\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples and\n     * // output histogram\n     * int      num_samples;    // e.g., 10\n     * float*   d_samples;      // e.g., [2.2, 6.0, 7.1, 2.9, 3.5, 0.3, 2.9, 2.0, 6.1, 999.5]\n     * int*     d_histogram;    // e.g., [ -, -, -, -, -, -, -, -]\n     * int      num_levels      // e.g., 7 (seven level boundaries for six bins)\n     * float*   d_levels;       // e.g., [0.0, 2.0, 4.0, 6.0, 8.0, 12.0, 16.0]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::HistogramRange(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_samples);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::HistogramRange(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_samples);\n     *\n     * // d_histogram   <-- [1, 0, 5, 0, 3, 0, 0, 0];\n     *\n     * \\endcode\n     *\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t HistogramRange(\n        void*               d_temp_storage,                         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                              ///< [in] The pointer to the input sequence of data samples.\n        CounterT*           d_histogram,                            ///< [out] The pointer to the histogram counter output array of length <tt>num_levels</tt> - 1.\n        int                 num_levels,                             ///< [in] The number of boundaries (levels) for delineating histogram samples.  Implies that the number of bins is <tt>num_levels</tt> - 1.\n        LevelT*             d_levels,                               ///< [in] The pointer to the array of boundaries (levels).  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_samples,                            ///< [in] The number of data samples per row in the region of interest\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n        CounterT*           d_histogram1[1] = {d_histogram};\n        int                 num_levels1[1]  = {num_levels};\n        LevelT*             d_levels1[1]    = {d_levels};\n\n        return MultiHistogramRange<1, 1>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram1,\n            num_levels1,\n            d_levels1,\n            num_samples,\n            1,\n            sizeof(SampleT) * num_samples,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes an intensity histogram from a sequence of data samples using the specified bin boundary levels.\n     *\n     * \\par\n     * - A two-dimensional <em>region of interest</em> within \\p d_samples can be specified\n     *   using the \\p num_row_samples, num_rows, and \\p row_stride_bytes parameters.\n     * - The row stride must be a whole multiple of the sample data type\n     *   size, i.e., <tt>(row_stride_bytes % sizeof(SampleT)) == 0</tt>.\n     * - The number of histogram bins is (\\p num_levels - 1)\n     * - The value range for bin<sub><em>i</em></sub> is [<tt>level[i]</tt>, <tt>level[i+1]</tt>)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of a six-bin histogram\n     * from a 2x5 region of interest within a flattened 2x7 array of float samples.\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples and\n     * // output histogram\n     * int      num_row_samples;    // e.g., 5\n     * int      num_rows;           // e.g., 2;\n     * int      row_stride_bytes;   // e.g., 7 * sizeof(float)\n     * float*   d_samples;          // e.g., [2.2, 6.0, 7.1, 2.9, 3.5,   -, -,\n     *                              //        0.3, 2.9, 2.0, 6.1, 999.5, -, -]\n     * int*     d_histogram;        // e.g., [ , , , , , , , ]\n     * int      num_levels          // e.g., 7 (seven level boundaries for six bins)\n     * float    *d_levels;          // e.g., [0.0, 2.0, 4.0, 6.0, 8.0, 12.0, 16.0]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::HistogramRange(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels,\n     *     num_row_samples, num_rows, row_stride_bytes);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::HistogramRange(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels,\n     *     num_row_samples, num_rows, row_stride_bytes);\n     *\n     * // d_histogram   <-- [1, 0, 5, 0, 3, 0, 0, 0];\n     *\n     * \\endcode\n     *\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t HistogramRange(\n        void*               d_temp_storage,                         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                              ///< [in] The pointer to the input sequence of data samples.\n        CounterT*           d_histogram,                            ///< [out] The pointer to the histogram counter output array of length <tt>num_levels</tt> - 1.\n        int                 num_levels,                             ///< [in] The number of boundaries (levels) for delineating histogram samples.  Implies that the number of bins is <tt>num_levels</tt> - 1.\n        LevelT*             d_levels,                               ///< [in] The pointer to the array of boundaries (levels).  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_row_samples,                        ///< [in] The number of data samples per row in the region of interest\n        OffsetT             num_rows,                               ///< [in] The number of rows in the region of interest\n        size_t              row_stride_bytes,                       ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        CounterT*           d_histogram1[1]     = {d_histogram};\n        int                 num_levels1[1]      = {num_levels};\n        LevelT*             d_levels1[1]        = {d_levels};\n\n        return MultiHistogramRange<1, 1>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram1,\n            num_levels1,\n            d_levels1,\n            num_row_samples,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n\n    /**\n     * \\brief Computes per-channel intensity histograms from a sequence of multi-channel \"pixel\" data samples using the specified bin boundary levels.\n     *\n     * \\par\n     * - The input is a sequence of <em>pixel</em> structures, where each pixel comprises\n     *   a record of \\p NUM_CHANNELS consecutive data samples (e.g., an <em>RGBA</em> pixel).\n     * - Of the \\p NUM_CHANNELS specified, the function will only compute histograms\n     *   for the first \\p NUM_ACTIVE_CHANNELS (e.g., <em>RGB</em> histograms from <em>RGBA</em>\n     *   pixel samples).\n     * - The number of histogram bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n     * - For channel<sub><em>i</em></sub>, the range of values for all histogram bins\n     *   have the same width: (<tt>upper_level[i]</tt> - <tt>lower_level[i]</tt>) / (<tt> num_levels[i]</tt> - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of three 4-bin <em>RGB</em> histograms\n     * from a quad-channel sequence of <em>RGBA</em> pixels (8 bits per channel per pixel)\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples\n     * // and output histograms\n     * int            num_pixels;       // e.g., 5\n     * unsigned char  *d_samples;       // e.g., [(2, 6, 7, 5),(3, 0, 2, 1),(7, 0, 6, 2),\n     *                                  //        (0, 6, 7, 5),(3, 0, 2, 6)]\n     * unsigned int   *d_histogram[3];  // e.g., [[ -, -, -, -],[ -, -, -, -],[ -, -, -, -]];\n     * int            num_levels[3];    // e.g., {5, 5, 5};\n     * unsigned int   *d_levels[3];     // e.g., [ [0, 2, 4, 6, 8],\n     *                                  //         [0, 2, 4, 6, 8],\n     *                                  //         [0, 2, 4, 6, 8] ];\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::MultiHistogramRange<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_pixels);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::MultiHistogramRange<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_pixels);\n     *\n     * // d_histogram   <-- [ [1, 3, 0, 1],\n     * //                     [3, 0, 0, 2],\n     * //                     [0, 2, 0, 3] ]\n     *\n     * \\endcode\n     *\n     * \\tparam NUM_CHANNELS             Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n     * \\tparam NUM_ACTIVE_CHANNELS      <b>[inferred]</b> Number of channels actively being histogrammed\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        int                 NUM_CHANNELS,\n        int                 NUM_ACTIVE_CHANNELS,\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t MultiHistogramRange(\n        void*               d_temp_storage,                         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                              ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four <em>RGBA</em> 8-bit samples).\n        CounterT*           d_histogram[NUM_ACTIVE_CHANNELS],       ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histogram[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n        int                 num_levels[NUM_ACTIVE_CHANNELS],        ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n        LevelT*             d_levels[NUM_ACTIVE_CHANNELS],          ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_pixels,                             ///< [in] The number of multi-channel pixels (i.e., the length of \\p d_samples / NUM_CHANNELS)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n        return MultiHistogramRange<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram,\n            num_levels,\n            d_levels,\n            num_pixels,\n            1,\n            sizeof(SampleT) * NUM_CHANNELS * num_pixels,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes per-channel intensity histograms from a sequence of multi-channel \"pixel\" data samples using the specified bin boundary levels.\n     *\n     * \\par\n     * - The input is a sequence of <em>pixel</em> structures, where each pixel comprises\n     *   a record of \\p NUM_CHANNELS consecutive data samples (e.g., an <em>RGBA</em> pixel).\n     * - Of the \\p NUM_CHANNELS specified, the function will only compute histograms\n     *   for the first \\p NUM_ACTIVE_CHANNELS (e.g., <em>RGB</em> histograms from <em>RGBA</em>\n     *   pixel samples).\n     * - A two-dimensional <em>region of interest</em> within \\p d_samples can be specified\n     *   using the \\p num_row_samples, num_rows, and \\p row_stride_bytes parameters.\n     * - The row stride must be a whole multiple of the sample data type\n     *   size, i.e., <tt>(row_stride_bytes % sizeof(SampleT)) == 0</tt>.\n     * - The number of histogram bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n     * - For channel<sub><em>i</em></sub>, the range of values for all histogram bins\n     *   have the same width: (<tt>upper_level[i]</tt> - <tt>lower_level[i]</tt>) / (<tt> num_levels[i]</tt> - 1)\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the computation of three 4-bin <em>RGB</em> histograms from a 2x3 region of\n     * interest of within a flattened 2x4 array of quad-channel <em>RGBA</em> pixels (8 bits per channel per pixel).\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_histogram.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input samples\n     * // and output histograms\n     * int              num_row_pixels;     // e.g., 3\n     * int              num_rows;           // e.g., 2\n     * size_t           row_stride_bytes;   // e.g., 4 * sizeof(unsigned char) * NUM_CHANNELS\n     * unsigned char*   d_samples;          // e.g., [(2, 6, 7, 5),(3, 0, 2, 1),(1, 1, 1, 1),(-, -, -, -),\n     *                                      //        (7, 0, 6, 2),(0, 6, 7, 5),(3, 0, 2, 6),(-, -, -, -)]\n     * int*             d_histogram[3];     // e.g., [[ -, -, -, -],[ -, -, -, -],[ -, -, -, -]];\n     * int              num_levels[3];      // e.g., {5, 5, 5};\n     * unsigned int*    d_levels[3];        // e.g., [ [0, 2, 4, 6, 8],\n     *                                      //         [0, 2, 4, 6, 8],\n     *                                      //         [0, 2, 4, 6, 8] ];\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceHistogram::MultiHistogramRange<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_row_pixels, num_rows, row_stride_bytes);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Compute histograms\n     * cub::DeviceHistogram::MultiHistogramRange<4, 3>(d_temp_storage, temp_storage_bytes,\n     *     d_samples, d_histogram, num_levels, d_levels, num_row_pixels, num_rows, row_stride_bytes);\n     *\n     * // d_histogram   <-- [ [2, 3, 0, 1],\n     * //                     [3, 0, 0, 2],\n     * //                     [1, 2, 0, 3] ]\n     *\n     * \\endcode\n     *\n     * \\tparam NUM_CHANNELS             Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n     * \\tparam NUM_ACTIVE_CHANNELS      <b>[inferred]</b> Number of channels actively being histogrammed\n     * \\tparam SampleIteratorT          <b>[inferred]</b> Random-access input iterator type for reading input samples. \\iterator\n     * \\tparam CounterT                 <b>[inferred]</b> Integer type for histogram bin counters\n     * \\tparam LevelT                   <b>[inferred]</b> Type for specifying boundaries (levels)\n     * \\tparam OffsetT                  <b>[inferred]</b> Signed integer type for sequence offsets, list lengths, pointer differences, etc.  \\offset_size1\n     */\n    template <\n        int                 NUM_CHANNELS,\n        int                 NUM_ACTIVE_CHANNELS,\n        typename            SampleIteratorT,\n        typename            CounterT,\n        typename            LevelT,\n        typename            OffsetT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t MultiHistogramRange(\n        void*               d_temp_storage,                         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                              ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four <em>RGBA</em> 8-bit samples).\n        CounterT*           d_histogram[NUM_ACTIVE_CHANNELS],       ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histogram[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n        int                 num_levels[NUM_ACTIVE_CHANNELS],        ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n        LevelT*             d_levels[NUM_ACTIVE_CHANNELS],          ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_row_pixels,                         ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                               ///< [in] The number of rows in the region of interest\n        size_t              row_stride_bytes,                       ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        /// The sample value type of the input iterator\n        typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n        Int2Type<sizeof(SampleT) == 1> is_byte_sample;\n\n        if ((sizeof(OffsetT) > sizeof(int)) &&\n            ((unsigned long long) (num_rows * row_stride_bytes) < (unsigned long long) std::numeric_limits<int>::max()))\n        {\n            // Down-convert OffsetT data type\n            return DipatchHistogram<NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, LevelT, int>::DispatchRange(\n                d_temp_storage, temp_storage_bytes, d_samples, d_histogram, num_levels, d_levels,\n                (int) num_row_pixels, (int) num_rows, (int) (row_stride_bytes / sizeof(SampleT)),\n                stream, debug_synchronous, is_byte_sample);\n        }\n\n        return DipatchHistogram<NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, LevelT, OffsetT>::DispatchRange(\n            d_temp_storage, temp_storage_bytes, d_samples, d_histogram, num_levels, d_levels,\n            num_row_pixels, num_rows, (OffsetT) (row_stride_bytes / sizeof(SampleT)),\n            stream, debug_synchronous, is_byte_sample);\n    }\n\n\n\n    //@}  end member group\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_partition.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DevicePartition provides device-wide, parallel operations for partitioning sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_select_if.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DevicePartition provides device-wide, parallel operations for partitioning sequences of data items residing within device-accessible memory. ![](partition_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * These operations apply a selection criterion to construct a partitioned output sequence from items selected/unselected from\n * a specified input sequence.\n *\n * \\par Usage Considerations\n * \\cdp_class{DevicePartition}\n *\n * \\par Performance\n * \\linear_performance{partition}\n *\n * \\par\n * The following chart illustrates DevicePartition::If\n * performance across different CUDA architectures for \\p int32 items,\n * where 50% of the items are randomly selected for the first partition.\n * \\plots_below\n *\n * \\image html partition_if_int32_50_percent.png\n *\n */\nstruct DevicePartition\n{\n    /**\n     * \\brief Uses the \\p d_flags sequence to split the corresponding items from \\p d_in into a partitioned sequence \\p d_out.  The total number of items copied into the first partition is written to \\p d_num_selected_out. ![](partition_flags_logo.png)\n     *\n     * \\par\n     * - The value type of \\p d_flags must be castable to \\p bool (e.g., \\p bool, \\p char, \\p int, etc.).\n     * - Copies of the selected items are compacted into \\p d_out and maintain their original\n     *   relative ordering, however copies of the unselected items are compacted into the\n     *   rear of \\p d_out in reverse order.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the compaction of items selected from an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>       // or equivalently <cub/device/device_partition.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input, flags, and output\n     * int  num_items;              // e.g., 8\n     * int  *d_in;                  // e.g., [1, 2, 3, 4, 5, 6, 7, 8]\n     * char *d_flags;               // e.g., [1, 0, 0, 1, 0, 1, 1, 0]\n     * int  *d_out;                 // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int  *d_num_selected_out;    // e.g., [ ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DevicePartition::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run selection\n     * cub::DevicePartition::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items);\n     *\n     * // d_out                 <-- [1, 4, 6, 7, 8, 5, 3, 2]\n     * // d_num_selected_out    <-- [4]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam FlagIterator         <b>[inferred]</b> Random-access input iterator type for reading selection flags \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Random-access output iterator type for writing output items \\iterator\n     * \\tparam NumSelectedIteratorT  <b>[inferred]</b> Output iterator type for recording the number of items selected \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    FlagIterator,\n        typename                    OutputIteratorT,\n        typename                    NumSelectedIteratorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Flagged(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        FlagIterator                d_flags,                        ///< [in] Pointer to the input sequence of selection flags\n        OutputIteratorT             d_out,                          ///< [out] Pointer to the output sequence of partitioned data items\n        NumSelectedIteratorT        d_num_selected_out,             ///< [out] Pointer to the output total number of items selected (i.e., the offset of the unselected partition)\n        int                         num_items,                      ///< [in] Total number of items to select from\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int                     OffsetT;         // Signed integer type for global offsets\n        typedef NullType                SelectOp;       // Selection op (not used)\n        typedef NullType                EqualityOp;     // Equality operator (not used)\n\n        return DispatchSelectIf<InputIteratorT, FlagIterator, OutputIteratorT, NumSelectedIteratorT, SelectOp, EqualityOp, OffsetT, true>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_flags,\n            d_out,\n            d_num_selected_out,\n            SelectOp(),\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Uses the \\p select_op functor to split the corresponding items from \\p d_in into a partitioned sequence \\p d_out.  The total number of items copied into the first partition is written to \\p d_num_selected_out. ![](partition_logo.png)\n     *\n     * \\par\n     * - Copies of the selected items are compacted into \\p d_out and maintain their original\n     *   relative ordering, however copies of the unselected items are compacted into the\n     *   rear of \\p d_out in reverse order.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated partition-if performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.  Items are\n     * selected for the first partition with 50% probability.\n     *\n     * \\image html partition_if_int32_50_percent.png\n     * \\image html partition_if_int64_50_percent.png\n     *\n     * \\par\n     * The following charts are similar, but 5% selection probability for the first partition:\n     *\n     * \\image html partition_if_int32_5_percent.png\n     * \\image html partition_if_int64_5_percent.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the compaction of items selected from an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_partition.cuh>\n     *\n     * // Functor type for selecting values less than some criteria\n     * struct LessThan\n     * {\n     *     int compare;\n     *\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     LessThan(int compare) : compare(compare) {}\n     *\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     bool operator()(const int &a) const {\n     *         return (a < compare);\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int      num_items;              // e.g., 8\n     * int      *d_in;                  // e.g., [0, 2, 3, 9, 5, 2, 81, 8]\n     * int      *d_out;                 // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int      *d_num_selected_out;    // e.g., [ ]\n     * LessThan select_op(7);\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run selection\n     * cub::DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op);\n     *\n     * // d_out                 <-- [0, 2, 3, 5, 2, 8, 81, 9]\n     * // d_num_selected_out    <-- [5]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Random-access output iterator type for writing output items \\iterator\n     * \\tparam NumSelectedIteratorT  <b>[inferred]</b> Output iterator type for recording the number of items selected \\iterator\n     * \\tparam SelectOp             <b>[inferred]</b> Selection functor type having member <tt>bool operator()(const T &a)</tt>\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT,\n        typename                    NumSelectedIteratorT,\n        typename                    SelectOp>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t If(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                          ///< [out] Pointer to the output sequence of partitioned data items\n        NumSelectedIteratorT        d_num_selected_out,             ///< [out] Pointer to the output total number of items selected (i.e., the offset of the unselected partition)\n        int                         num_items,                      ///< [in] Total number of items to select from\n        SelectOp                    select_op,                      ///< [in] Unary selection operator\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int                     OffsetT;         // Signed integer type for global offsets\n        typedef NullType*               FlagIterator;   // FlagT iterator type (not used)\n        typedef NullType                EqualityOp;     // Equality operator (not used)\n\n        return DispatchSelectIf<InputIteratorT, FlagIterator, OutputIteratorT, NumSelectedIteratorT, SelectOp, EqualityOp, OffsetT, true>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            NULL,\n            d_out,\n            d_num_selected_out,\n            select_op,\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n};\n\n/**\n * \\example example_device_partition_flagged.cu\n * \\example example_device_partition_if.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_radix_sort.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceRadixSort provides device-wide, parallel operations for computing a radix sort across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_radix_sort.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceRadixSort provides device-wide, parallel operations for computing a radix sort across a sequence of data items residing within device-accessible memory. ![](sorting_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * The [<em>radix sorting method</em>](http://en.wikipedia.org/wiki/Radix_sort) arranges\n * items into ascending (or descending) order.  The algorithm relies upon a positional representation for\n * keys, i.e., each key is comprised of an ordered sequence of symbols (e.g., digits,\n * characters, etc.) specified from least-significant to most-significant.  For a\n * given input sequence of keys and a set of rules specifying a total ordering\n * of the symbolic alphabet, the radix sorting method produces a lexicographic\n * ordering of those keys.\n *\n * \\par\n * DeviceRadixSort can sort all of the built-in C++ numeric primitive types, e.g.:\n * <tt>unsigned char</tt>, \\p int, \\p double, etc.  Although the direct radix sorting\n * method can only be applied to unsigned integral types, DeviceRadixSort\n * is able to sort signed and floating-point types via simple bit-wise transformations\n * that ensure lexicographic key ordering.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceRadixSort}\n *\n * \\par Performance\n * \\linear_performance{radix sort} The following chart illustrates DeviceRadixSort::SortKeys\n * performance across different CUDA architectures for uniform-random \\p uint32 keys.\n * \\plots_below\n *\n * \\image html lsb_radix_sort_int32_keys.png\n *\n */\nstruct DeviceRadixSort\n{\n\n    /******************************************************************//**\n     * \\name KeyT-value pairs\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Sorts key-value pairs into ascending order. (~<em>2N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated sorting performance across different\n     * CUDA architectures for uniform-random <tt>uint32,uint32</tt> and\n     * <tt>uint64,uint64</tt> pairs, respectively.\n     *\n     * \\image html lsb_radix_sort_int32_pairs.png\n     * \\image html lsb_radix_sort_int64_pairs.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [        ...        ]\n     * int  *d_values_in;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_values_out;      // e.g., [        ...        ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out, num_items);\n     *\n     * // d_keys_out            <-- [0, 3, 5, 6, 7, 8, 9]\n     * // d_values_out          <-- [5, 4, 3, 1, 2, 0, 6]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     * \\tparam ValueT    <b>[inferred]</b> ValueT type\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairs(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] Pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] Pointer to the sorted output sequence of key data\n        const ValueT        *d_values_in,                           ///< [in] Pointer to the corresponding input sequence of associated value items\n        ValueT              *d_values_out,                          ///< [out] Pointer to the correspondingly-reordered output sequence of associated value items\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>       d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<ValueT>     d_values(const_cast<ValueT*>(d_values_in), d_values_out);\n\n        return DispatchRadixSort<false, KeyT, ValueT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts key-value pairs into ascending order. (~<em>N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers and a corresponding\n     *   pair of associated value buffers.  Each pair is managed by a DoubleBuffer\n     *   structure that indicates which of the two buffers is \"current\" (and thus\n     *   contains the input data to be sorted).\n     * - The contents of both buffers within each pair may be altered by the sorting\n     *   operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within each DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated sorting performance across different\n     * CUDA architectures for uniform-random <tt>uint32,uint32</tt> and\n     * <tt>uint64,uint64</tt> pairs, respectively.\n     *\n     * \\image html lsb_radix_sort_int32_pairs.png\n     * \\image html lsb_radix_sort_int64_pairs.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [        ...        ]\n     * int  *d_value_buf;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_value_alt_buf;   // e.g., [        ...        ]\n     * ...\n     *\n     * // Create a set of DoubleBuffers to wrap pairs of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     * cub::DoubleBuffer<int> d_values(d_value_buf, d_value_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items);\n     *\n     * // d_keys.Current()      <-- [0, 3, 5, 6, 7, 8, 9]\n     * // d_values.Current()    <-- [5, 4, 3, 1, 2, 0, 6]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     * \\tparam ValueT    <b>[inferred]</b> ValueT type\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairs(\n        void                    *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,                              ///< [in,out] Double-buffer of values whose \"current\" device-accessible buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        int                     num_items,                              ///< [in] Number of items to sort\n        int                     begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                     end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchRadixSort<false, KeyT, ValueT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts key-value pairs into descending order. (~<em>2N</em> auxiliary storage required).\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * Performance is similar to DeviceRadixSort::SortPairs.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [        ...        ]\n     * int  *d_values_in;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_values_out;      // e.g., [        ...        ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out, num_items);\n     *\n     * // d_keys_out            <-- [9, 8, 7, 6, 5, 3, 0]\n     * // d_values_out          <-- [6, 0, 2, 1, 3, 4, 5]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     * \\tparam ValueT    <b>[inferred]</b> ValueT type\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairsDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] Pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] Pointer to the sorted output sequence of key data\n        const ValueT        *d_values_in,                           ///< [in] Pointer to the corresponding input sequence of associated value items\n        ValueT              *d_values_out,                          ///< [out] Pointer to the correspondingly-reordered output sequence of associated value items\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>       d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<ValueT>     d_values(const_cast<ValueT*>(d_values_in), d_values_out);\n\n        return DispatchRadixSort<true, KeyT, ValueT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts key-value pairs into descending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers and a corresponding\n     *   pair of associated value buffers.  Each pair is managed by a DoubleBuffer\n     *   structure that indicates which of the two buffers is \"current\" (and thus\n     *   contains the input data to be sorted).\n     * - The contents of both buffers within each pair may be altered by the sorting\n     *   operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within each DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * Performance is similar to DeviceRadixSort::SortPairs.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [        ...        ]\n     * int  *d_value_buf;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_value_alt_buf;   // e.g., [        ...        ]\n     * ...\n     *\n     * // Create a set of DoubleBuffers to wrap pairs of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     * cub::DoubleBuffer<int> d_values(d_value_buf, d_value_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items);\n     *\n     * // d_keys.Current()      <-- [9, 8, 7, 6, 5, 3, 0]\n     * // d_values.Current()    <-- [6, 0, 2, 1, 3, 4, 5]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     * \\tparam ValueT    <b>[inferred]</b> ValueT type\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairsDescending(\n        void                    *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,                              ///< [in,out] Double-buffer of values whose \"current\" device-accessible buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        int                     num_items,                              ///< [in] Number of items to sort\n        int                     begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                     end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchRadixSort<true, KeyT, ValueT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Keys-only\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Sorts keys into ascending order. (~<em>2N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated sorting performance across different\n     * CUDA architectures for uniform-random \\p uint32 and \\p uint64 keys, respectively.\n     *\n     * \\image html lsb_radix_sort_int32_keys.png\n     * \\image html lsb_radix_sort_int64_keys.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [        ...        ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, num_items);\n     *\n     * // d_keys_out            <-- [0, 3, 5, 6, 7, 8, 9]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     */\n    template <typename KeyT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeys(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] Pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] Pointer to the sorted output sequence of key data\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<KeyT>      d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<NullType>  d_values;\n\n        return DispatchRadixSort<false, KeyT, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts keys into ascending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers managed by a\n     *   DoubleBuffer structure that indicates which of the two buffers is\n     *   \"current\" (and thus contains the input data to be sorted).\n     * - The contents of both buffers may be altered by the sorting operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within the DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated sorting performance across different\n     * CUDA architectures for uniform-random \\p uint32 and \\p uint64 keys, respectively.\n     *\n     * \\image html lsb_radix_sort_int32_keys.png\n     * \\image html lsb_radix_sort_int64_keys.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [        ...        ]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys, num_items);\n     *\n     * // d_keys.Current()      <-- [0, 3, 5, 6, 7, 8, 9]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     */\n    template <typename KeyT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeys(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>  &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<NullType> d_values;\n\n        return DispatchRadixSort<false, KeyT, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n    /**\n     * \\brief Sorts keys into descending order. (~<em>2N</em> auxiliary storage required).\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * Performance is similar to DeviceRadixSort::SortKeys.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [        ...        ]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, num_items);\n     *\n     * // d_keys_out            <-- [9, 8, 7, 6, 5, 3, 0]s\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     */\n    template <typename KeyT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeysDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] Pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] Pointer to the sorted output sequence of key data\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>      d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<NullType>  d_values;\n\n        return DispatchRadixSort<true, KeyT, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts keys into descending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers managed by a\n     *   DoubleBuffer structure that indicates which of the two buffers is\n     *   \"current\" (and thus contains the input data to be sorted).\n     * - The contents of both buffers may be altered by the sorting operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within the DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * Performance is similar to DeviceRadixSort::SortKeys.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sorting of a device vector of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [        ...        ]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys, num_items);\n     *\n     * // d_keys.Current()      <-- [9, 8, 7, 6, 5, 3, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT      <b>[inferred]</b> KeyT type\n     */\n    template <typename KeyT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeysDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>  &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        int                 num_items,                              ///< [in] Number of items to sort\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<NullType> d_values;\n\n        return DispatchRadixSort<true, KeyT, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    //@}  end member group\n\n\n};\n\n/**\n * \\example example_device_radix_sort.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_reduce.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceReduce provides device-wide, parallel operations for computing a reduction across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n#include <limits>\n\n#include \"../iterator/arg_index_input_iterator.cuh\"\n#include \"dispatch/dispatch_reduce.cuh\"\n#include \"dispatch/dispatch_reduce_by_key.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceReduce provides device-wide, parallel operations for computing a reduction across a sequence of data items residing within device-accessible memory. ![](reduce_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * A <a href=\"http://en.wikipedia.org/wiki/Reduce_(higher-order_function)\"><em>reduction</em></a> (or <em>fold</em>)\n * uses a binary combining operator to compute a single aggregate from a sequence of input elements.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceReduce}\n *\n * \\par Performance\n * \\linear_performance{reduction, reduce-by-key, and run-length encode}\n *\n * \\par\n * The following chart illustrates DeviceReduce::Sum\n * performance across different CUDA architectures for \\p int32 keys.\n *\n * \\image html reduce_int32.png\n *\n * \\par\n * The following chart illustrates DeviceReduce::ReduceByKey (summation)\n * performance across different CUDA architectures for \\p fp32\n * values.  Segments are identified by \\p int32 keys, and have lengths uniformly sampled from [1,1000].\n *\n * \\image html reduce_by_key_fp32_len_500.png\n *\n * \\par\n * \\plots_below\n *\n */\nstruct DeviceReduce\n{\n    /**\n     * \\brief Computes a device-wide reduction using the specified binary \\p reduction_op functor and initial value \\p init.\n     *\n     * \\par\n     * - Does not support binary reduction operators that are non-commutative.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a user-defined min-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // CustomMin functor\n     * struct CustomMin\n     * {\n     *     template <typename T>\n     *     __device__ __forceinline__\n     *     T operator()(const T &a, const T &b) const {\n     *         return (b < a) ? b : a;\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;  // e.g., 7\n     * int          *d_in;      // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int          *d_out;     // e.g., [-]\n     * CustomMin    min_op;\n     * int          init;       // e.g., INT_MAX\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::Reduce(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, min_op, init);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run reduction\n     * cub::DeviceReduce::Reduce(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, min_op, init);\n     *\n     * // d_out <-- [0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     * \\tparam ReductionOpT         <b>[inferred]</b> Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt> \n     * \\tparam T                    <b>[inferred]</b> Data element type that is convertible to the \\p value type of \\p InputIteratorT\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT,\n        typename                    ReductionOpT,\n        typename                    T>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Reduce(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        ReductionOpT                reduction_op,                       ///< [in] Binary reduction functor\n        T                           init,                               ///< [in] Initial value of the reduction\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchReduce<InputIteratorT, OutputIteratorT, OffsetT, ReductionOpT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_items,\n            reduction_op,\n            init,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide sum using the addition (\\p +) operator.\n     *\n     * \\par\n     * - Uses \\p 0 as the initial value of the reduction.\n     * - Does not support \\p + operators that are non-commutative..\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated sum-reduction performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.\n     *\n     * \\image html reduce_int32.png\n     * \\image html reduce_int64.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sum-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;      // e.g., 7\n     * int  *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_out;         // e.g., [-]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sum-reduction\n     * cub::DeviceReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // d_out <-- [38]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Sum(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The output value type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n        return DispatchReduce<InputIteratorT, OutputIteratorT, OffsetT, cub::Sum>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_items,\n            cub::Sum(),\n            OutputT(),            // zero-initialize\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide minimum using the less-than ('<') operator.\n     *\n     * \\par\n     * - Uses <tt>std::numeric_limits<T>::max()</tt> as the initial value of the reduction.\n     * - Does not support \\p < operators that are non-commutative.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the min-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;      // e.g., 7\n     * int  *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_out;         // e.g., [-]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::Min(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run min-reduction\n     * cub::DeviceReduce::Min(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // d_out <-- [0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Min(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input value type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n        return DispatchReduce<InputIteratorT, OutputIteratorT, OffsetT, cub::Min>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_items,\n            cub::Min(),\n            Traits<InputT>::Max(), // replace with std::numeric_limits<T>::max() when C++11 support is more prevalent\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Finds the first device-wide minimum using the less-than ('<') operator, also returning the index of that item.\n     *\n     * \\par\n     * - The output value type of \\p d_out is cub::KeyValuePair <tt><int, T></tt> (assuming the value type of \\p d_in is \\p T)\n     *   - The minimum is written to <tt>d_out.value</tt> and its offset in the input array is written to <tt>d_out.key</tt>.\n     *   - The <tt>{1, std::numeric_limits<T>::max()}</tt> tuple is produced for zero-length inputs\n     * - Does not support \\p < operators that are non-commutative.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the argmin-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int                      num_items;      // e.g., 7\n     * int                      *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * KeyValuePair<int, int>   *d_out;         // e.g., [{-,-}]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::ArgMin(d_temp_storage, temp_storage_bytes, d_in, d_argmin, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run argmin-reduction\n     * cub::DeviceReduce::ArgMin(d_temp_storage, temp_storage_bytes, d_in, d_argmin, num_items);\n     *\n     * // d_out <-- [{5, 0}]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items (of some type \\p T) \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate (having value type <tt>cub::KeyValuePair<int, T></tt>) \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ArgMin(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputValueT;\n\n        // The output tuple type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            KeyValuePair<OffsetT, InputValueT>,                                                                 // ... then the key value pair OffsetT + InputValueT\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputTupleT;                     // ... else the output iterator's value type\n\n        // The output value type\n        typedef typename OutputTupleT::Value OutputValueT;\n\n        // Wrapped input iterator to produce index-value <OffsetT, InputT> tuples\n        typedef ArgIndexInputIterator<InputIteratorT, OffsetT, OutputValueT> ArgIndexInputIteratorT;\n        ArgIndexInputIteratorT d_indexed_in(d_in);\n\n        // Initial value\n        OutputTupleT initial_value(1, Traits<InputValueT>::Max());   // replace with std::numeric_limits<T>::max() when C++11 support is more prevalent\n\n        return DispatchReduce<ArgIndexInputIteratorT, OutputIteratorT, OffsetT, cub::ArgMin>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_indexed_in,\n            d_out,\n            num_items,\n            cub::ArgMin(),\n            initial_value,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide maximum using the greater-than ('>') operator.\n     *\n     * \\par\n     * - Uses <tt>std::numeric_limits<T>::lowest()</tt> as the initial value of the reduction.\n     * - Does not support \\p > operators that are non-commutative.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the max-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;      // e.g., 7\n     * int  *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_out;         // e.g., [-]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::Max(d_temp_storage, temp_storage_bytes, d_in, d_max, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run max-reduction\n     * cub::DeviceReduce::Max(d_temp_storage, temp_storage_bytes, d_in, d_max, num_items);\n     *\n     * // d_out <-- [9]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Max(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input value type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n        return DispatchReduce<InputIteratorT, OutputIteratorT, OffsetT, cub::Max>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_items,\n            cub::Max(),\n            Traits<InputT>::Lowest(),    // replace with std::numeric_limits<T>::lowest() when C++11 support is more prevalent\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Finds the first device-wide maximum using the greater-than ('>') operator, also returning the index of that item\n     *\n     * \\par\n     * - The output value type of \\p d_out is cub::KeyValuePair <tt><int, T></tt> (assuming the value type of \\p d_in is \\p T)\n     *   - The maximum is written to <tt>d_out.value</tt> and its offset in the input array is written to <tt>d_out.key</tt>.\n     *   - The <tt>{1, std::numeric_limits<T>::lowest()}</tt> tuple is produced for zero-length inputs\n     * - Does not support \\p > operators that are non-commutative.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the argmax-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_reduce.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int                      num_items;      // e.g., 7\n     * int                      *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * KeyValuePair<int, int>   *d_out;         // e.g., [{-,-}]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::ArgMax(d_temp_storage, temp_storage_bytes, d_in, d_argmax, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run argmax-reduction\n     * cub::DeviceReduce::ArgMax(d_temp_storage, temp_storage_bytes, d_in, d_argmax, num_items);\n     *\n     * // d_out <-- [{6, 9}]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items (of some type \\p T) \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate (having value type <tt>cub::KeyValuePair<int, T></tt>) \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ArgMax(\n        void                        *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                              ///< [out] Pointer to the output aggregate\n        int                         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputValueT;\n\n        // The output tuple type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            KeyValuePair<OffsetT, InputValueT>,                                                                 // ... then the key value pair OffsetT + InputValueT\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputTupleT;                     // ... else the output iterator's value type\n\n        // The output value type\n        typedef typename OutputTupleT::Value OutputValueT;\n\n        // Wrapped input iterator to produce index-value <OffsetT, InputT> tuples\n        typedef ArgIndexInputIterator<InputIteratorT, OffsetT, OutputValueT> ArgIndexInputIteratorT;\n        ArgIndexInputIteratorT d_indexed_in(d_in);\n\n        // Initial value\n        OutputTupleT initial_value(1, Traits<InputValueT>::Lowest());     // replace with std::numeric_limits<T>::lowest() when C++11 support is more prevalent\n\n        return DispatchReduce<ArgIndexInputIteratorT, OutputIteratorT, OffsetT, cub::ArgMax>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_indexed_in,\n            d_out,\n            num_items,\n            cub::ArgMax(),\n            initial_value,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Reduces segments of values, where segments are demarcated by corresponding runs of identical keys.\n     *\n     * \\par\n     * This operation computes segmented reductions within \\p d_values_in using\n     * the specified binary \\p reduction_op functor.  The segments are identified by\n     * \"runs\" of corresponding keys in \\p d_keys_in, where runs are maximal ranges of\n     * consecutive, identical keys.  For the <em>i</em><sup>th</sup> run encountered,\n     * the first key of the run and the corresponding value aggregate of that run are\n     * written to <tt>d_unique_out[<em>i</em>]</tt> and <tt>d_aggregates_out[<em>i</em>]</tt>,\n     * respectively. The total number of runs encountered is written to \\p d_num_runs_out.\n     *\n     * \\par\n     * - The <tt>==</tt> equality operator is used to determine whether keys are equivalent\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following chart illustrates reduction-by-key (sum) performance across\n     * different CUDA architectures for \\p fp32 and \\p fp64 values, respectively.  Segments\n     * are identified by \\p int32 keys, and have lengths uniformly sampled from [1,1000].\n     *\n     * \\image html reduce_by_key_fp32_len_500.png\n     * \\image html reduce_by_key_fp64_len_500.png\n     *\n     * \\par\n     * The following charts are similar, but with segment lengths uniformly sampled from [1,10]:\n     *\n     * \\image html reduce_by_key_fp32_len_5.png\n     * \\image html reduce_by_key_fp64_len_5.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the segmented reduction of \\p int values grouped\n     * by runs of associated \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_reduce.cuh>\n     *\n     * // CustomMin functor\n     * struct CustomMin\n     * {\n     *     template <typename T>\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     T operator()(const T &a, const T &b) const {\n     *         return (b < a) ? b : a;\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;          // e.g., 8\n     * int          *d_keys_in;         // e.g., [0, 2, 2, 9, 5, 5, 5, 8]\n     * int          *d_values_in;       // e.g., [0, 7, 1, 6, 2, 5, 3, 4]\n     * int          *d_unique_out;      // e.g., [-, -, -, -, -, -, -, -]\n     * int          *d_aggregates_out;  // e.g., [-, -, -, -, -, -, -, -]\n     * int          *d_num_runs_out;    // e.g., [-]\n     * CustomMin    reduction_op;\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceReduce::ReduceByKey(d_temp_storage, temp_storage_bytes, d_keys_in, d_unique_out, d_values_in, d_aggregates_out, d_num_runs_out, reduction_op, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run reduce-by-key\n     * cub::DeviceReduce::ReduceByKey(d_temp_storage, temp_storage_bytes, d_keys_in, d_unique_out, d_values_in, d_aggregates_out, d_num_runs_out, reduction_op, num_items);\n     *\n     * // d_unique_out      <-- [0, 2, 9, 5, 8]\n     * // d_aggregates_out  <-- [0, 1, 6, 2, 4]\n     * // d_num_runs_out    <-- [5]\n     *\n     * \\endcode\n     *\n     * \\tparam KeysInputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input keys \\iterator\n     * \\tparam UniqueOutputIteratorT    <b>[inferred]</b> Random-access output iterator type for writing unique output keys \\iterator\n     * \\tparam ValuesInputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input values \\iterator\n     * \\tparam AggregatesOutputIterator <b>[inferred]</b> Random-access output iterator type for writing output value aggregates \\iterator\n     * \\tparam NumRunsOutputIteratorT   <b>[inferred]</b> Output iterator type for recording the number of runs encountered \\iterator\n     * \\tparam ReductionOpT              <b>[inferred]</b> Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt> \n     */\n    template <\n        typename                    KeysInputIteratorT,\n        typename                    UniqueOutputIteratorT,\n        typename                    ValuesInputIteratorT,\n        typename                    AggregatesOutputIteratorT,\n        typename                    NumRunsOutputIteratorT,\n        typename                    ReductionOpT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t ReduceByKey(\n        void                        *d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        KeysInputIteratorT          d_keys_in,                      ///< [in] Pointer to the input sequence of keys\n        UniqueOutputIteratorT       d_unique_out,                   ///< [out] Pointer to the output sequence of unique keys (one key per run)\n        ValuesInputIteratorT        d_values_in,                    ///< [in] Pointer to the input sequence of corresponding values\n        AggregatesOutputIteratorT   d_aggregates_out,               ///< [out] Pointer to the output sequence of value aggregates (one aggregate per run)\n        NumRunsOutputIteratorT      d_num_runs_out,                 ///< [out] Pointer to total number of runs encountered (i.e., the length of d_unique_out)\n        ReductionOpT                reduction_op,                   ///< [in] Binary reduction functor\n        int                         num_items,                      ///< [in] Total number of associated key+value pairs (i.e., the length of \\p d_in_keys and \\p d_in_values)\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // FlagT iterator type (not used)\n\n        // Selection op (not used)\n\n        // Default == operator\n        typedef Equality EqualityOp;\n\n        return DispatchReduceByKey<KeysInputIteratorT, UniqueOutputIteratorT, ValuesInputIteratorT, AggregatesOutputIteratorT, NumRunsOutputIteratorT, EqualityOp, ReductionOpT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys_in,\n            d_unique_out,\n            d_values_in,\n            d_aggregates_out,\n            d_num_runs_out,\n            EqualityOp(),\n            reduction_op,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n};\n\n/**\n * \\example example_device_reduce.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_run_length_encode.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceRunLengthEncode provides device-wide, parallel operations for computing a run-length encoding across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_rle.cuh\"\n#include \"dispatch/dispatch_reduce_by_key.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceRunLengthEncode provides device-wide, parallel operations for demarcating \"runs\" of same-valued items within a sequence residing within device-accessible memory. ![](run_length_encode_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * A <a href=\"http://en.wikipedia.org/wiki/Run-length_encoding\"><em>run-length encoding</em></a>\n * computes a simple compressed representation of a sequence of input elements such that each\n * maximal \"run\" of consecutive same-valued data items is encoded as a single data value along with a\n * count of the elements in that run.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceRunLengthEncode}\n *\n * \\par Performance\n * \\linear_performance{run-length encode}\n *\n * \\par\n * The following chart illustrates DeviceRunLengthEncode::RunLengthEncode performance across\n * different CUDA architectures for \\p int32 items.\n * Segments have lengths uniformly sampled from [1,1000].\n *\n * \\image html rle_int32_len_500.png\n *\n * \\par\n * \\plots_below\n *\n */\nstruct DeviceRunLengthEncode\n{\n\n    /**\n     * \\brief Computes a run-length encoding of the sequence \\p d_in.\n     *\n     * \\par\n     * - For the <em>i</em><sup>th</sup> run encountered, the first key of the run and its length are written to\n     *   <tt>d_unique_out[<em>i</em>]</tt> and <tt>d_counts_out[<em>i</em>]</tt>,\n     *   respectively.\n     * - The total number of runs encountered is written to \\p d_num_runs_out.\n     * - The <tt>==</tt> equality operator is used to determine whether values are equivalent\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated encode performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.  Segments have\n     * lengths uniformly sampled from [1,1000].\n     *\n     * \\image html rle_int32_len_500.png\n     * \\image html rle_int64_len_500.png\n     *\n     * \\par\n     * The following charts are similar, but with segment lengths uniformly sampled from [1,10]:\n     *\n     * \\image html rle_int32_len_5.png\n     * \\image html rle_int64_len_5.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the run-length encoding of a sequence of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_run_length_encode.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;          // e.g., 8\n     * int          *d_in;              // e.g., [0, 2, 2, 9, 5, 5, 5, 8]\n     * int          *d_unique_out;      // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int          *d_counts_out;      // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int          *d_num_runs_out;    // e.g., [ ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRunLengthEncode::Encode(d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_counts_out, d_num_runs_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run encoding\n     * cub::DeviceRunLengthEncode::Encode(d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_counts_out, d_num_runs_out, num_items);\n     *\n     * // d_unique_out      <-- [0, 2, 9, 5, 8]\n     * // d_counts_out      <-- [1, 2, 1, 3, 1]\n     * // d_num_runs_out    <-- [5]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT           <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam UniqueOutputIteratorT    <b>[inferred]</b> Random-access output iterator type for writing unique output items \\iterator\n     * \\tparam LengthsOutputIteratorT   <b>[inferred]</b> Random-access output iterator type for writing output counts \\iterator\n     * \\tparam NumRunsOutputIteratorT   <b>[inferred]</b> Output iterator type for recording the number of runs encountered \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    UniqueOutputIteratorT,\n        typename                    LengthsOutputIteratorT,\n        typename                    NumRunsOutputIteratorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Encode(\n        void*                       d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of keys\n        UniqueOutputIteratorT       d_unique_out,                   ///< [out] Pointer to the output sequence of unique keys (one key per run)\n        LengthsOutputIteratorT      d_counts_out,                   ///< [out] Pointer to the output sequence of run-lengths (one count per run)\n        NumRunsOutputIteratorT      d_num_runs_out,                     ///< [out] Pointer to total number of runs\n        int                         num_items,                      ///< [in] Total number of associated key+value pairs (i.e., the length of \\p d_in_keys and \\p d_in_values)\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int         OffsetT;                    // Signed integer type for global offsets\n        typedef NullType*   FlagIterator;               // FlagT iterator type (not used)\n        typedef NullType    SelectOp;                   // Selection op (not used)\n        typedef Equality    EqualityOp;                 // Default == operator\n        typedef cub::Sum    ReductionOp;                // Value reduction operator\n\n        // The lengths output value type\n        typedef typename If<(Equals<typename std::iterator_traits<LengthsOutputIteratorT>::value_type, void>::VALUE),   // LengthT =  (if output iterator's value type is void) ?\n            OffsetT,                                                                                                    // ... then the OffsetT type,\n            typename std::iterator_traits<LengthsOutputIteratorT>::value_type>::Type LengthT;                           // ... else the output iterator's value type\n\n        // Generator type for providing 1s values for run-length reduction\n        typedef ConstantInputIterator<LengthT, OffsetT> LengthsInputIteratorT;\n\n        return DispatchReduceByKey<InputIteratorT, UniqueOutputIteratorT, LengthsInputIteratorT, LengthsOutputIteratorT, NumRunsOutputIteratorT, EqualityOp, ReductionOp, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_unique_out,\n            LengthsInputIteratorT((LengthT) 1),\n            d_counts_out,\n            d_num_runs_out,\n            EqualityOp(),\n            ReductionOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Enumerates the starting offsets and lengths of all non-trivial runs (of length > 1) of same-valued keys in the sequence \\p d_in.\n     *\n     * \\par\n     * - For the <em>i</em><sup>th</sup> non-trivial run, the run's starting offset\n     *   and its length are written to <tt>d_offsets_out[<em>i</em>]</tt> and\n     *   <tt>d_lengths_out[<em>i</em>]</tt>, respectively.\n     * - The total number of runs encountered is written to \\p d_num_runs_out.\n     * - The <tt>==</tt> equality operator is used to determine whether values are equivalent\n     * - \\devicestorage\n     *\n     * \\par Performance\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the identification of non-trivial runs within a sequence of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_run_length_encode.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;          // e.g., 8\n     * int          *d_in;              // e.g., [0, 2, 2, 9, 5, 5, 5, 8]\n     * int          *d_offsets_out;     // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int          *d_lengths_out;     // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int          *d_num_runs_out;    // e.g., [ ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceRunLengthEncode::NonTrivialRuns(d_temp_storage, temp_storage_bytes, d_in, d_offsets_out, d_lengths_out, d_num_runs_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run encoding\n     * cub::DeviceRunLengthEncode::NonTrivialRuns(d_temp_storage, temp_storage_bytes, d_in, d_offsets_out, d_lengths_out, d_num_runs_out, num_items);\n     *\n     * // d_offsets_out         <-- [1, 4]\n     * // d_lengths_out         <-- [2, 3]\n     * // d_num_runs_out        <-- [2]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT           <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OffsetsOutputIteratorT   <b>[inferred]</b> Random-access output iterator type for writing run-offset values \\iterator\n     * \\tparam LengthsOutputIteratorT   <b>[inferred]</b> Random-access output iterator type for writing run-length values \\iterator\n     * \\tparam NumRunsOutputIteratorT   <b>[inferred]</b> Output iterator type for recording the number of runs encountered \\iterator\n     */\n    template <\n        typename                InputIteratorT,\n        typename                OffsetsOutputIteratorT,\n        typename                LengthsOutputIteratorT,\n        typename                NumRunsOutputIteratorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t NonTrivialRuns(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT          d_in,                           ///< [in] Pointer to input sequence of data items\n        OffsetsOutputIteratorT  d_offsets_out,                  ///< [out] Pointer to output sequence of run-offsets (one offset per non-trivial run)\n        LengthsOutputIteratorT  d_lengths_out,                  ///< [out] Pointer to output sequence of run-lengths (one count per non-trivial run)\n        NumRunsOutputIteratorT  d_num_runs_out,                 ///< [out] Pointer to total number of runs (i.e., length of \\p d_offsets_out)\n        int                     num_items,                      ///< [in] Total number of associated key+value pairs (i.e., the length of \\p d_in_keys and \\p d_in_values)\n        cudaStream_t            stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int         OffsetT;                    // Signed integer type for global offsets\n        typedef Equality    EqualityOp;                 // Default == operator\n\n        return DeviceRleDispatch<InputIteratorT, OffsetsOutputIteratorT, LengthsOutputIteratorT, NumRunsOutputIteratorT, EqualityOp, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_offsets_out,\n            d_lengths_out,\n            d_num_runs_out,\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_scan.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceScan provides device-wide, parallel operations for computing a prefix scan across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_scan.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceScan provides device-wide, parallel operations for computing a prefix scan across a sequence of data items residing within device-accessible memory. ![](device_scan.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * Given a sequence of input elements and a binary reduction operator, a [<em>prefix scan</em>](http://en.wikipedia.org/wiki/Prefix_sum)\n * produces an output sequence where each element is computed to be the reduction\n * of the elements occurring earlier in the input sequence.  <em>Prefix sum</em>\n * connotes a prefix scan with the addition operator. The term \\em inclusive indicates\n * that the <em>i</em><sup>th</sup> output reduction incorporates the <em>i</em><sup>th</sup> input.\n * The term \\em exclusive indicates the <em>i</em><sup>th</sup> input is not incorporated into\n * the <em>i</em><sup>th</sup> output reduction.\n *\n * \\par\n * As of CUB 1.0.1 (2013), CUB's device-wide scan APIs have implemented our <em>\"decoupled look-back\"</em> algorithm\n * for performing global prefix scan with only a single pass through the\n * input data, as described in our 2016 technical report [1].  The central\n * idea is to leverage a small, constant factor of redundant work in order to overlap the latencies\n * of global prefix propagation with local computation.  As such, our algorithm requires only\n * ~2<em>n</em> data movement (<em>n</em> inputs are read, <em>n</em> outputs are written), and typically\n * proceeds at \"memcpy\" speeds.\n *\n * \\par\n * [1] [Duane Merrill and Michael Garland.  \"Single-pass Parallel Prefix Scan with Decoupled Look-back\", <em>NVIDIA Technical Report NVR-2016-002</em>, 2016.](https://research.nvidia.com/publication/single-pass-parallel-prefix-scan-decoupled-look-back)\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceScan}\n *\n * \\par Performance\n * \\linear_performance{prefix scan}\n *\n * \\par\n * The following chart illustrates DeviceScan::ExclusiveSum\n * performance across different CUDA architectures for \\p int32 keys.\n * \\plots_below\n *\n * \\image html scan_int32.png\n *\n */\nstruct DeviceScan\n{\n    /******************************************************************//**\n     * \\name Exclusive scans\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes a device-wide exclusive prefix sum.  The value of 0 is applied as the initial value, and is assigned to *d_out.\n     *\n     * \\par\n     * - Supports non-commutative sum operators.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated exclusive sum performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.\n     *\n     * \\image html scan_int32.png\n     * \\image html scan_int64.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the exclusive prefix sum of an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_scan.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;      // e.g., 7\n     * int  *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_out;         // e.g., [ ,  ,  ,  ,  ,  ,  ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run exclusive prefix sum\n     * cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // d_out s<-- [0, 8, 14, 21, 26, 29, 29]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading scan inputs \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Random-access output iterator type for writing scan outputs \\iterator\n     */\n    template <\n        typename        InputIteratorT,\n        typename        OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ExclusiveSum(\n        void            *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t          &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                              ///< [out] Pointer to the output sequence of data items\n        int             num_items,                          ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t    stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The output value type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n        // Initial value\n        OutputT init_value = 0;\n\n        return DispatchScan<InputIteratorT, OutputIteratorT, Sum, OutputT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            Sum(),\n            init_value,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide exclusive prefix scan using the specified binary \\p scan_op functor.  The \\p init_value value is applied as the initial value, and is assigned to *d_out.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the exclusive prefix min-scan of an \\p int device vector\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_scan.cuh>\n     *\n     * // CustomMin functor\n     * struct CustomMin\n     * {\n     *     template <typename T>\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     T operator()(const T &a, const T &b) const {\n     *         return (b < a) ? b : a;\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;      // e.g., 7\n     * int          *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int          *d_out;         // e.g., [ ,  ,  ,  ,  ,  ,  ]\n     * CustomMin    min_op\n     * ...\n     *\n     * // Determine temporary device storage requirements for exclusive prefix scan\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceScan::ExclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, min_op, (int) MAX_INT, num_items);\n     *\n     * // Allocate temporary storage for exclusive prefix scan\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run exclusive prefix min-scan\n     * cub::DeviceScan::ExclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, min_op, (int) MAX_INT, num_items);\n     *\n     * // d_out <-- [2147483647, 8, 6, 6, 5, 3, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT   <b>[inferred]</b> Random-access input iterator type for reading scan inputs \\iterator\n     * \\tparam OutputIteratorT  <b>[inferred]</b> Random-access output iterator type for writing scan outputs \\iterator\n     * \\tparam ScanOp           <b>[inferred]</b> Binary scan functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam Identity         <b>[inferred]</b> Type of the \\p identity value used Binary scan functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename        InputIteratorT,\n        typename        OutputIteratorT,\n        typename        ScanOpT,\n        typename        InitValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ExclusiveScan(\n        void            *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t          &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                              ///< [out] Pointer to the output sequence of data items\n        ScanOpT         scan_op,                            ///< [in] Binary scan functor\n        InitValueT      init_value,                         ///< [in] Initial value to seed the exclusive scan (and is assigned to *d_out)\n        int             num_items,                          ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t    stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchScan<InputIteratorT, OutputIteratorT, ScanOpT, InitValueT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            scan_op,\n            init_value,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive scans\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes a device-wide inclusive prefix sum.\n     *\n     * \\par\n     * - Supports non-commutative sum operators.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the inclusive prefix sum of an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_scan.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;      // e.g., 7\n     * int  *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_out;         // e.g., [ ,  ,  ,  ,  ,  ,  ]\n     * ...\n     *\n     * // Determine temporary device storage requirements for inclusive prefix sum\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // Allocate temporary storage for inclusive prefix sum\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run inclusive prefix sum\n     * cub::DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items);\n     *\n     * // d_out <-- [8, 14, 21, 26, 29, 29, 38]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading scan inputs \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Random-access output iterator type for writing scan outputs \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t InclusiveSum(\n        void*               d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                           ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                          ///< [out] Pointer to the output sequence of data items\n        int                 num_items,                      ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t        stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchScan<InputIteratorT, OutputIteratorT, Sum, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            Sum(),\n            NullType(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide inclusive prefix scan using the specified binary \\p scan_op functor.\n     *\n     * \\par\n     * - Supports non-commutative scan operators.\n     * - Provides \"run-to-run\" determinism for pseudo-associative reduction\n     *   (e.g., addition of floating point types) on the same GPU device.\n     *   However, results for pseudo-associative reduction may be inconsistent\n     *   from one device to a another device of a different compute-capability\n     *   because CUB can employ different tile-sizing for different architectures.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the inclusive prefix min-scan of an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_scan.cuh>\n     *\n     * // CustomMin functor\n     * struct CustomMin\n     * {\n     *     template <typename T>\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     T operator()(const T &a, const T &b) const {\n     *         return (b < a) ? b : a;\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_items;      // e.g., 7\n     * int          *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int          *d_out;         // e.g., [ ,  ,  ,  ,  ,  ,  ]\n     * CustomMin    min_op;\n     * ...\n     *\n     * // Determine temporary device storage requirements for inclusive prefix scan\n     * void *d_temp_storage = NULL;\n     * size_t temp_storage_bytes = 0;\n     * cub::DeviceScan::InclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, min_op, num_items);\n     *\n     * // Allocate temporary storage for inclusive prefix scan\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run inclusive prefix min-scan\n     * cub::DeviceScan::InclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, min_op, num_items);\n     *\n     * // d_out <-- [8, 6, 6, 5, 3, 0, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT   <b>[inferred]</b> Random-access input iterator type for reading scan inputs \\iterator\n     * \\tparam OutputIteratorT  <b>[inferred]</b> Random-access output iterator type for writing scan outputs \\iterator\n     * \\tparam ScanOp           <b>[inferred]</b> Binary scan functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename        InputIteratorT,\n        typename        OutputIteratorT,\n        typename        ScanOpT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t InclusiveScan(\n        void            *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t          &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                              ///< [out] Pointer to the output sequence of data items\n        ScanOpT         scan_op,                            ///< [in] Binary scan functor\n        int             num_items,                          ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t    stream             = 0,             ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous  = false)         ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchScan<InputIteratorT, OutputIteratorT, ScanOpT, NullType, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            scan_op,\n            NullType(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n    //@}  end member group\n\n};\n\n/**\n * \\example example_device_scan.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_segmented_radix_sort.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSegmentedRadixSort provides device-wide, parallel operations for computing a batched radix sort across multiple, non-overlapping sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_radix_sort.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceSegmentedRadixSort provides device-wide, parallel operations for computing a batched radix sort across multiple, non-overlapping sequences of data items residing within device-accessible memory. ![](segmented_sorting_logo.png)\n * \\ingroup SegmentedModule\n *\n * \\par Overview\n * The [<em>radix sorting method</em>](http://en.wikipedia.org/wiki/Radix_sort) arranges\n * items into ascending (or descending) order.  The algorithm relies upon a positional representation for\n * keys, i.e., each key is comprised of an ordered sequence of symbols (e.g., digits,\n * characters, etc.) specified from least-significant to most-significant.  For a\n * given input sequence of keys and a set of rules specifying a total ordering\n * of the symbolic alphabet, the radix sorting method produces a lexicographic\n * ordering of those keys.\n *\n * \\par\n * DeviceSegmentedRadixSort can sort all of the built-in C++ numeric primitive types, e.g.:\n * <tt>unsigned char</tt>, \\p int, \\p double, etc.  Although the direct radix sorting\n * method can only be applied to unsigned integral types, DeviceSegmentedRadixSort\n * is able to sort signed and floating-point types via simple bit-wise transformations\n * that ensure lexicographic key ordering.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceSegmentedRadixSort}\n *\n */\nstruct DeviceSegmentedRadixSort\n{\n\n    /******************************************************************//**\n     * \\name Key-value pairs\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Sorts segments of key-value pairs into ascending order. (~<em>2N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [-, -, -, -, -, -, -]\n     * int  *d_values_in;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_values_out;      // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortPairs(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortPairs(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys_out            <-- [6, 7, 8, 0, 3, 5, 9]\n     * // d_values_out          <-- [1, 2, 0, 5, 4, 3, 6]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam ValueT           <b>[inferred]</b> Value type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairs(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] %Device-accessible pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] %Device-accessible pointer to the sorted output sequence of key data\n        const ValueT        *d_values_in,                           ///< [in] %Device-accessible pointer to the corresponding input sequence of associated value items\n        ValueT              *d_values_out,                          ///< [out] %Device-accessible pointer to the correspondingly-reordered output sequence of associated value items\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>       d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<ValueT>     d_values(const_cast<ValueT*>(d_values_in), d_values_out);\n\n        return DispatchSegmentedRadixSort<false, KeyT, ValueT, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts segments of key-value pairs into ascending order. (~<em>N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers and a corresponding\n     *   pair of associated value buffers.  Each pair is managed by a DoubleBuffer\n     *   structure that indicates which of the two buffers is \"current\" (and thus\n     *   contains the input data to be sorted).\n     * - The contents of both buffers within each pair may be altered by the sorting\n     *   operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within each DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [-, -, -, -, -, -, -]\n     * int  *d_value_buf;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_value_alt_buf;   // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Create a set of DoubleBuffers to wrap pairs of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     * cub::DoubleBuffer<int> d_values(d_value_buf, d_value_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys.Current()      <-- [6, 7, 8, 0, 3, 5, 9]\n     * // d_values.Current()    <-- [5, 4, 3, 1, 2, 0, 6]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam ValueT           <b>[inferred]</b> Value type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename                KeyT,\n        typename                ValueT,\n        typename                OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairs(\n        void                    *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,                              ///< [in,out] Double-buffer of values whose \"current\" device-accessible buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        int                     num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                     num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT         d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT         d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                     begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                     end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchSegmentedRadixSort<false, KeyT, ValueT, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts segments of key-value pairs into descending order. (~<em>2N</em> auxiliary storage required).\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [-, -, -, -, -, -, -]\n     * int  *d_values_in;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_values_out;      // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes,\n     *     d_keys_in, d_keys_out, d_values_in, d_values_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys_out            <-- [8, 7, 6, 9, 5, 3, 0]\n     * // d_values_out          <-- [0, 2, 1, 6, 3, 4, 5]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam ValueT           <b>[inferred]</b> Value type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            ValueT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairsDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] %Device-accessible pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] %Device-accessible pointer to the sorted output sequence of key data\n        const ValueT        *d_values_in,                           ///< [in] %Device-accessible pointer to the corresponding input sequence of associated value items\n        ValueT              *d_values_out,                          ///< [out] %Device-accessible pointer to the correspondingly-reordered output sequence of associated value items\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>       d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<ValueT>     d_values(const_cast<ValueT*>(d_values_in), d_values_out);\n\n        return DispatchSegmentedRadixSort<true, KeyT, ValueT, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts segments of key-value pairs into descending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers and a corresponding\n     *   pair of associated value buffers.  Each pair is managed by a DoubleBuffer\n     *   structure that indicates which of the two buffers is \"current\" (and thus\n     *   contains the input data to be sorted).\n     * - The contents of both buffers within each pair may be altered by the sorting\n     *   operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within each DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys\n     * with associated vector of \\p int values.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [-, -, -, -, -, -, -]\n     * int  *d_value_buf;       // e.g., [0, 1, 2, 3, 4, 5, 6]\n     * int  *d_value_alt_buf;   // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Create a set of DoubleBuffers to wrap pairs of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     * cub::DoubleBuffer<int> d_values(d_value_buf, d_value_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes, d_keys, d_values,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortPairsDescending(d_temp_storage, temp_storage_bytes, d_keys, d_values,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys.Current()      <-- [8, 7, 6, 9, 5, 3, 0]\n     * // d_values.Current()    <-- [0, 2, 1, 6, 3, 4, 5]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam ValueT           <b>[inferred]</b> Value type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename                KeyT,\n        typename                ValueT,\n        typename                OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortPairsDescending(\n        void                    *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,                              ///< [in,out] Double-buffer of values whose \"current\" device-accessible buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        int                     num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                     num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT         d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT         d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                     begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                     end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchSegmentedRadixSort<true, KeyT, ValueT, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Keys-only\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Sorts segments of keys into ascending order. (~<em>2N </em>auxiliary storage required)\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys_out            <-- [6, 7, 8, 0, 3, 5, 9]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeys(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] %Device-accessible pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] %Device-accessible pointer to the sorted output sequence of key data\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<KeyT>      d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<NullType>  d_values;\n\n        return DispatchSegmentedRadixSort<false, KeyT, NullType, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts segments of keys into ascending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers managed by a\n     *   DoubleBuffer structure that indicates which of the two buffers is\n     *   \"current\" (and thus contains the input data to be sorted).\n     * - The contents of both buffers may be altered by the sorting operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within the DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys.Current()      <-- [6, 7, 8, 0, 3, 5, 9]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeys(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>  &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<NullType> d_values;\n\n        return DispatchSegmentedRadixSort<false, KeyT, NullType, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n    /**\n     * \\brief Sorts segments of keys into descending order. (~<em>2N</em> auxiliary storage required).\n     *\n     * \\par\n     * - The contents of the input data are not altered by the sorting operation\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageNP  For sorting using only <em>O</em>(<tt>P</tt>) temporary storage, see the sorting interface using DoubleBuffer wrappers below.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_keys_in;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_keys_out;        // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys_out            <-- [8, 7, 6, 9, 5, 3, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeysDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        const KeyT          *d_keys_in,                             ///< [in] %Device-accessible pointer to the input data of key data to sort\n        KeyT                *d_keys_out,                            ///< [out] %Device-accessible pointer to the sorted output sequence of key data\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        DoubleBuffer<KeyT>      d_keys(const_cast<KeyT*>(d_keys_in), d_keys_out);\n        DoubleBuffer<NullType>  d_values;\n\n        return DispatchSegmentedRadixSort<true, KeyT, NullType, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            false,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Sorts segments of keys into descending order. (~<em>N </em>auxiliary storage required).\n     *\n     * \\par\n     * - The sorting operation is given a pair of key buffers managed by a\n     *   DoubleBuffer structure that indicates which of the two buffers is\n     *   \"current\" (and thus contains the input data to be sorted).\n     * - The contents of both buffers may be altered by the sorting operation.\n     * - Upon completion, the sorting operation will update the \"current\" indicator\n     *   within the DoubleBuffer wrapper to reference which of the two buffers\n     *   now contains the sorted output sequence (a function of the number of key bits\n     *   specified and the targeted device architecture).\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - An optional bit subrange <tt>[begin_bit, end_bit)</tt> of differentiating key bits can be specified.  This can reduce overall sorting overhead and yield a corresponding performance improvement.\n     * - \\devicestorageP\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the batched sorting of three segments (with one zero-length segment) of \\p int keys.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_segmentd_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for sorting data\n     * int  num_items;          // e.g., 7\n     * int  num_segments;       // e.g., 3\n     * int  *d_offsets;         // e.g., [0, 3, 3, 7]\n     * int  *d_key_buf;         // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int  *d_key_alt_buf;     // e.g., [-, -, -, -, -, -, -]\n     * ...\n     *\n     * // Create a DoubleBuffer to wrap the pair of device pointers\n     * cub::DoubleBuffer<int> d_keys(d_key_buf, d_key_alt_buf);\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sorting operation\n     * cub::DeviceSegmentedRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys,\n     *     num_items, num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_keys.Current()      <-- [8, 7, 6, 9, 5, 3, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam KeyT             <b>[inferred]</b> Key type\n     * \\tparam OffsetIteratorT  <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            KeyT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t SortKeysDescending(\n        void                *d_temp_storage,                        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>  &d_keys,                                ///< [in,out] Reference to the double-buffer of keys whose \"current\" device-accessible buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        int                 num_items,                              ///< [in] The total number of items to sort (across all segments)\n        int                 num_segments,                           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                 begin_bit           = 0,                ///< [in] <b>[optional]</b> The least-significant bit index (inclusive)  needed for key comparison\n        int                 end_bit             = sizeof(KeyT) * 8, ///< [in] <b>[optional]</b> The most-significant bit index (exclusive) needed for key comparison (e.g., sizeof(unsigned int) * 8)\n        cudaStream_t        stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Null value type\n        DoubleBuffer<NullType> d_values;\n\n        return DispatchSegmentedRadixSort<true, KeyT, NullType, OffsetIteratorT, OffsetT>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys,\n            d_values,\n            num_items,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            begin_bit,\n            end_bit,\n            true,\n            stream,\n            debug_synchronous);\n    }\n\n\n    //@}  end member group\n\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_segmented_reduce.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSegmentedReduce provides device-wide, parallel operations for computing a batched reduction across multiple sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"../iterator/arg_index_input_iterator.cuh\"\n#include \"dispatch/dispatch_reduce.cuh\"\n#include \"dispatch/dispatch_reduce_by_key.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceSegmentedReduce provides device-wide, parallel operations for computing a reduction across multiple sequences of data items residing within device-accessible memory. ![](reduce_logo.png)\n * \\ingroup SegmentedModule\n *\n * \\par Overview\n * A <a href=\"http://en.wikipedia.org/wiki/Reduce_(higher-order_function)\"><em>reduction</em></a> (or <em>fold</em>)\n * uses a binary combining operator to compute a single aggregate from a sequence of input elements.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceSegmentedReduce}\n *\n */\nstruct DeviceSegmentedReduce\n{\n    /**\n     * \\brief Computes a device-wide segmented reduction using the specified binary \\p reduction_op functor.\n     *\n     * \\par\n     * - Does not support binary reduction operators that are non-commutative.\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a custom min-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // CustomMin functor\n     * struct CustomMin\n     * {\n     *     template <typename T>\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     T operator()(const T &a, const T &b) const {\n     *         return (b < a) ? b : a;\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int          num_segments;   // e.g., 3\n     * int          *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int          *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int          *d_out;         // e.g., [-, -, -]\n     * CustomMin    min_op;\n     * int          initial_value;           // e.g., INT_MAX\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::Reduce(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1, min_op, initial_value);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run reduction\n     * cub::DeviceSegmentedReduce::Reduce(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1, min_op, initial_value);\n     *\n     * // d_out <-- [6, INT_MAX, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     * \\tparam OffsetIteratorT      <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     * \\tparam ReductionOp          <b>[inferred]</b> Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n     * \\tparam T                    <b>[inferred]</b> Data element type that is convertible to the \\p value type of \\p InputIteratorT\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT,\n        typename            ReductionOp,\n        typename            T>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Reduce(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        ReductionOp         reduction_op,                       ///< [in] Binary reduction functor \n        T                   initial_value,                      ///< [in] Initial value of the reduction for each segment\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        return DispatchSegmentedReduce<InputIteratorT, OutputIteratorT, OffsetIteratorT, OffsetT, ReductionOp>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            reduction_op,\n            initial_value,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide segmented sum using the addition ('+') operator.\n     *\n     * \\par\n     * - Uses \\p 0 as the initial value of the reduction for each segment.\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - Does not support \\p + operators that are non-commutative..\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the sum reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int num_segments;   // e.g., 3\n     * int *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int *d_out;         // e.g., [-, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run sum-reduction\n     * cub::DeviceSegmentedReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_out <-- [21, 0, 17]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     * \\tparam OffsetIteratorT      <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Sum(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The output value type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n        return DispatchSegmentedReduce<InputIteratorT,  OutputIteratorT, OffsetIteratorT, OffsetT, cub::Sum>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            cub::Sum(),\n            OutputT(),            // zero-initialize\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide segmented minimum using the less-than ('<') operator.\n     *\n     * \\par\n     * - Uses <tt>std::numeric_limits<T>::max()</tt> as the initial value of the reduction for each segment.\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - Does not support \\p < operators that are non-commutative.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the min-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int num_segments;   // e.g., 3\n     * int *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int *d_out;         // e.g., [-, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::Min(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run min-reduction\n     * cub::DeviceSegmentedReduce::Min(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_out <-- [6, INT_MAX, 0]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     * \\tparam OffsetIteratorT      <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Min(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input value type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n        return DispatchSegmentedReduce<InputIteratorT,  OutputIteratorT, OffsetIteratorT, OffsetT, cub::Min>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            cub::Min(),\n            Traits<InputT>::Max(),    // replace with std::numeric_limits<T>::max() when C++11 support is more prevalent\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Finds the first device-wide minimum in each segment using the less-than ('<') operator, also returning the in-segment index of that item.\n     *\n     * \\par\n     * - The output value type of \\p d_out is cub::KeyValuePair <tt><int, T></tt> (assuming the value type of \\p d_in is \\p T)\n     *   - The minimum of the <em>i</em><sup>th</sup> segment is written to <tt>d_out[i].value</tt> and its offset in that segment is written to <tt>d_out[i].key</tt>.\n     *   - The <tt>{1, std::numeric_limits<T>::max()}</tt> tuple is produced for zero-length inputs\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - Does not support \\p < operators that are non-commutative.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the argmin-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int                      num_segments;   // e.g., 3\n     * int                      *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int                      *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * KeyValuePair<int, int>   *d_out;         // e.g., [{-,-}, {-,-}, {-,-}]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::ArgMin(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run argmin-reduction\n     * cub::DeviceSegmentedReduce::ArgMin(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_out <-- [{1,6}, {1,INT_MAX}, {2,0}]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items (of some type \\p T) \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate (having value type <tt>KeyValuePair<int, T></tt>) \\iterator\n     * \\tparam OffsetIteratorT      <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ArgMin(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputValueT;\n\n        // The output tuple type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            KeyValuePair<OffsetT, InputValueT>,                                                                 // ... then the key value pair OffsetT + InputValueT\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputTupleT;                     // ... else the output iterator's value type\n\n        // The output value type\n        typedef typename OutputTupleT::Value OutputValueT;\n\n        // Wrapped input iterator to produce index-value <OffsetT, InputT> tuples\n        typedef ArgIndexInputIterator<InputIteratorT, OffsetT, OutputValueT> ArgIndexInputIteratorT;\n        ArgIndexInputIteratorT d_indexed_in(d_in);\n\n        // Initial value\n        OutputTupleT initial_value(1, Traits<InputValueT>::Max());   // replace with std::numeric_limits<T>::max() when C++11 support is more prevalent\n\n        return DispatchSegmentedReduce<ArgIndexInputIteratorT,  OutputIteratorT, OffsetIteratorT, OffsetT, cub::ArgMin>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_indexed_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            cub::ArgMin(),\n            initial_value,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide segmented maximum using the greater-than ('>') operator.\n     *\n     * \\par\n     * - Uses <tt>std::numeric_limits<T>::lowest()</tt> as the initial value of the reduction.\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - Does not support \\p > operators that are non-commutative.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the max-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_radix_sort.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int num_segments;   // e.g., 3\n     * int *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * int *d_out;         // e.g., [-, -, -]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::Max(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run max-reduction\n     * cub::DeviceSegmentedReduce::Max(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_out <-- [8, INT_MIN, 9]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate \\iterator\n     * \\tparam OffsetIteratorT      <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t Max(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input value type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n        return DispatchSegmentedReduce<InputIteratorT,  OutputIteratorT, OffsetIteratorT, OffsetT, cub::Max>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            cub::Max(),\n            Traits<InputT>::Lowest(),    // replace with std::numeric_limits<T>::lowest() when C++11 support is more prevalent\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Finds the first device-wide maximum in each segment using the greater-than ('>') operator, also returning the in-segment index of that item\n     *\n     * \\par\n     * - The output value type of \\p d_out is cub::KeyValuePair <tt><int, T></tt> (assuming the value type of \\p d_in is \\p T)\n     *   - The maximum of the <em>i</em><sup>th</sup> segment is written to <tt>d_out[i].value</tt> and its offset in that segment is written to <tt>d_out[i].key</tt>.\n     *   - The <tt>{1, std::numeric_limits<T>::lowest()}</tt> tuple is produced for zero-length inputs\n     * - When input a contiguous sequence of segments, a single sequence\n     *   \\p segment_offsets (of length <tt>num_segments+1</tt>) can be aliased\n     *   for both the \\p d_begin_offsets and \\p d_end_offsets parameters (where\n     *   the latter is specified as <tt>segment_offsets+1</tt>).\n     * - Does not support \\p > operators that are non-commutative.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the argmax-reduction of a device vector of \\p int data elements.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_reduce.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int                      num_segments;   // e.g., 3\n     * int                      *d_offsets;     // e.g., [0, 3, 3, 7]\n     * int                      *d_in;          // e.g., [8, 6, 7, 5, 3, 0, 9]\n     * KeyValuePair<int, int>   *d_out;         // e.g., [{-,-}, {-,-}, {-,-}]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSegmentedReduce::ArgMax(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run argmax-reduction\n     * cub::DeviceSegmentedReduce::ArgMax(d_temp_storage, temp_storage_bytes, d_in, d_out,\n     *     num_segments, d_offsets, d_offsets + 1);\n     *\n     * // d_out <-- [{0,8}, {1,INT_MIN}, {3,9}]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT     <b>[inferred]</b> Random-access input iterator type for reading input items (of some type \\p T) \\iterator\n     * \\tparam OutputIteratorT    <b>[inferred]</b> Output iterator type for recording the reduced aggregate (having value type <tt>KeyValuePair<int, T></tt>) \\iterator\n     * \\tparam OffsetIteratorT    <b>[inferred]</b> Random-access input iterator type for reading segment offsets \\iterator\n     */\n    template <\n        typename            InputIteratorT,\n        typename            OutputIteratorT,\n        typename            OffsetIteratorT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t ArgMax(\n        void                *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t              &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                              ///< [out] Pointer to the output aggregate\n        int                 num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT     d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT     d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        cudaStream_t        stream              = 0,            ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous   = false)        ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // The input type\n        typedef typename std::iterator_traits<InputIteratorT>::value_type InputValueT;\n\n        // The output tuple type\n        typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            KeyValuePair<OffsetT, InputValueT>,                                                                 // ... then the key value pair OffsetT + InputValueT\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputTupleT;                     // ... else the output iterator's value type\n\n        // The output value type\n        typedef typename OutputTupleT::Value OutputValueT;\n\n        // Wrapped input iterator to produce index-value <OffsetT, InputT> tuples\n        typedef ArgIndexInputIterator<InputIteratorT, OffsetT, OutputValueT> ArgIndexInputIteratorT;\n        ArgIndexInputIteratorT d_indexed_in(d_in);\n\n        // Initial value\n        OutputTupleT initial_value(1, Traits<InputValueT>::Lowest());     // replace with std::numeric_limits<T>::lowest() when C++11 support is more prevalent\n\n        return DispatchSegmentedReduce<ArgIndexInputIteratorT, OutputIteratorT, OffsetIteratorT, OffsetT, cub::ArgMax>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_indexed_in,\n            d_out,\n            num_segments,\n            d_begin_offsets,\n            d_end_offsets,\n            cub::ArgMax(),\n            initial_value,\n            stream,\n            debug_synchronous);\n    }\n\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_select.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSelect provides device-wide, parallel operations for compacting selected items from sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch/dispatch_select_if.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceSelect provides device-wide, parallel operations for compacting selected items from sequences of data items residing within device-accessible memory. ![](select_logo.png)\n * \\ingroup SingleModule\n *\n * \\par Overview\n * These operations apply a selection criterion to selectively copy\n * items from a specified input sequence to a compact output sequence.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceSelect}\n *\n * \\par Performance\n * \\linear_performance{select-flagged, select-if, and select-unique}\n *\n * \\par\n * The following chart illustrates DeviceSelect::If\n * performance across different CUDA architectures for \\p int32 items,\n * where 50% of the items are randomly selected.\n *\n * \\image html select_if_int32_50_percent.png\n *\n * \\par\n * The following chart illustrates DeviceSelect::Unique\n * performance across different CUDA architectures for \\p int32 items\n * where segments have lengths uniformly sampled from [1,1000].\n *\n * \\image html select_unique_int32_len_500.png\n *\n * \\par\n * \\plots_below\n *\n */\nstruct DeviceSelect\n{\n    /**\n     * \\brief Uses the \\p d_flags sequence to selectively copy the corresponding items from \\p d_in into \\p d_out.  The total number of items selected is written to \\p d_num_selected_out. ![](select_flags_logo.png)\n     *\n     * \\par\n     * - The value type of \\p d_flags must be castable to \\p bool (e.g., \\p bool, \\p char, \\p int, etc.).\n     * - Copies of the selected items are compacted into \\p d_out and maintain their original relative ordering.\n     * - \\devicestorage\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the compaction of items selected from an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>       // or equivalently <cub/device/device_select.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input, flags, and output\n     * int  num_items;              // e.g., 8\n     * int  *d_in;                  // e.g., [1, 2, 3, 4, 5, 6, 7, 8]\n     * char *d_flags;               // e.g., [1, 0, 0, 1, 0, 1, 1, 0]\n     * int  *d_out;                 // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int  *d_num_selected_out;    // e.g., [ ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSelect::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run selection\n     * cub::DeviceSelect::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items);\n     *\n     * // d_out                 <-- [1, 4, 6, 7]\n     * // d_num_selected_out    <-- [4]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam FlagIterator         <b>[inferred]</b> Random-access input iterator type for reading selection flags \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Random-access output iterator type for writing selected items \\iterator\n     * \\tparam NumSelectedIteratorT  <b>[inferred]</b> Output iterator type for recording the number of items selected \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    FlagIterator,\n        typename                    OutputIteratorT,\n        typename                    NumSelectedIteratorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Flagged(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        FlagIterator                d_flags,                        ///< [in] Pointer to the input sequence of selection flags\n        OutputIteratorT             d_out,                          ///< [out] Pointer to the output sequence of selected data items\n        NumSelectedIteratorT         d_num_selected_out,                 ///< [out] Pointer to the output total number of items selected (i.e., length of \\p d_out)\n        int                         num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int                     OffsetT;         // Signed integer type for global offsets\n        typedef NullType                SelectOp;       // Selection op (not used)\n        typedef NullType                EqualityOp;     // Equality operator (not used)\n\n        return DispatchSelectIf<InputIteratorT, FlagIterator, OutputIteratorT, NumSelectedIteratorT, SelectOp, EqualityOp, OffsetT, false>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_flags,\n            d_out,\n            d_num_selected_out,\n            SelectOp(),\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Uses the \\p select_op functor to selectively copy items from \\p d_in into \\p d_out.  The total number of items selected is written to \\p d_num_selected_out. ![](select_logo.png)\n     *\n     * \\par\n     * - Copies of the selected items are compacted into \\p d_out and maintain their original relative ordering.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated select-if performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.  Items are\n     * selected with 50% probability.\n     *\n     * \\image html select_if_int32_50_percent.png\n     * \\image html select_if_int64_50_percent.png\n     *\n     * \\par\n     * The following charts are similar, but 5% selection probability:\n     *\n     * \\image html select_if_int32_5_percent.png\n     * \\image html select_if_int64_5_percent.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the compaction of items selected from an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_select.cuh>\n     *\n     * // Functor type for selecting values less than some criteria\n     * struct LessThan\n     * {\n     *     int compare;\n     *\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     LessThan(int compare) : compare(compare) {}\n     *\n     *     CUB_RUNTIME_FUNCTION __forceinline__\n     *     bool operator()(const int &a) const {\n     *         return (a < compare);\n     *     }\n     * };\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int      num_items;              // e.g., 8\n     * int      *d_in;                  // e.g., [0, 2, 3, 9, 5, 2, 81, 8]\n     * int      *d_out;                 // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int      *d_num_selected_out;    // e.g., [ ]\n     * LessThan select_op(7);\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run selection\n     * cub::DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op);\n     *\n     * // d_out                 <-- [0, 2, 3, 5, 2]\n     * // d_num_selected_out    <-- [5]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Random-access output iterator type for writing selected items \\iterator\n     * \\tparam NumSelectedIteratorT  <b>[inferred]</b> Output iterator type for recording the number of items selected \\iterator\n     * \\tparam SelectOp             <b>[inferred]</b> Selection operator type having member <tt>bool operator()(const T &a)</tt>\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT,\n        typename                    NumSelectedIteratorT,\n        typename                    SelectOp>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t If(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                          ///< [out] Pointer to the output sequence of selected data items\n        NumSelectedIteratorT         d_num_selected_out,                 ///< [out] Pointer to the output total number of items selected (i.e., length of \\p d_out)\n        int                         num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        SelectOp                    select_op,                      ///< [in] Unary selection operator\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int                     OffsetT;         // Signed integer type for global offsets\n        typedef NullType*               FlagIterator;   // FlagT iterator type (not used)\n        typedef NullType                EqualityOp;     // Equality operator (not used)\n\n        return DispatchSelectIf<InputIteratorT, FlagIterator, OutputIteratorT, NumSelectedIteratorT, SelectOp, EqualityOp, OffsetT, false>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            NULL,\n            d_out,\n            d_num_selected_out,\n            select_op,\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Given an input sequence \\p d_in having runs of consecutive equal-valued keys, only the first key from each run is selectively copied to \\p d_out.  The total number of items selected is written to \\p d_num_selected_out. ![](unique_logo.png)\n     *\n     * \\par\n     * - The <tt>==</tt> equality operator is used to determine whether keys are equivalent\n     * - Copies of the selected items are compacted into \\p d_out and maintain their original relative ordering.\n     * - \\devicestorage\n     *\n     * \\par Performance\n     * The following charts illustrate saturated select-unique performance across different\n     * CUDA architectures for \\p int32 and \\p int64 items, respectively.  Segments have\n     * lengths uniformly sampled from [1,1000].\n     *\n     * \\image html select_unique_int32_len_500.png\n     * \\image html select_unique_int64_len_500.png\n     *\n     * \\par\n     * The following charts are similar, but with segment lengths uniformly sampled from [1,10]:\n     *\n     * \\image html select_unique_int32_len_5.png\n     * \\image html select_unique_int64_len_5.png\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the compaction of items selected from an \\p int device vector.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>       // or equivalently <cub/device/device_select.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input and output\n     * int  num_items;              // e.g., 8\n     * int  *d_in;                  // e.g., [0, 2, 2, 9, 5, 5, 5, 8]\n     * int  *d_out;                 // e.g., [ ,  ,  ,  ,  ,  ,  ,  ]\n     * int  *d_num_selected_out;    // e.g., [ ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void     *d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSelect::Unique(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run selection\n     * cub::DeviceSelect::Unique(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items);\n     *\n     * // d_out                 <-- [0, 2, 9, 5, 8]\n     * // d_num_selected_out    <-- [5]\n     *\n     * \\endcode\n     *\n     * \\tparam InputIteratorT       <b>[inferred]</b> Random-access input iterator type for reading input items \\iterator\n     * \\tparam OutputIteratorT      <b>[inferred]</b> Random-access output iterator type for writing selected items \\iterator\n     * \\tparam NumSelectedIteratorT  <b>[inferred]</b> Output iterator type for recording the number of items selected \\iterator\n     */\n    template <\n        typename                    InputIteratorT,\n        typename                    OutputIteratorT,\n        typename                    NumSelectedIteratorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Unique(\n        void*               d_temp_storage,                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                      &temp_storage_bytes,            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT             d_out,                          ///< [out] Pointer to the output sequence of selected data items\n        NumSelectedIteratorT         d_num_selected_out,             ///< [out] Pointer to the output total number of items selected (i.e., length of \\p d_out)\n        int                         num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream             = 0,         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous  = false)     ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        typedef int                     OffsetT;         // Signed integer type for global offsets\n        typedef NullType*               FlagIterator;   // FlagT iterator type (not used)\n        typedef NullType                SelectOp;       // Selection op (not used)\n        typedef Equality                EqualityOp;     // Default == operator\n\n        return DispatchSelectIf<InputIteratorT, FlagIterator, OutputIteratorT, NumSelectedIteratorT, SelectOp, EqualityOp, OffsetT, false>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            NULL,\n            d_out,\n            d_num_selected_out,\n            SelectOp(),\n            EqualityOp(),\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n\n};\n\n/**\n * \\example example_device_select_flagged.cu\n * \\example example_device_select_if.cu\n * \\example example_device_select_unique.cu\n */\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/device_spmv.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSpmv provides device-wide parallel operations for performing sparse-matrix * vector multiplication (SpMV).\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n#include <limits>\n\n#include \"dispatch/dispatch_spmv_orig.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief DeviceSpmv provides device-wide parallel operations for performing sparse-matrix * dense-vector multiplication (SpMV).\n * \\ingroup SingleModule\n *\n * \\par Overview\n * The [<em>SpMV computation</em>](http://en.wikipedia.org/wiki/Sparse_matrix-vector_multiplication)\n * performs the matrix-vector operation\n * <em>y</em> = <em>alpha</em>*<b>A</b>*<em>x</em> + <em>beta</em>*<em>y</em>,\n * where:\n *  - <b>A</b> is an <em>m</em>x<em>n</em> sparse matrix whose non-zero structure is specified in\n *    [<em>compressed-storage-row (CSR) format</em>](http://en.wikipedia.org/wiki/Sparse_matrix#Compressed_row_Storage_.28CRS_or_CSR.29)\n *    (i.e., three arrays: <em>values</em>, <em>row_offsets</em>, and <em>column_indices</em>)\n *  - <em>x</em> and <em>y</em> are dense vectors\n *  - <em>alpha</em> and <em>beta</em> are scalar multiplicands\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceSpmv}\n *\n */\nstruct DeviceSpmv\n{\n    /******************************************************************//**\n     * \\name CSR matrix operations\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief This function performs the matrix-vector operation <em>y</em> = <b>A</b>*<em>x</em>.\n     *\n     * \\par Snippet\n     * The code snippet below illustrates SpMV upon a 9x9 CSR matrix <b>A</b>\n     * representing a 3x3 lattice (24 non-zeros).\n     *\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>   // or equivalently <cub/device/device_spmv.cuh>\n     *\n     * // Declare, allocate, and initialize device-accessible pointers for input matrix A, input vector x,\n     * // and output vector y\n     * int    num_rows = 9;\n     * int    num_cols = 9;\n     * int    num_nonzeros = 24;\n     *\n     * float* d_values;  // e.g., [1, 1, 1, 1, 1, 1, 1, 1,\n     *                   //        1, 1, 1, 1, 1, 1, 1, 1,\n     *                   //        1, 1, 1, 1, 1, 1, 1, 1]\n     *\n     * int*   d_column_indices; // e.g., [1, 3, 0, 2, 4, 1, 5, 0,\n     *                          //        4, 6, 1, 3, 5, 7, 2, 4,\n     *                          //        8, 3, 7, 4, 6, 8, 5, 7]\n     *\n     * int*   d_row_offsets;    // e.g., [0, 2, 5, 7, 10, 14, 17, 19, 22, 24]\n     *\n     * float* d_vector_x;       // e.g., [1, 1, 1, 1, 1, 1, 1, 1, 1]\n     * float* d_vector_y;       // e.g., [ ,  ,  ,  ,  ,  ,  ,  ,  ]\n     * ...\n     *\n     * // Determine temporary device storage requirements\n     * void*    d_temp_storage = NULL;\n     * size_t   temp_storage_bytes = 0;\n     * cub::DeviceSpmv::CsrMV(d_temp_storage, temp_storage_bytes, d_values,\n     *     d_row_offsets, d_column_indices, d_vector_x, d_vector_y,\n     *     num_rows, num_cols, num_nonzeros, alpha, beta);\n     *\n     * // Allocate temporary storage\n     * cudaMalloc(&d_temp_storage, temp_storage_bytes);\n     *\n     * // Run SpMV\n     * cub::DeviceSpmv::CsrMV(d_temp_storage, temp_storage_bytes, d_values,\n     *     d_row_offsets, d_column_indices, d_vector_x, d_vector_y,\n     *     num_rows, num_cols, num_nonzeros, alpha, beta);\n     *\n     * // d_vector_y <-- [2, 3, 2, 3, 4, 3, 2, 3, 2]\n     *\n     * \\endcode\n     *\n     * \\tparam ValueT       <b>[inferred]</b> Matrix and vector value type (e.g., /p float, /p double, etc.)\n     */\n    template <\n        typename            ValueT>\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t CsrMV(\n        void*               d_temp_storage,                     ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                 ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        ValueT*             d_values,                           ///< [in] Pointer to the array of \\p num_nonzeros values of the corresponding nonzero elements of matrix <b>A</b>.\n        int*                d_row_offsets,                      ///< [in] Pointer to the array of \\p m + 1 offsets demarcating the start of every row in \\p d_column_indices and \\p d_values (with the final entry being equal to \\p num_nonzeros)\n        int*                d_column_indices,                   ///< [in] Pointer to the array of \\p num_nonzeros column-indices of the corresponding nonzero elements of matrix <b>A</b>.  (Indices are zero-valued.)\n        ValueT*             d_vector_x,                         ///< [in] Pointer to the array of \\p num_cols values corresponding to the dense input vector <em>x</em>\n        ValueT*             d_vector_y,                         ///< [out] Pointer to the array of \\p num_rows values corresponding to the dense output vector <em>y</em>\n        int                 num_rows,                           ///< [in] number of rows of matrix <b>A</b>.\n        int                 num_cols,                           ///< [in] number of columns of matrix <b>A</b>.\n        int                 num_nonzeros,                       ///< [in] number of nonzero elements of matrix <b>A</b>.\n        cudaStream_t        stream                  = 0,        ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous       = false)    ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        SpmvParams<ValueT, int> spmv_params;\n        spmv_params.d_values             = d_values;\n        spmv_params.d_row_end_offsets    = d_row_offsets + 1;\n        spmv_params.d_column_indices     = d_column_indices;\n        spmv_params.d_vector_x           = d_vector_x;\n        spmv_params.d_vector_y           = d_vector_y;\n        spmv_params.num_rows             = num_rows;\n        spmv_params.num_cols             = num_cols;\n        spmv_params.num_nonzeros         = num_nonzeros;\n        spmv_params.alpha                = 1.0;\n        spmv_params.beta                 = 0.0;\n\n        return DispatchSpmv<ValueT, int>::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            spmv_params,\n            stream,\n            debug_synchronous);\n    }\n\n    //@}  end member group\n};\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_histogram.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceHistogram provides device-wide parallel operations for constructing histogram(s) from a sequence of samples data residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n#include <limits>\n\n#include \"../../agent/agent_histogram.cuh\"\n#include \"../../util_debug.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../thread/thread_search.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n\n/******************************************************************************\n * Histogram kernel entry points\n *****************************************************************************/\n\n/**\n * Histogram initialization kernel entry point\n */\ntemplate <\n    int                                             NUM_ACTIVE_CHANNELS,            ///< Number of channels actively being histogrammed\n    typename                                        CounterT,                       ///< Integer type for counting sample occurrences per histogram bin\n    typename                                        OffsetT>                        ///< Signed integer type for global offsets\n__global__ void DeviceHistogramInitKernel(\n    ArrayWrapper<int, NUM_ACTIVE_CHANNELS>          num_output_bins_wrapper,        ///< Number of output histogram bins per channel\n    ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS>    d_output_histograms_wrapper,    ///< Histogram counter data having logical dimensions <tt>CounterT[NUM_ACTIVE_CHANNELS][num_bins.array[CHANNEL]]</tt>\n    GridQueue<int>                                  tile_queue)                     ///< Drain queue descriptor for dynamically mapping tile data onto thread blocks\n{\n    if ((threadIdx.x == 0) && (blockIdx.x == 0))\n        tile_queue.ResetDrain();\n\n    int output_bin = (blockIdx.x * blockDim.x) + threadIdx.x;\n\n    #pragma unroll\n    for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n    {\n        if (output_bin < num_output_bins_wrapper.array[CHANNEL])\n            d_output_histograms_wrapper.array[CHANNEL][output_bin] = 0;\n    }\n}\n\n\n/**\n * Histogram privatized sweep kernel entry point (multi-block).  Computes privatized histograms, one per thread block.\n */\ntemplate <\n    typename                                            AgentHistogramPolicyT,     ///< Parameterized AgentHistogramPolicy tuning policy type\n    int                                                 PRIVATIZED_SMEM_BINS,           ///< Maximum number of histogram bins per channel (e.g., up to 256)\n    int                                                 NUM_CHANNELS,                   ///< Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n    int                                                 NUM_ACTIVE_CHANNELS,            ///< Number of channels actively being histogrammed\n    typename                                            SampleIteratorT,                ///< The input iterator type. \\iterator.\n    typename                                            CounterT,                       ///< Integer type for counting sample occurrences per histogram bin\n    typename                                            PrivatizedDecodeOpT,            ///< The transform operator type for determining privatized counter indices from samples, one for each channel\n    typename                                            OutputDecodeOpT,                ///< The transform operator type for determining output bin-ids from privatized counter indices, one for each channel\n    typename                                            OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int(AgentHistogramPolicyT::BLOCK_THREADS))\n__global__ void DeviceHistogramSweepKernel(\n    SampleIteratorT                                         d_samples,                          ///< Input data to reduce\n    ArrayWrapper<int, NUM_ACTIVE_CHANNELS>                  num_output_bins_wrapper,            ///< The number bins per final output histogram\n    ArrayWrapper<int, NUM_ACTIVE_CHANNELS>                  num_privatized_bins_wrapper,        ///< The number bins per privatized histogram\n    ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS>            d_output_histograms_wrapper,        ///< Reference to final output histograms\n    ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS>            d_privatized_histograms_wrapper,    ///< Reference to privatized histograms\n    ArrayWrapper<OutputDecodeOpT, NUM_ACTIVE_CHANNELS>      output_decode_op_wrapper,           ///< The transform operator for determining output bin-ids from privatized counter indices, one for each channel\n    ArrayWrapper<PrivatizedDecodeOpT, NUM_ACTIVE_CHANNELS>  privatized_decode_op_wrapper,       ///< The transform operator for determining privatized counter indices from samples, one for each channel\n    OffsetT                                                 num_row_pixels,                     ///< The number of multi-channel pixels per row in the region of interest\n    OffsetT                                                 num_rows,                           ///< The number of rows in the region of interest\n    OffsetT                                                 row_stride_samples,                 ///< The number of samples between starts of consecutive rows in the region of interest\n    int                                                     tiles_per_row,                      ///< Number of image tiles per row\n    GridQueue<int>                                          tile_queue)                         ///< Drain queue descriptor for dynamically mapping tile data onto thread blocks\n{\n    // Thread block type for compositing input tiles\n    typedef AgentHistogram<\n            AgentHistogramPolicyT,\n            PRIVATIZED_SMEM_BINS,\n            NUM_CHANNELS,\n            NUM_ACTIVE_CHANNELS,\n            SampleIteratorT,\n            CounterT,\n            PrivatizedDecodeOpT,\n            OutputDecodeOpT,\n            OffsetT>\n        AgentHistogramT;\n\n    // Shared memory for AgentHistogram\n    __shared__ typename AgentHistogramT::TempStorage temp_storage;\n\n    AgentHistogramT agent(\n        temp_storage,\n        d_samples,\n        num_output_bins_wrapper.array,\n        num_privatized_bins_wrapper.array,\n        d_output_histograms_wrapper.array,\n        d_privatized_histograms_wrapper.array,\n        output_decode_op_wrapper.array,\n        privatized_decode_op_wrapper.array);\n\n    // Initialize counters\n    agent.InitBinCounters();\n\n    // Consume input tiles\n    agent.ConsumeTiles(\n        num_row_pixels,\n        num_rows,\n        row_stride_samples,\n        tiles_per_row,\n        tile_queue);\n\n    // Store output to global (if necessary)\n    agent.StoreOutput();\n\n}\n\n\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceHistogram\n */\ntemplate <\n    int         NUM_CHANNELS,               ///< Number of channels interleaved in the input data (may be greater than the number of channels being actively histogrammed)\n    int         NUM_ACTIVE_CHANNELS,        ///< Number of channels actively being histogrammed\n    typename    SampleIteratorT,            ///< Random-access input iterator type for reading input items \\iterator\n    typename    CounterT,                   ///< Integer type for counting sample occurrences per histogram bin\n    typename    LevelT,                     ///< Type for specifying bin level boundaries\n    typename    OffsetT>                    ///< Signed integer type for global offsets\nstruct DipatchHistogram\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    /// The sample value type of the input iterator\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    enum\n    {\n        // Maximum number of bins per channel for which we will use a privatized smem strategy\n        MAX_PRIVATIZED_SMEM_BINS = 256\n    };\n\n\n    //---------------------------------------------------------------------\n    // Transform functors for converting samples to bin-ids\n    //---------------------------------------------------------------------\n\n    // Searches for bin given a list of bin-boundary levels\n    template <typename LevelIteratorT>\n    struct SearchTransform\n    {\n        LevelIteratorT  d_levels;                   // Pointer to levels array\n        int             num_output_levels;          // Number of levels in array\n\n        // Initializer\n        __host__ __device__ __forceinline__ void Init(\n            LevelIteratorT  d_levels,               // Pointer to levels array\n            int             num_output_levels)      // Number of levels in array\n        {\n            this->d_levels          = d_levels;\n            this->num_output_levels = num_output_levels;\n        }\n\n        // Method for converting samples to bin-ids\n        template <CacheLoadModifier LOAD_MODIFIER, typename _SampleT>\n        __host__ __device__ __forceinline__ void BinSelect(_SampleT sample, int &bin, bool valid)\n        {\n            /// Level iterator wrapper type\n            typedef typename If<IsPointer<LevelIteratorT>::VALUE,\n                    CacheModifiedInputIterator<LOAD_MODIFIER, LevelT, OffsetT>,     // Wrap the native input pointer with CacheModifiedInputIterator\n                    LevelIteratorT>::Type                                           // Directly use the supplied input iterator type\n                WrappedLevelIteratorT;\n\n            WrappedLevelIteratorT wrapped_levels(d_levels);\n\n            int num_bins = num_output_levels - 1;\n            if (valid)\n            {\n                bin = UpperBound(wrapped_levels, num_output_levels, (LevelT) sample) - 1;\n                if (bin >= num_bins)\n                    bin = -1;\n            }\n        }\n    };\n\n\n    // Scales samples to evenly-spaced bins\n    struct ScaleTransform\n    {\n        int    num_bins;    // Number of levels in array\n        LevelT max;         // Max sample level (exclusive)\n        LevelT min;         // Min sample level (inclusive)\n        LevelT scale;       // Bin scaling factor\n\n        // Initializer\n        template <typename _LevelT>\n        __host__ __device__ __forceinline__ void Init(\n            int     num_output_levels,  // Number of levels in array\n            _LevelT max,                // Max sample level (exclusive)\n            _LevelT min,                // Min sample level (inclusive)\n            _LevelT scale)              // Bin scaling factor\n        {\n            this->num_bins = num_output_levels - 1;\n            this->max = max;\n            this->min = min;\n            this->scale = scale;\n        }\n\n        // Initializer (float specialization)\n        __host__ __device__ __forceinline__ void Init(\n            int    num_output_levels,   // Number of levels in array\n            float   max,                // Max sample level (exclusive)\n            float   min,                // Min sample level (inclusive)\n            float   scale)              // Bin scaling factor\n        {\n            this->num_bins = num_output_levels - 1;\n            this->max = max;\n            this->min = min;\n            this->scale = float(1.0) / scale;\n        }\n\n        // Initializer (double specialization)\n        __host__ __device__ __forceinline__ void Init(\n            int    num_output_levels,   // Number of levels in array\n            double max,                 // Max sample level (exclusive)\n            double min,                 // Min sample level (inclusive)\n            double scale)               // Bin scaling factor\n        {\n            this->num_bins = num_output_levels - 1;\n            this->max = max;\n            this->min = min;\n            this->scale = double(1.0) / scale;\n        }\n\n        // Method for converting samples to bin-ids\n        template <CacheLoadModifier LOAD_MODIFIER, typename _SampleT>\n        __host__ __device__ __forceinline__ void BinSelect(_SampleT sample, int &bin, bool valid)\n        {\n            LevelT level_sample = (LevelT) sample;\n\n            if (valid && (level_sample >= min) && (level_sample < max))\n                bin = (int) ((level_sample - min) / scale);\n        }\n\n        // Method for converting samples to bin-ids (float specialization)\n        template <CacheLoadModifier LOAD_MODIFIER>\n        __host__ __device__ __forceinline__ void BinSelect(float sample, int &bin, bool valid)\n        {\n            LevelT level_sample = (LevelT) sample;\n\n            if (valid && (level_sample >= min) && (level_sample < max))\n                bin = (int) ((level_sample - min) * scale);\n        }\n\n        // Method for converting samples to bin-ids (double specialization)\n        template <CacheLoadModifier LOAD_MODIFIER>\n        __host__ __device__ __forceinline__ void BinSelect(double sample, int &bin, bool valid)\n        {\n            LevelT level_sample = (LevelT) sample;\n\n            if (valid && (level_sample >= min) && (level_sample < max))\n                bin = (int) ((level_sample - min) * scale);\n        }\n    };\n\n\n    // Pass-through bin transform operator\n    struct PassThruTransform\n    {\n        // Method for converting samples to bin-ids\n        template <CacheLoadModifier LOAD_MODIFIER, typename _SampleT>\n        __host__ __device__ __forceinline__ void BinSelect(_SampleT sample, int &bin, bool valid)\n        {\n            if (valid)\n                bin = (int) sample;\n        }\n    };\n\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies\n    //---------------------------------------------------------------------\n\n    template <int NOMINAL_ITEMS_PER_THREAD>\n    struct TScale\n    {\n        enum\n        {\n            V_SCALE = (sizeof(SampleT) + sizeof(int) - 1) / sizeof(int),\n            VALUE   = CUB_MAX((NOMINAL_ITEMS_PER_THREAD / NUM_ACTIVE_CHANNELS / V_SCALE), 1)\n        };\n    };\n\n\n    /// SM11\n    struct Policy110\n    {\n        // HistogramSweepPolicy\n        typedef AgentHistogramPolicy<\n                512,\n                (NUM_CHANNELS == 1) ? 8 : 2,\n                BLOCK_LOAD_DIRECT,\n                LOAD_DEFAULT,\n                true,\n                GMEM,\n                false>\n            HistogramSweepPolicy;\n    };\n\n    /// SM20\n    struct Policy200\n    {\n        // HistogramSweepPolicy\n        typedef AgentHistogramPolicy<\n                (NUM_CHANNELS == 1) ? 256 : 128,\n                (NUM_CHANNELS == 1) ? 8 : 3,\n                (NUM_CHANNELS == 1) ? BLOCK_LOAD_DIRECT : BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                true,\n                SMEM,\n                false>\n            HistogramSweepPolicy;\n    };\n\n    /// SM30\n    struct Policy300\n    {\n        // HistogramSweepPolicy\n        typedef AgentHistogramPolicy<\n                512,\n                (NUM_CHANNELS == 1) ? 8 : 2,\n                BLOCK_LOAD_DIRECT,\n                LOAD_DEFAULT,\n                true,\n                GMEM,\n                false>\n            HistogramSweepPolicy;\n    };\n\n    /// SM35\n    struct Policy350\n    {\n        // HistogramSweepPolicy\n        typedef AgentHistogramPolicy<\n                128,\n                TScale<8>::VALUE,\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                true,\n                BLEND,\n                true>\n            HistogramSweepPolicy;\n    };\n\n    /// SM50\n    struct Policy500\n    {\n        // HistogramSweepPolicy\n        typedef AgentHistogramPolicy<\n                384,\n                TScale<16>::VALUE,\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                true,\n                SMEM,\n                false>\n            HistogramSweepPolicy;\n    };\n\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies of current PTX compiler pass\n    //---------------------------------------------------------------------\n\n#if (CUB_PTX_ARCH >= 500)\n    typedef Policy500 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#else\n    typedef Policy110 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxHistogramSweepPolicy : PtxPolicy::HistogramSweepPolicy {};\n\n\n    //---------------------------------------------------------------------\n    // Utilities\n    //---------------------------------------------------------------------\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t InitConfigs(\n        int             ptx_version,\n        KernelConfig    &histogram_sweep_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        return histogram_sweep_config.template Init<PtxHistogramSweepPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 500)\n        {\n            return histogram_sweep_config.template Init<typename Policy500::HistogramSweepPolicy>();\n        }\n        else if (ptx_version >= 350)\n        {\n            return histogram_sweep_config.template Init<typename Policy350::HistogramSweepPolicy>();\n        }\n        else if (ptx_version >= 300)\n        {\n            return histogram_sweep_config.template Init<typename Policy300::HistogramSweepPolicy>();\n        }\n        else if (ptx_version >= 200)\n        {\n            return histogram_sweep_config.template Init<typename Policy200::HistogramSweepPolicy>();\n        }\n        else if (ptx_version >= 110)\n        {\n            return histogram_sweep_config.template Init<typename Policy110::HistogramSweepPolicy>();\n        }\n        else\n        {\n            // No global atomic support\n            return cudaErrorNotSupported;\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration\n     */\n    struct KernelConfig\n    {\n        int                             block_threads;\n        int                             pixels_per_thread;\n\n        template <typename BlockPolicy>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        cudaError_t Init()\n        {\n            block_threads               = BlockPolicy::BLOCK_THREADS;\n            pixels_per_thread           = BlockPolicy::PIXELS_PER_THREAD;\n\n            return cudaSuccess;\n        }\n    };\n\n\n    //---------------------------------------------------------------------\n    // Dispatch entrypoints\n    //---------------------------------------------------------------------\n\n    /**\n     * Privatization-based dispatch routine\n     */\n    template <\n        typename                            PrivatizedDecodeOpT,                            ///< The transform operator type for determining privatized counter indices from samples, one for each channel\n        typename                            OutputDecodeOpT,                                ///< The transform operator type for determining output bin-ids from privatized counter indices, one for each channel\n        typename                            DeviceHistogramInitKernelT,                     ///< Function type of cub::DeviceHistogramInitKernel\n        typename                            DeviceHistogramSweepKernelT>                    ///< Function type of cub::DeviceHistogramSweepKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t PrivatizedDispatch(\n        void*                               d_temp_storage,                                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                             temp_storage_bytes,                             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT                     d_samples,                                      ///< [in] The pointer to the input sequence of sample items. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n        CounterT*                           d_output_histograms[NUM_ACTIVE_CHANNELS],       ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_output_levels[i]</tt> - 1.\n        int                                 num_privatized_levels[NUM_ACTIVE_CHANNELS],     ///< [in] The number of bin level boundaries for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        PrivatizedDecodeOpT                 privatized_decode_op[NUM_ACTIVE_CHANNELS],      ///< [in] Transform operators for determining bin-ids from samples, one for each channel\n        int                                 num_output_levels[NUM_ACTIVE_CHANNELS],         ///< [in] The number of bin level boundaries for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        OutputDecodeOpT                     output_decode_op[NUM_ACTIVE_CHANNELS],          ///< [in] Transform operators for determining bin-ids from samples, one for each channel\n        int                                 max_num_output_bins,                            ///< [in] Maximum number of output bins in any channel\n        OffsetT                             num_row_pixels,                                 ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT                             num_rows,                                       ///< [in] The number of rows in the region of interest\n        OffsetT                             row_stride_samples,                             ///< [in] The number of samples between starts of consecutive rows in the region of interest\n        DeviceHistogramInitKernelT          histogram_init_kernel,                          ///< [in] Kernel function pointer to parameterization of cub::DeviceHistogramInitKernel\n        DeviceHistogramSweepKernelT         histogram_sweep_kernel,                         ///< [in] Kernel function pointer to parameterization of cub::DeviceHistogramSweepKernel\n        KernelConfig                        histogram_sweep_config,                         ///< [in] Dispatch parameters that match the policy that \\p histogram_sweep_kernel was compiled for\n        cudaStream_t                        stream,                                         ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                                debug_synchronous)                              ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n    #ifndef CUB_RUNTIME_ENABLED\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported);\n\n    #else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Get SM occupancy for histogram_sweep_kernel\n            int histogram_sweep_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                histogram_sweep_sm_occupancy,\n                histogram_sweep_kernel,\n                histogram_sweep_config.block_threads))) break;\n\n            // Get device occupancy for histogram_sweep_kernel\n            int histogram_sweep_occupancy = histogram_sweep_sm_occupancy * sm_count;\n\n            if (num_row_pixels * NUM_CHANNELS == row_stride_samples)\n            {\n                // Treat as a single linear array of samples\n                num_row_pixels      *= num_rows;\n                num_rows            = 1;\n                row_stride_samples  = num_row_pixels * NUM_CHANNELS;\n            }\n\n            // Get grid dimensions, trying to keep total blocks ~histogram_sweep_occupancy\n            int pixels_per_tile     = histogram_sweep_config.block_threads * histogram_sweep_config.pixels_per_thread;\n            int tiles_per_row       = int(num_row_pixels + pixels_per_tile - 1) / pixels_per_tile;\n            int blocks_per_row      = CUB_MIN(histogram_sweep_occupancy, tiles_per_row);\n            int blocks_per_col      = (blocks_per_row > 0) ?\n                                        int(CUB_MIN(histogram_sweep_occupancy / blocks_per_row, num_rows)) :\n                                        0;\n            int num_thread_blocks   = blocks_per_row * blocks_per_col;\n\n            dim3 sweep_grid_dims;\n            sweep_grid_dims.x = (unsigned int) blocks_per_row;\n            sweep_grid_dims.y = (unsigned int) blocks_per_col;\n            sweep_grid_dims.z = 1;\n\n            // Temporary storage allocation requirements\n            const int   NUM_ALLOCATIONS = NUM_ACTIVE_CHANNELS + 1;\n            void*       allocations[NUM_ALLOCATIONS];\n            size_t      allocation_sizes[NUM_ALLOCATIONS];\n\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                allocation_sizes[CHANNEL] = size_t(num_thread_blocks) * (num_privatized_levels[CHANNEL] - 1) * sizeof(CounterT);\n\n            allocation_sizes[NUM_ALLOCATIONS - 1] = GridQueue<int>::AllocationSize();\n\n            // Alias the temporary allocations from the single storage blob (or compute the necessary size of the blob)\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Construct the grid queue descriptor\n            GridQueue<int> tile_queue(allocations[NUM_ALLOCATIONS - 1]);\n\n            // Setup array wrapper for histogram channel output (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS> d_output_histograms_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                d_output_histograms_wrapper.array[CHANNEL] = d_output_histograms[CHANNEL];\n\n            // Setup array wrapper for privatized per-block histogram channel output (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS> d_privatized_histograms_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                d_privatized_histograms_wrapper.array[CHANNEL] = (CounterT*) allocations[CHANNEL];\n\n            // Setup array wrapper for sweep bin transforms (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<PrivatizedDecodeOpT, NUM_ACTIVE_CHANNELS> privatized_decode_op_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                privatized_decode_op_wrapper.array[CHANNEL] = privatized_decode_op[CHANNEL];\n\n            // Setup array wrapper for aggregation bin transforms (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<OutputDecodeOpT, NUM_ACTIVE_CHANNELS> output_decode_op_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                output_decode_op_wrapper.array[CHANNEL] = output_decode_op[CHANNEL];\n\n            // Setup array wrapper for num privatized bins (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<int, NUM_ACTIVE_CHANNELS> num_privatized_bins_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                num_privatized_bins_wrapper.array[CHANNEL] = num_privatized_levels[CHANNEL] - 1;\n\n            // Setup array wrapper for num output bins (because we can't pass static arrays as kernel parameters)\n            ArrayWrapper<int, NUM_ACTIVE_CHANNELS> num_output_bins_wrapper;\n            for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n                num_output_bins_wrapper.array[CHANNEL] = num_output_levels[CHANNEL] - 1;\n\n            int histogram_init_block_threads    = 256;\n            int histogram_init_grid_dims        = (max_num_output_bins + histogram_init_block_threads - 1) / histogram_init_block_threads;\n\n            // Log DeviceHistogramInitKernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking DeviceHistogramInitKernel<<<%d, %d, 0, %lld>>>()\\n\",\n                histogram_init_grid_dims, histogram_init_block_threads, (long long) stream);\n\n            // Invoke histogram_init_kernel\n            histogram_init_kernel<<<histogram_init_grid_dims, histogram_init_block_threads, 0, stream>>>(\n                num_output_bins_wrapper,\n                d_output_histograms_wrapper,\n                tile_queue);\n\n            // Return if empty problem\n            if ((blocks_per_row == 0) || (blocks_per_col == 0))\n                break;\n\n            // Log histogram_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking histogram_sweep_kernel<<<{%d, %d, %d}, %d, 0, %lld>>>(), %d pixels per thread, %d SM occupancy\\n\",\n                sweep_grid_dims.x, sweep_grid_dims.y, sweep_grid_dims.z,\n                histogram_sweep_config.block_threads, (long long) stream, histogram_sweep_config.pixels_per_thread, histogram_sweep_sm_occupancy);\n\n            // Invoke histogram_sweep_kernel\n            histogram_sweep_kernel<<<sweep_grid_dims, histogram_sweep_config.block_threads, 0, stream>>>(\n                d_samples,\n                num_output_bins_wrapper,\n                num_privatized_bins_wrapper,\n                d_output_histograms_wrapper,\n                d_privatized_histograms_wrapper,\n                output_decode_op_wrapper,\n                privatized_decode_op_wrapper,\n                num_row_pixels,\n                num_rows,\n                row_stride_samples,\n                tiles_per_row,\n                tile_queue);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n        }\n        while (0);\n\n        return error;\n\n    #endif // CUB_RUNTIME_ENABLED\n    }\n\n\n\n    /**\n     * Dispatch routine for HistogramRange, specialized for sample types larger than 8bit\n     */\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t DispatchRange(\n        void*               d_temp_storage,                                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n        CounterT*           d_output_histograms[NUM_ACTIVE_CHANNELS],      ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_output_levels[i]</tt> - 1.\n        int                 num_output_levels[NUM_ACTIVE_CHANNELS],     ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        LevelT              *d_levels[NUM_ACTIVE_CHANNELS],             ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        OffsetT             row_stride_samples,                         ///< [in] The number of samples between starts of consecutive rows in the region of interest\n        cudaStream_t        stream,                                     ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous,                          ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n        Int2Type<false>     is_byte_sample)                             ///< [in] Marker type indicating whether or not SampleT is a 8b type\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel dispatch configurations\n            KernelConfig histogram_sweep_config;\n            if (CubDebug(error = InitConfigs(ptx_version, histogram_sweep_config)))\n                break;\n\n            // Use the search transform op for converting samples to privatized bins\n            typedef SearchTransform<LevelT*> PrivatizedDecodeOpT;\n\n            // Use the pass-thru transform op for converting privatized bins to output bins\n            typedef PassThruTransform OutputDecodeOpT;\n\n            PrivatizedDecodeOpT     privatized_decode_op[NUM_ACTIVE_CHANNELS];\n            OutputDecodeOpT         output_decode_op[NUM_ACTIVE_CHANNELS];\n            int                     max_levels = num_output_levels[0];\n\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                privatized_decode_op[channel].Init(d_levels[channel], num_output_levels[channel]);\n                if (num_output_levels[channel] > max_levels)\n                    max_levels = num_output_levels[channel];\n            }\n            int max_num_output_bins = max_levels - 1;\n\n            // Dispatch\n            if (max_num_output_bins > MAX_PRIVATIZED_SMEM_BINS)\n            {\n                // Too many bins to keep in shared memory.\n                const int PRIVATIZED_SMEM_BINS = 0;\n\n                if (CubDebug(error = PrivatizedDispatch(\n                    d_temp_storage,\n                    temp_storage_bytes,\n                    d_samples,\n                    d_output_histograms,\n                    num_output_levels,\n                    privatized_decode_op,\n                    num_output_levels,\n                    output_decode_op,\n                    max_num_output_bins,\n                    num_row_pixels,\n                    num_rows,\n                    row_stride_samples,\n                    DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                    DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                    histogram_sweep_config,\n                    stream,\n                    debug_synchronous))) break;\n            }\n            else\n            {\n                // Dispatch shared-privatized approach\n                const int PRIVATIZED_SMEM_BINS = MAX_PRIVATIZED_SMEM_BINS;\n\n                if (CubDebug(error = PrivatizedDispatch(\n                    d_temp_storage,\n                    temp_storage_bytes,\n                    d_samples,\n                    d_output_histograms,\n                    num_output_levels,\n                    privatized_decode_op,\n                    num_output_levels,\n                    output_decode_op,\n                    max_num_output_bins,\n                    num_row_pixels,\n                    num_rows,\n                    row_stride_samples,\n                    DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                    DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                    histogram_sweep_config,\n                    stream,\n                    debug_synchronous))) break;\n            }\n\n        } while (0);\n\n        return error;\n    }\n\n\n    /**\n     * Dispatch routine for HistogramRange, specialized for 8-bit sample types (computes 256-bin privatized histograms and then reduces to user-specified levels)\n     */\n    CUB_RUNTIME_FUNCTION\n    static cudaError_t DispatchRange(\n        void*               d_temp_storage,                             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                         ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n        CounterT*           d_output_histograms[NUM_ACTIVE_CHANNELS],   ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_output_levels[i]</tt> - 1.\n        int                 num_output_levels[NUM_ACTIVE_CHANNELS],     ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        LevelT              *d_levels[NUM_ACTIVE_CHANNELS],             ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n        OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        OffsetT             row_stride_samples,                         ///< [in] The number of samples between starts of consecutive rows in the region of interest\n        cudaStream_t        stream,                                     ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous,                          ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n        Int2Type<true>      is_byte_sample)                             ///< [in] Marker type indicating whether or not SampleT is a 8b type\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel dispatch configurations\n            KernelConfig histogram_sweep_config;\n            if (CubDebug(error = InitConfigs(ptx_version, histogram_sweep_config)))\n                break;\n\n            // Use the pass-thru transform op for converting samples to privatized bins\n            typedef PassThruTransform PrivatizedDecodeOpT;\n\n            // Use the search transform op for converting privatized bins to output bins\n            typedef SearchTransform<LevelT*> OutputDecodeOpT;\n\n            int                         num_privatized_levels[NUM_ACTIVE_CHANNELS];\n            PrivatizedDecodeOpT         privatized_decode_op[NUM_ACTIVE_CHANNELS];\n            OutputDecodeOpT             output_decode_op[NUM_ACTIVE_CHANNELS];\n            int                         max_levels = num_output_levels[0];              // Maximum number of levels in any channel\n\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                num_privatized_levels[channel] = 257;\n                output_decode_op[channel].Init(d_levels[channel], num_output_levels[channel]);\n\n                if (num_output_levels[channel] > max_levels)\n                    max_levels = num_output_levels[channel];\n            }\n            int max_num_output_bins = max_levels - 1;\n\n            const int PRIVATIZED_SMEM_BINS = 256;\n\n            if (CubDebug(error = PrivatizedDispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_samples,\n                d_output_histograms,\n                num_privatized_levels,\n                privatized_decode_op,\n                num_output_levels,\n                output_decode_op,\n                max_num_output_bins,\n                num_row_pixels,\n                num_rows,\n                row_stride_samples,\n                DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                histogram_sweep_config,\n                stream,\n                debug_synchronous))) break;\n\n        } while (0);\n\n        return error;\n    }\n\n\n    /**\n     * Dispatch routine for HistogramEven, specialized for sample types larger than 8-bit\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t DispatchEven(\n        void*               d_temp_storage,                            ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the input sequence of sample items. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n        CounterT*           d_output_histograms[NUM_ACTIVE_CHANNELS],  ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_output_levels[i]</tt> - 1.\n        int                 num_output_levels[NUM_ACTIVE_CHANNELS],     ///< [in] The number of bin level boundaries for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        LevelT              lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n        LevelT              upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n        OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        OffsetT             row_stride_samples,                         ///< [in] The number of samples between starts of consecutive rows in the region of interest\n        cudaStream_t        stream,                                     ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous,                          ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n        Int2Type<false>     is_byte_sample)                             ///< [in] Marker type indicating whether or not SampleT is a 8b type\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel dispatch configurations\n            KernelConfig histogram_sweep_config;\n            if (CubDebug(error = InitConfigs(ptx_version, histogram_sweep_config)))\n                break;\n\n            // Use the scale transform op for converting samples to privatized bins\n            typedef ScaleTransform PrivatizedDecodeOpT;\n\n            // Use the pass-thru transform op for converting privatized bins to output bins\n            typedef PassThruTransform OutputDecodeOpT;\n\n            PrivatizedDecodeOpT         privatized_decode_op[NUM_ACTIVE_CHANNELS];\n            OutputDecodeOpT             output_decode_op[NUM_ACTIVE_CHANNELS];\n            int                         max_levels = num_output_levels[0];\n\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                int     bins    = num_output_levels[channel] - 1;\n                LevelT  scale   = (upper_level[channel] - lower_level[channel]) / bins;\n\n                privatized_decode_op[channel].Init(num_output_levels[channel], upper_level[channel], lower_level[channel], scale);\n\n                if (num_output_levels[channel] > max_levels)\n                    max_levels = num_output_levels[channel];\n            }\n            int max_num_output_bins = max_levels - 1;\n\n            if (max_num_output_bins > MAX_PRIVATIZED_SMEM_BINS)\n            {\n                // Dispatch shared-privatized approach\n                const int PRIVATIZED_SMEM_BINS = 0;\n\n                if (CubDebug(error = PrivatizedDispatch(\n                    d_temp_storage,\n                    temp_storage_bytes,\n                    d_samples,\n                    d_output_histograms,\n                    num_output_levels,\n                    privatized_decode_op,\n                    num_output_levels,\n                    output_decode_op,\n                    max_num_output_bins,\n                    num_row_pixels,\n                    num_rows,\n                    row_stride_samples,\n                    DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                    DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                    histogram_sweep_config,\n                    stream,\n                    debug_synchronous))) break;\n            }\n            else\n            {\n                // Dispatch shared-privatized approach\n                const int PRIVATIZED_SMEM_BINS = MAX_PRIVATIZED_SMEM_BINS;\n\n                if (CubDebug(error = PrivatizedDispatch(\n                    d_temp_storage,\n                    temp_storage_bytes,\n                    d_samples,\n                    d_output_histograms,\n                    num_output_levels,\n                    privatized_decode_op,\n                    num_output_levels,\n                    output_decode_op,\n                    max_num_output_bins,\n                    num_row_pixels,\n                    num_rows,\n                    row_stride_samples,\n                    DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                    DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                    histogram_sweep_config,\n                    stream,\n                    debug_synchronous))) break;\n            }\n        }\n        while (0);\n\n        return error;\n    }\n\n\n    /**\n     * Dispatch routine for HistogramEven, specialized for 8-bit sample types (computes 256-bin privatized histograms and then reduces to user-specified levels)\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t DispatchEven(\n        void*               d_temp_storage,                            ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,                        ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SampleIteratorT     d_samples,                                  ///< [in] The pointer to the input sequence of sample items. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n        CounterT*           d_output_histograms[NUM_ACTIVE_CHANNELS],  ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_output_levels[i]</tt> - 1.\n        int                 num_output_levels[NUM_ACTIVE_CHANNELS],     ///< [in] The number of bin level boundaries for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_output_levels[i]</tt> - 1.\n        LevelT              lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n        LevelT              upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n        OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n        OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n        OffsetT             row_stride_samples,                         ///< [in] The number of samples between starts of consecutive rows in the region of interest\n        cudaStream_t        stream,                                     ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous,                          ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n        Int2Type<true>      is_byte_sample)                             ///< [in] Marker type indicating whether or not SampleT is a 8b type\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel dispatch configurations\n            KernelConfig histogram_sweep_config;\n            if (CubDebug(error = InitConfigs(ptx_version, histogram_sweep_config)))\n                break;\n\n            // Use the pass-thru transform op for converting samples to privatized bins\n            typedef PassThruTransform PrivatizedDecodeOpT;\n\n            // Use the scale transform op for converting privatized bins to output bins\n            typedef ScaleTransform OutputDecodeOpT;\n\n            int                     num_privatized_levels[NUM_ACTIVE_CHANNELS];\n            PrivatizedDecodeOpT     privatized_decode_op[NUM_ACTIVE_CHANNELS];\n            OutputDecodeOpT         output_decode_op[NUM_ACTIVE_CHANNELS];\n            int                     max_levels = num_output_levels[0];\n\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                num_privatized_levels[channel] = 257;\n\n                int     bins    = num_output_levels[channel] - 1;\n                LevelT  scale   = (upper_level[channel] - lower_level[channel]) / bins;\n                output_decode_op[channel].Init(num_output_levels[channel], upper_level[channel], lower_level[channel], scale);\n\n                if (num_output_levels[channel] > max_levels)\n                    max_levels = num_output_levels[channel];\n            }\n            int max_num_output_bins = max_levels - 1;\n\n            const int PRIVATIZED_SMEM_BINS = 256;\n\n            if (CubDebug(error = PrivatizedDispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_samples,\n                d_output_histograms,\n                num_privatized_levels,\n                privatized_decode_op,\n                num_output_levels,\n                output_decode_op,\n                max_num_output_bins,\n                num_row_pixels,\n                num_rows,\n                row_stride_samples,\n                DeviceHistogramInitKernel<NUM_ACTIVE_CHANNELS, CounterT, OffsetT>,\n                DeviceHistogramSweepKernel<PtxHistogramSweepPolicy, PRIVATIZED_SMEM_BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, PrivatizedDecodeOpT, OutputDecodeOpT, OffsetT>,\n                histogram_sweep_config,\n                stream,\n                debug_synchronous))) break;\n\n        }\n        while (0);\n\n        return error;\n    }\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_radix_sort.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceRadixSort provides device-wide, parallel operations for computing a radix sort across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"../../agent/agent_radix_sort_upsweep.cuh\"\n#include \"../../agent/agent_radix_sort_downsweep.cuh\"\n#include \"../../agent/agent_scan.cuh\"\n#include \"../../block/block_radix_sort.cuh\"\n#include \"../../grid/grid_even_share.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_debug.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Upsweep digit-counting kernel entry point (multi-block).  Computes privatized digit histograms, one per block.\n */\ntemplate <\n    typename                ChainedPolicyT,                 ///< Chained tuning policy\n    bool                    ALT_DIGIT_BITS,                 ///< Whether or not to use the alternate (lower-bits) policy\n    bool                    IS_DESCENDING,                  ///< Whether or not the sorted-order is high-to-low\n    typename                KeyT,                           ///< Key type\n    typename                OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int((ALT_DIGIT_BITS) ?\n    ChainedPolicyT::ActivePolicy::AltUpsweepPolicy::BLOCK_THREADS :\n    ChainedPolicyT::ActivePolicy::UpsweepPolicy::BLOCK_THREADS))\n__global__ void DeviceRadixSortUpsweepKernel(\n    const KeyT              *d_keys,                        ///< [in] Input keys buffer\n    OffsetT                 *d_spine,                       ///< [out] Privatized (per block) digit histograms (striped, i.e., 0s counts from each block, then 1s counts from each block, etc.)\n    OffsetT                 /*num_items*/,                  ///< [in] Total number of input data items\n    int                     current_bit,                    ///< [in] Bit position of current radix digit\n    int                     num_bits,                       ///< [in] Number of bits of current radix digit\n    GridEvenShare<OffsetT>  even_share)                     ///< [in] Even-share descriptor for mapan equal number of tiles onto each thread block\n{\n    enum {\n        TILE_ITEMS = ChainedPolicyT::ActivePolicy::AltUpsweepPolicy::BLOCK_THREADS *\n                        ChainedPolicyT::ActivePolicy::AltUpsweepPolicy::ITEMS_PER_THREAD\n    };\n\n    // Parameterize AgentRadixSortUpsweep type for the current configuration\n    typedef AgentRadixSortUpsweep<\n            typename If<(ALT_DIGIT_BITS),\n                typename ChainedPolicyT::ActivePolicy::AltUpsweepPolicy,\n                typename ChainedPolicyT::ActivePolicy::UpsweepPolicy>::Type,\n            KeyT,\n            OffsetT>\n        AgentRadixSortUpsweepT;\n\n    // Shared memory storage\n    __shared__ typename AgentRadixSortUpsweepT::TempStorage temp_storage;\n\n    // Initialize GRID_MAPPING_RAKE even-share descriptor for this thread block\n    even_share.template BlockInit<TILE_ITEMS, GRID_MAPPING_RAKE>();\n\n    AgentRadixSortUpsweepT upsweep(temp_storage, d_keys, current_bit, num_bits);\n\n    upsweep.ProcessRegion(even_share.block_offset, even_share.block_end);\n\n    CTA_SYNC();\n\n    // Write out digit counts (striped)\n    upsweep.ExtractCounts<IS_DESCENDING>(d_spine, gridDim.x, blockIdx.x);\n}\n\n\n/**\n * Spine scan kernel entry point (single-block).  Computes an exclusive prefix sum over the privatized digit histograms\n */\ntemplate <\n    typename                ChainedPolicyT,                 ///< Chained tuning policy\n    typename                OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int(ChainedPolicyT::ActivePolicy::ScanPolicy::BLOCK_THREADS), 1)\n__global__ void RadixSortScanBinsKernel(\n    OffsetT                 *d_spine,                       ///< [in,out] Privatized (per block) digit histograms (striped, i.e., 0s counts from each block, then 1s counts from each block, etc.)\n    int                     num_counts)                     ///< [in] Total number of bin-counts\n{\n    // Parameterize the AgentScan type for the current configuration\n    typedef AgentScan<\n            typename ChainedPolicyT::ActivePolicy::ScanPolicy,\n            OffsetT*,\n            OffsetT*,\n            cub::Sum,\n            OffsetT,\n            OffsetT>\n        AgentScanT;\n\n    // Shared memory storage\n    __shared__ typename AgentScanT::TempStorage temp_storage;\n\n    // Block scan instance\n    AgentScanT block_scan(temp_storage, d_spine, d_spine, cub::Sum(), OffsetT(0)) ;\n\n    // Process full input tiles\n    int block_offset = 0;\n    BlockScanRunningPrefixOp<OffsetT, Sum> prefix_op(0, Sum());\n    while (block_offset + AgentScanT::TILE_ITEMS <= num_counts)\n    {\n        block_scan.template ConsumeTile<false, false>(block_offset, prefix_op);\n        block_offset += AgentScanT::TILE_ITEMS;\n    }\n}\n\n\n/**\n * Downsweep pass kernel entry point (multi-block).  Scatters keys (and values) into corresponding bins for the current digit place.\n */\ntemplate <\n    typename                ChainedPolicyT,                 ///< Chained tuning policy\n    bool                    ALT_DIGIT_BITS,                 ///< Whether or not to use the alternate (lower-bits) policy\n    bool                    IS_DESCENDING,                  ///< Whether or not the sorted-order is high-to-low\n    typename                KeyT,                           ///< Key type\n    typename                ValueT,                         ///< Value type\n    typename                OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int((ALT_DIGIT_BITS) ?\n    ChainedPolicyT::ActivePolicy::AltDownsweepPolicy::BLOCK_THREADS :\n    ChainedPolicyT::ActivePolicy::DownsweepPolicy::BLOCK_THREADS))\n__global__ void DeviceRadixSortDownsweepKernel(\n    const KeyT              *d_keys_in,                     ///< [in] Input keys buffer\n    KeyT                    *d_keys_out,                    ///< [in] Output keys buffer\n    const ValueT            *d_values_in,                   ///< [in] Input values buffer\n    ValueT                  *d_values_out,                  ///< [in] Output values buffer\n    OffsetT                 *d_spine,                       ///< [in] Scan of privatized (per block) digit histograms (striped, i.e., 0s counts from each block, then 1s counts from each block, etc.)\n    OffsetT                 num_items,                      ///< [in] Total number of input data items\n    int                     current_bit,                    ///< [in] Bit position of current radix digit\n    int                     num_bits,                       ///< [in] Number of bits of current radix digit\n    GridEvenShare<OffsetT>  even_share)                     ///< [in] Even-share descriptor for mapan equal number of tiles onto each thread block\n{\n    enum {\n        TILE_ITEMS = ChainedPolicyT::ActivePolicy::AltUpsweepPolicy::BLOCK_THREADS *\n                        ChainedPolicyT::ActivePolicy::AltUpsweepPolicy::ITEMS_PER_THREAD\n    };\n\n    // Parameterize AgentRadixSortDownsweep type for the current configuration\n    typedef AgentRadixSortDownsweep<\n            typename If<(ALT_DIGIT_BITS),\n                typename ChainedPolicyT::ActivePolicy::AltDownsweepPolicy,\n                typename ChainedPolicyT::ActivePolicy::DownsweepPolicy>::Type,\n            IS_DESCENDING,\n            KeyT,\n            ValueT,\n            OffsetT>\n        AgentRadixSortDownsweepT;\n\n    // Shared memory storage\n    __shared__  typename AgentRadixSortDownsweepT::TempStorage temp_storage;\n\n    // Initialize even-share descriptor for this thread block\n    even_share.template BlockInit<TILE_ITEMS, GRID_MAPPING_RAKE>();\n\n    // Process input tiles\n    AgentRadixSortDownsweepT(temp_storage, num_items, d_spine, d_keys_in, d_keys_out, d_values_in, d_values_out, current_bit, num_bits).ProcessRegion(\n        even_share.block_offset,\n        even_share.block_end);\n}\n\n\n/**\n * Single pass kernel entry point (single-block).  Fully sorts a tile of input.\n */\ntemplate <\n    typename                ChainedPolicyT,                 ///< Chained tuning policy\n    bool                    IS_DESCENDING,                  ///< Whether or not the sorted-order is high-to-low\n    typename                KeyT,                           ///< Key type\n    typename                ValueT,                         ///< Value type\n    typename                OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int(ChainedPolicyT::ActivePolicy::SingleTilePolicy::BLOCK_THREADS), 1)\n__global__ void DeviceRadixSortSingleTileKernel(\n    const KeyT              *d_keys_in,                     ///< [in] Input keys buffer\n    KeyT                    *d_keys_out,                    ///< [in] Output keys buffer\n    const ValueT            *d_values_in,                   ///< [in] Input values buffer\n    ValueT                  *d_values_out,                  ///< [in] Output values buffer\n    OffsetT                 num_items,                      ///< [in] Total number of input data items\n    int                     current_bit,                    ///< [in] Bit position of current radix digit\n    int                     end_bit)                        ///< [in] The past-the-end (most-significant) bit index needed for key comparison\n{\n    // Constants\n    enum\n    {\n        BLOCK_THREADS           = ChainedPolicyT::ActivePolicy::SingleTilePolicy::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = ChainedPolicyT::ActivePolicy::SingleTilePolicy::ITEMS_PER_THREAD,\n        KEYS_ONLY               = Equals<ValueT, NullType>::VALUE,\n    };\n\n    // BlockRadixSort type\n    typedef BlockRadixSort<\n            KeyT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            ValueT,\n            ChainedPolicyT::ActivePolicy::SingleTilePolicy::RADIX_BITS,\n            (ChainedPolicyT::ActivePolicy::SingleTilePolicy::RANK_ALGORITHM == RADIX_RANK_MEMOIZE),\n            ChainedPolicyT::ActivePolicy::SingleTilePolicy::SCAN_ALGORITHM>\n        BlockRadixSortT;\n\n    // BlockLoad type (keys)\n    typedef BlockLoad<\n        KeyT,\n        BLOCK_THREADS,\n        ITEMS_PER_THREAD,\n        ChainedPolicyT::ActivePolicy::SingleTilePolicy::LOAD_ALGORITHM> BlockLoadKeys;\n\n    // BlockLoad type (values)\n    typedef BlockLoad<\n        ValueT,\n        BLOCK_THREADS,\n        ITEMS_PER_THREAD,\n        ChainedPolicyT::ActivePolicy::SingleTilePolicy::LOAD_ALGORITHM> BlockLoadValues;\n\n    // Unsigned word for key bits\n    typedef typename Traits<KeyT>::UnsignedBits UnsignedBitsT;\n\n    // Shared memory storage\n    __shared__ union TempStorage\n    {\n        typename BlockRadixSortT::TempStorage       sort;\n        typename BlockLoadKeys::TempStorage         load_keys;\n        typename BlockLoadValues::TempStorage       load_values;\n\n    } temp_storage;\n\n    // Keys and values for the block\n    KeyT            keys[ITEMS_PER_THREAD];\n    ValueT          values[ITEMS_PER_THREAD];\n\n    // Get default (min/max) value for out-of-bounds keys\n    UnsignedBitsT   default_key_bits = (IS_DESCENDING) ? Traits<KeyT>::LOWEST_KEY : Traits<KeyT>::MAX_KEY;\n    KeyT            default_key = reinterpret_cast<KeyT&>(default_key_bits);\n\n    // Load keys\n    BlockLoadKeys(temp_storage.load_keys).Load(d_keys_in, keys, num_items, default_key);\n\n    CTA_SYNC();\n\n    // Load values\n    if (!KEYS_ONLY)\n    {\n        BlockLoadValues(temp_storage.load_values).Load(d_values_in, values, num_items);\n\n        CTA_SYNC();\n    }\n\n    // Sort tile\n    BlockRadixSortT(temp_storage.sort).SortBlockedToStriped(\n        keys,\n        values,\n        current_bit,\n        end_bit,\n        Int2Type<IS_DESCENDING>(),\n        Int2Type<KEYS_ONLY>());\n\n    // Store keys and values\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n    {\n        int item_offset = ITEM * BLOCK_THREADS + threadIdx.x;\n        if (item_offset < num_items)\n        {\n            d_keys_out[item_offset] = keys[ITEM];\n            if (!KEYS_ONLY)\n                d_values_out[item_offset] = values[ITEM];\n        }\n    }\n}\n\n\n/**\n * Segmented radix sorting pass (one block per segment)\n */\ntemplate <\n    typename                ChainedPolicyT,                 ///< Chained tuning policy\n    bool                    ALT_DIGIT_BITS,                 ///< Whether or not to use the alternate (lower-bits) policy\n    bool                    IS_DESCENDING,                  ///< Whether or not the sorted-order is high-to-low\n    typename                KeyT,                           ///< Key type\n    typename                ValueT,                         ///< Value type\n    typename                OffsetIteratorT,                ///< Random-access input iterator type for reading segment offsets \\iterator\n    typename                OffsetT>                        ///< Signed integer type for global offsets\n__launch_bounds__ (int((ALT_DIGIT_BITS) ?\n    ChainedPolicyT::ActivePolicy::AltSegmentedPolicy::BLOCK_THREADS :\n    ChainedPolicyT::ActivePolicy::SegmentedPolicy::BLOCK_THREADS))\n__global__ void DeviceSegmentedRadixSortKernel(\n    const KeyT              *d_keys_in,                     ///< [in] Input keys buffer\n    KeyT                    *d_keys_out,                    ///< [in] Output keys buffer\n    const ValueT            *d_values_in,                   ///< [in] Input values buffer\n    ValueT                  *d_values_out,                  ///< [in] Output values buffer\n    OffsetIteratorT         d_begin_offsets,                ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n    OffsetIteratorT         d_end_offsets,                  ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n    int                     /*num_segments*/,               ///< [in] The number of segments that comprise the sorting data\n    int                     current_bit,                    ///< [in] Bit position of current radix digit\n    int                     pass_bits)                      ///< [in] Number of bits of current radix digit\n{\n    //\n    // Constants\n    //\n\n    typedef typename If<(ALT_DIGIT_BITS),\n        typename ChainedPolicyT::ActivePolicy::AltSegmentedPolicy,\n        typename ChainedPolicyT::ActivePolicy::SegmentedPolicy>::Type SegmentedPolicyT;\n\n    enum\n    {\n        BLOCK_THREADS       = SegmentedPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = SegmentedPolicyT::ITEMS_PER_THREAD,\n        RADIX_BITS          = SegmentedPolicyT::RADIX_BITS,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n        RADIX_DIGITS        = 1 << RADIX_BITS,\n        KEYS_ONLY           = Equals<ValueT, NullType>::VALUE,\n    };\n\n    // Upsweep type\n    typedef AgentRadixSortUpsweep<\n            AgentRadixSortUpsweepPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, SegmentedPolicyT::LOAD_MODIFIER, RADIX_BITS>,\n            KeyT,\n            OffsetT>\n        BlockUpsweepT;\n\n    // Digit-scan type\n    typedef BlockScan<OffsetT, BLOCK_THREADS> DigitScanT;\n\n    // Downsweep type\n    typedef AgentRadixSortDownsweep<SegmentedPolicyT, IS_DESCENDING, KeyT, ValueT, OffsetT> BlockDownsweepT;\n\n    enum\n    {\n        /// Number of bin-starting offsets tracked per thread\n        BINS_TRACKED_PER_THREAD = BlockDownsweepT::BINS_TRACKED_PER_THREAD\n    };\n\n    //\n    // Process input tiles\n    //\n\n    // Shared memory storage\n    __shared__ union\n    {\n        typename BlockUpsweepT::TempStorage     upsweep;\n        typename BlockDownsweepT::TempStorage   downsweep;\n        struct\n        {\n            volatile OffsetT                        reverse_counts_in[RADIX_DIGITS];\n            volatile OffsetT                        reverse_counts_out[RADIX_DIGITS];\n            typename DigitScanT::TempStorage        scan;\n        };\n\n    } temp_storage;\n\n    OffsetT segment_begin   = d_begin_offsets[blockIdx.x];\n    OffsetT segment_end     = d_end_offsets[blockIdx.x];\n    OffsetT num_items       = segment_end - segment_begin;\n\n    // Check if empty segment\n    if (num_items <= 0)\n        return;\n\n    // Upsweep\n    BlockUpsweepT upsweep(temp_storage.upsweep, d_keys_in, current_bit, pass_bits);\n    upsweep.ProcessRegion(segment_begin, segment_end);\n\n    CTA_SYNC();\n\n    // The count of each digit value in this pass (valid in the first RADIX_DIGITS threads)\n    OffsetT bin_count[BINS_TRACKED_PER_THREAD];\n    upsweep.ExtractCounts(bin_count);\n\n    CTA_SYNC();\n\n    if (IS_DESCENDING)\n    {\n        // Reverse bin counts\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n                temp_storage.reverse_counts_in[bin_idx] = bin_count[track];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n                bin_count[track] = temp_storage.reverse_counts_in[RADIX_DIGITS - bin_idx - 1];\n        }\n    }\n\n    // Scan\n    OffsetT bin_offset[BINS_TRACKED_PER_THREAD];     // The global scatter base offset for each digit value in this pass (valid in the first RADIX_DIGITS threads)\n    DigitScanT(temp_storage.scan).ExclusiveSum(bin_count, bin_offset);\n\n    #pragma unroll\n    for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n    {\n        bin_offset[track] += segment_begin;\n    }\n\n    if (IS_DESCENDING)\n    {\n        // Reverse bin offsets\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n                temp_storage.reverse_counts_out[threadIdx.x] = bin_offset[track];\n        }\n\n        CTA_SYNC();\n\n        #pragma unroll\n        for (int track = 0; track < BINS_TRACKED_PER_THREAD; ++track)\n        {\n            int bin_idx = (threadIdx.x * BINS_TRACKED_PER_THREAD) + track;\n\n            if ((BLOCK_THREADS == RADIX_DIGITS) || (bin_idx < RADIX_DIGITS))\n                bin_offset[track] = temp_storage.reverse_counts_out[RADIX_DIGITS - bin_idx - 1];\n        }\n    }\n\n    CTA_SYNC();\n\n    // Downsweep\n    BlockDownsweepT downsweep(temp_storage.downsweep, bin_offset, num_items, d_keys_in, d_keys_out, d_values_in, d_values_out, current_bit, pass_bits);\n    downsweep.ProcessRegion(segment_begin, segment_end);\n}\n\n\n\n/******************************************************************************\n * Policy\n ******************************************************************************/\n\n/**\n * Tuning policy for kernel specialization\n */\ntemplate <\n    typename KeyT,          ///< Key type\n    typename ValueT,        ///< Value type\n    typename OffsetT>       ///< Signed integer type for global offsets\nstruct DeviceRadixSortPolicy\n{\n    //------------------------------------------------------------------------------\n    // Constants\n    //------------------------------------------------------------------------------\n\n    enum\n    {\n        // Whether this is a keys-only (or key-value) sort\n        KEYS_ONLY = (Equals<ValueT, NullType>::VALUE),\n\n        // Relative size of KeyT type to a 4-byte word\n        SCALE_FACTOR_4B = (CUB_MAX(sizeof(KeyT), sizeof(ValueT)) + 3) / 4,\n    };\n\n    //------------------------------------------------------------------------------\n    // Architecture-specific tuning policies\n    //------------------------------------------------------------------------------\n\n    /// SM13\n    struct Policy130 : ChainedPolicy<130, Policy130, Policy130>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 5,\n            ALT_RADIX_BITS          = PRIMARY_RADIX_BITS - 1,\n        };\n\n        // Keys-only upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 19 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>   UpsweepPolicyKeys;\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 15 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>       AltUpsweepPolicyKeys;\n\n        // Key-value pairs upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 19 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>   UpsweepPolicyPairs;\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 15 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>       AltUpsweepPolicyPairs;\n\n        // Upsweep policies\n        typedef typename If<KEYS_ONLY, UpsweepPolicyKeys, UpsweepPolicyPairs>::Type         UpsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltUpsweepPolicyKeys, AltUpsweepPolicyPairs>::Type   AltUpsweepPolicy;\n\n        // Scan policy\n        typedef AgentScanPolicy <256, 4, BLOCK_LOAD_VECTORIZE, LOAD_DEFAULT, BLOCK_STORE_VECTORIZE, BLOCK_SCAN_WARP_SCANS> ScanPolicy;\n\n        // Keys-only downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <64, CUB_MAX(1, 19 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>    DownsweepPolicyKeys;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 15 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>       AltDownsweepPolicyKeys;\n\n        // Key-value pairs downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <64, CUB_MAX(1, 19 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>    DownsweepPolicyPairs;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 15 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>       AltDownsweepPolicyPairs;\n\n        // Downsweep policies\n        typedef typename If<KEYS_ONLY, DownsweepPolicyKeys, DownsweepPolicyPairs>::Type         DownsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltDownsweepPolicyKeys, AltDownsweepPolicyPairs>::Type   AltDownsweepPolicy;\n\n        // Single-tile policy\n        typedef DownsweepPolicy SingleTilePolicy;\n\n        // Segmented policies\n        typedef DownsweepPolicy     SegmentedPolicy;\n        typedef AltDownsweepPolicy  AltSegmentedPolicy;\n    };\n\n    /// SM20\n    struct Policy200 : ChainedPolicy<200, Policy200, Policy130>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 5,\n            ALT_RADIX_BITS          = PRIMARY_RADIX_BITS - 1,\n        };\n\n        // Keys-only upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <64, CUB_MAX(1, 18 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>    UpsweepPolicyKeys;\n        typedef AgentRadixSortUpsweepPolicy <64, CUB_MAX(1, 18 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>        AltUpsweepPolicyKeys;\n\n        // Key-value pairs upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 13 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>   UpsweepPolicyPairs;\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 13 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>       AltUpsweepPolicyPairs;\n\n        // Upsweep policies\n        typedef typename If<KEYS_ONLY, UpsweepPolicyKeys, UpsweepPolicyPairs>::Type         UpsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltUpsweepPolicyKeys, AltUpsweepPolicyPairs>::Type   AltUpsweepPolicy;\n\n        // Scan policy\n        typedef AgentScanPolicy <512, 4, BLOCK_LOAD_VECTORIZE, LOAD_DEFAULT, BLOCK_STORE_VECTORIZE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Keys-only downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <64, CUB_MAX(1, 18 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>    DownsweepPolicyKeys;\n        typedef AgentRadixSortDownsweepPolicy <64, CUB_MAX(1, 18 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>        AltDownsweepPolicyKeys;\n\n        // Key-value pairs downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 13 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>   DownsweepPolicyPairs;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 13 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>       AltDownsweepPolicyPairs;\n\n        // Downsweep policies\n        typedef typename If<KEYS_ONLY, DownsweepPolicyKeys, DownsweepPolicyPairs>::Type         DownsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltDownsweepPolicyKeys, AltDownsweepPolicyPairs>::Type   AltDownsweepPolicy;\n\n        // Single-tile policy\n        typedef DownsweepPolicy SingleTilePolicy;\n\n        // Segmented policies\n        typedef DownsweepPolicy     SegmentedPolicy;\n        typedef AltDownsweepPolicy  AltSegmentedPolicy;\n    };\n\n    /// SM30\n    struct Policy300 : ChainedPolicy<300, Policy300, Policy200>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 5,\n            ALT_RADIX_BITS          = PRIMARY_RADIX_BITS - 1,\n        };\n\n        // Keys-only upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <256, CUB_MAX(1, 7 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>    UpsweepPolicyKeys;\n        typedef AgentRadixSortUpsweepPolicy <256, CUB_MAX(1, 7 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>        AltUpsweepPolicyKeys;\n\n        // Key-value pairs upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <256, CUB_MAX(1, 5 / SCALE_FACTOR_4B), LOAD_DEFAULT, PRIMARY_RADIX_BITS>    UpsweepPolicyPairs;\n        typedef AgentRadixSortUpsweepPolicy <256, CUB_MAX(1, 5 / SCALE_FACTOR_4B), LOAD_DEFAULT, ALT_RADIX_BITS>        AltUpsweepPolicyPairs;\n\n        // Upsweep policies\n        typedef typename If<KEYS_ONLY, UpsweepPolicyKeys, UpsweepPolicyPairs>::Type         UpsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltUpsweepPolicyKeys, AltUpsweepPolicyPairs>::Type   AltUpsweepPolicy;\n\n        // Scan policy\n        typedef AgentScanPolicy <1024, 4, BLOCK_LOAD_VECTORIZE, LOAD_DEFAULT, BLOCK_STORE_VECTORIZE, BLOCK_SCAN_WARP_SCANS> ScanPolicy;\n\n        // Keys-only downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 14 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>   DownsweepPolicyKeys;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 14 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>       AltDownsweepPolicyKeys;\n\n        // Key-value pairs downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 10 / SCALE_FACTOR_4B), BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>    DownsweepPolicyPairs;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 10 / SCALE_FACTOR_4B), BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, ALT_RADIX_BITS>        AltDownsweepPolicyPairs;\n\n        // Downsweep policies\n        typedef typename If<KEYS_ONLY, DownsweepPolicyKeys, DownsweepPolicyPairs>::Type         DownsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltDownsweepPolicyKeys, AltDownsweepPolicyPairs>::Type   AltDownsweepPolicy;\n\n        // Single-tile policy\n        typedef DownsweepPolicy SingleTilePolicy;\n\n        // Segmented policies\n        typedef DownsweepPolicy     SegmentedPolicy;\n        typedef AltDownsweepPolicy  AltSegmentedPolicy;\n    };\n\n\n    /// SM35\n    struct Policy350 : ChainedPolicy<350, Policy350, Policy300>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 6,    // 1.72B 32b keys/s, 1.17B 32b pairs/s, 1.55B 32b segmented keys/s (K40m)\n        };\n\n        // Scan policy\n        typedef AgentScanPolicy <1024, 4, BLOCK_LOAD_VECTORIZE, LOAD_DEFAULT, BLOCK_STORE_VECTORIZE, BLOCK_SCAN_WARP_SCANS> ScanPolicy;\n\n        // Keys-only downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <128,   CUB_MAX(1, 9 / SCALE_FACTOR_4B), BLOCK_LOAD_WARP_TRANSPOSE, LOAD_LDG, RADIX_RANK_MATCH, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS> DownsweepPolicyKeys;\n        typedef AgentRadixSortDownsweepPolicy <64,   CUB_MAX(1, 18 / SCALE_FACTOR_4B), BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS - 1> AltDownsweepPolicyKeys;\n\n        // Key-value pairs downsweep policies\n        typedef DownsweepPolicyKeys DownsweepPolicyPairs;\n        typedef AgentRadixSortDownsweepPolicy <128,  CUB_MAX(1, 15 / SCALE_FACTOR_4B), BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS - 1> AltDownsweepPolicyPairs;\n\n        // Downsweep policies\n        typedef typename If<KEYS_ONLY, DownsweepPolicyKeys, DownsweepPolicyPairs>::Type DownsweepPolicy;\n        typedef typename If<KEYS_ONLY, AltDownsweepPolicyKeys, AltDownsweepPolicyPairs>::Type AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef DownsweepPolicy UpsweepPolicy;\n        typedef AltDownsweepPolicy AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef DownsweepPolicy SingleTilePolicy;\n\n        // Segmented policies\n        typedef DownsweepPolicy     SegmentedPolicy;\n        typedef AltDownsweepPolicy  AltSegmentedPolicy;\n\n\n    };\n\n\n    /// SM50\n    struct Policy500 : ChainedPolicy<500, Policy500, Policy350>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 7,    // 3.5B 32b keys/s, 1.92B 32b pairs/s (TitanX)\n            SINGLE_TILE_RADIX_BITS  = 6,\n            SEGMENTED_RADIX_BITS    = 6,    // 3.1B 32b segmented keys/s (TitanX)\n        };\n\n        // ScanPolicy\n        typedef AgentScanPolicy <512, 23, BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, BLOCK_STORE_WARP_TRANSPOSE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <160, CUB_MAX(1, 39 / SCALE_FACTOR_4B),  BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_BASIC, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>  DownsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 16 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_RAKING_MEMOIZE, PRIMARY_RADIX_BITS - 1>   AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef DownsweepPolicy UpsweepPolicy;\n        typedef AltDownsweepPolicy AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 19 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SINGLE_TILE_RADIX_BITS> SingleTilePolicy;\n\n        // Segmented policies\n        typedef AgentRadixSortDownsweepPolicy <192, CUB_MAX(1, 31 / SCALE_FACTOR_4B),  BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS>   SegmentedPolicy;\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 11 / SCALE_FACTOR_4B),  BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS - 1>       AltSegmentedPolicy;\n    };\n\n\n    /// SM60 (GP100)\n    struct Policy600 : ChainedPolicy<600, Policy600, Policy500>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 7,    // 6.9B 32b keys/s (Quadro P100)\n            SINGLE_TILE_RADIX_BITS  = 6,\n            SEGMENTED_RADIX_BITS    = 6,    // 5.9B 32b segmented keys/s (Quadro P100)\n        };\n\n        // ScanPolicy\n        typedef AgentScanPolicy <512, 23, BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, BLOCK_STORE_WARP_TRANSPOSE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 25 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MATCH, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>   DownsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <192, CUB_MAX(1, 39 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS - 1>   AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef DownsweepPolicy UpsweepPolicy;\n        typedef AltDownsweepPolicy AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 19 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SINGLE_TILE_RADIX_BITS>          SingleTilePolicy;\n\n        // Segmented policies\n        typedef AgentRadixSortDownsweepPolicy <192, CUB_MAX(1, 39 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS>     SegmentedPolicy;\n        typedef AgentRadixSortDownsweepPolicy <384, CUB_MAX(1, 11 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS - 1> AltSegmentedPolicy;\n\n    };\n\n\n    /// SM61 (GP104)\n    struct Policy610 : ChainedPolicy<610, Policy610, Policy600>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 7,    // 3.4B 32b keys/s, 1.83B 32b pairs/s (1080)\n            SINGLE_TILE_RADIX_BITS  = 6,\n            SEGMENTED_RADIX_BITS    = 6,    // 3.3B 32b segmented keys/s (1080)\n        };\n\n        // ScanPolicy\n        typedef AgentScanPolicy <512, 23, BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, BLOCK_STORE_WARP_TRANSPOSE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <384, CUB_MAX(1, 31 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT,       LOAD_DEFAULT,       RADIX_RANK_MATCH,   BLOCK_SCAN_RAKING_MEMOIZE, PRIMARY_RADIX_BITS>   DownsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 35 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE,    LOAD_DEFAULT,   RADIX_RANK_MEMOIZE, BLOCK_SCAN_RAKING_MEMOIZE, PRIMARY_RADIX_BITS - 1>   AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 16 / SCALE_FACTOR_4B), LOAD_LDG, PRIMARY_RADIX_BITS>        UpsweepPolicy;\n        typedef AgentRadixSortUpsweepPolicy <128, CUB_MAX(1, 16 / SCALE_FACTOR_4B), LOAD_LDG, PRIMARY_RADIX_BITS - 1>    AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 19 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SINGLE_TILE_RADIX_BITS>          SingleTilePolicy;\n\n        // Segmented policies\n        typedef AgentRadixSortDownsweepPolicy <192, CUB_MAX(1, 39 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS>     SegmentedPolicy;\n        typedef AgentRadixSortDownsweepPolicy <384, CUB_MAX(1, 11 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS - 1> AltSegmentedPolicy;\n    };\n\n\n    /// SM62 (Tegra, less RF)\n    struct Policy620 : ChainedPolicy<620, Policy620, Policy610>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 5,\n            ALT_RADIX_BITS          = PRIMARY_RADIX_BITS - 1,\n        };\n\n        // ScanPolicy\n        typedef AgentScanPolicy <512, 23, BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, BLOCK_STORE_WARP_TRANSPOSE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 16 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_RAKING_MEMOIZE, PRIMARY_RADIX_BITS>   DownsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 16 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_RAKING_MEMOIZE, ALT_RADIX_BITS>       AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef DownsweepPolicy UpsweepPolicy;\n        typedef AltDownsweepPolicy AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 19 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS> SingleTilePolicy;\n\n        // Segmented policies\n        typedef DownsweepPolicy     SegmentedPolicy;\n        typedef AltDownsweepPolicy  AltSegmentedPolicy;\n    };\n\n\n    /// SM70 (GV100)\n    struct Policy700 : ChainedPolicy<700, Policy700, Policy620>\n    {\n        enum {\n            PRIMARY_RADIX_BITS      = 6,    // 7.62B 32b keys/s (GV100)\n            SINGLE_TILE_RADIX_BITS  = 6,\n            SEGMENTED_RADIX_BITS    = 6,    // 8.7B 32b segmented keys/s (GV100)\n        };\n\n        // ScanPolicy\n        typedef AgentScanPolicy <512, 23, BLOCK_LOAD_WARP_TRANSPOSE, LOAD_DEFAULT, BLOCK_STORE_WARP_TRANSPOSE, BLOCK_SCAN_RAKING_MEMOIZE> ScanPolicy;\n\n        // Downsweep policies\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 47 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>   DownsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <384, CUB_MAX(1, 29 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS - 1>   AltDownsweepPolicy;\n\n        // Upsweep policies\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 47 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MATCH, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS>  UpsweepPolicy;\n        typedef AgentRadixSortDownsweepPolicy <128, CUB_MAX(1, 29 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MATCH, BLOCK_SCAN_WARP_SCANS, PRIMARY_RADIX_BITS - 1>  AltUpsweepPolicy;\n\n        // Single-tile policy\n        typedef AgentRadixSortDownsweepPolicy <256, CUB_MAX(1, 19 / SCALE_FACTOR_4B),  BLOCK_LOAD_DIRECT, LOAD_LDG, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SINGLE_TILE_RADIX_BITS>          SingleTilePolicy;\n\n        // Segmented policies\n        typedef AgentRadixSortDownsweepPolicy <192, CUB_MAX(1, 39 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS>     SegmentedPolicy;\n        typedef AgentRadixSortDownsweepPolicy <384, CUB_MAX(1, 11 / SCALE_FACTOR_4B),  BLOCK_LOAD_TRANSPOSE, LOAD_DEFAULT, RADIX_RANK_MEMOIZE, BLOCK_SCAN_WARP_SCANS, SEGMENTED_RADIX_BITS - 1> AltSegmentedPolicy;\n    };\n\n\n    /// MaxPolicy\n    typedef Policy700 MaxPolicy;\n\n\n};\n\n\n\n/******************************************************************************\n * Single-problem dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for device-wide radix sort\n */\ntemplate <\n    bool     IS_DESCENDING, ///< Whether or not the sorted-order is high-to-low\n    typename KeyT,          ///< Key type\n    typename ValueT,        ///< Value type\n    typename OffsetT>       ///< Signed integer type for global offsets\nstruct DispatchRadixSort :\n    DeviceRadixSortPolicy<KeyT, ValueT, OffsetT>\n{\n    //------------------------------------------------------------------------------\n    // Constants\n    //------------------------------------------------------------------------------\n\n    enum\n    {\n        // Whether this is a keys-only (or key-value) sort\n        KEYS_ONLY = (Equals<ValueT, NullType>::VALUE),\n    };\n\n\n    //------------------------------------------------------------------------------\n    // Problem state\n    //------------------------------------------------------------------------------\n\n    void                    *d_temp_storage;        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n    size_t                  &temp_storage_bytes;    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n    DoubleBuffer<KeyT>      &d_keys;                ///< [in,out] Double-buffer whose current buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n    DoubleBuffer<ValueT>    &d_values;              ///< [in,out] Double-buffer whose current buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n    OffsetT                 num_items;              ///< [in] Number of items to sort\n    int                     begin_bit;              ///< [in] The beginning (least-significant) bit index needed for key comparison\n    int                     end_bit;                ///< [in] The past-the-end (most-significant) bit index needed for key comparison\n    cudaStream_t            stream;                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n    bool                    debug_synchronous;      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    int                     ptx_version;            ///< [in] PTX version\n    bool                    is_overwrite_okay;      ///< [in] Whether is okay to overwrite source buffers\n\n\n    //------------------------------------------------------------------------------\n    // Constructor\n    //------------------------------------------------------------------------------\n\n    /// Constructor\n    CUB_RUNTIME_FUNCTION __forceinline__\n    DispatchRadixSort(\n        void*                   d_temp_storage,\n        size_t                  &temp_storage_bytes,\n        DoubleBuffer<KeyT>      &d_keys,\n        DoubleBuffer<ValueT>    &d_values,\n        OffsetT                 num_items,\n        int                     begin_bit,\n        int                     end_bit,\n        bool                    is_overwrite_okay,\n        cudaStream_t            stream,\n        bool                    debug_synchronous,\n        int                     ptx_version)\n    :\n        d_temp_storage(d_temp_storage),\n        temp_storage_bytes(temp_storage_bytes),\n        d_keys(d_keys),\n        d_values(d_values),\n        num_items(num_items),\n        begin_bit(begin_bit),\n        end_bit(end_bit),\n        stream(stream),\n        debug_synchronous(debug_synchronous),\n        ptx_version(ptx_version),\n        is_overwrite_okay(is_overwrite_okay)\n    {}\n\n\n    //------------------------------------------------------------------------------\n    // Small-problem (single tile) invocation\n    //------------------------------------------------------------------------------\n\n    /// Invoke a single block to sort in-core\n    template <\n        typename                ActivePolicyT,          ///< Umbrella policy active for the target device\n        typename                SingleTileKernelT>      ///< Function type of cub::DeviceRadixSortSingleTileKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokeSingleTile(\n        SingleTileKernelT       single_tile_kernel)     ///< [in] Kernel function pointer to parameterization of cub::DeviceRadixSortSingleTileKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n        (void)single_tile_kernel;\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Return if the caller is simply requesting the size of the storage allocation\n            if (d_temp_storage == NULL)\n            {\n                temp_storage_bytes = 1;\n                break;\n            }\n\n            // Return if empty problem\n            if (num_items == 0)\n                break;\n\n            // Log single_tile_kernel configuration\n            if (debug_synchronous)\n                _CubLog(\"Invoking single_tile_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy, current bit %d, bit_grain %d\\n\",\n                    1, ActivePolicyT::SingleTilePolicy::BLOCK_THREADS, (long long) stream,\n                    ActivePolicyT::SingleTilePolicy::ITEMS_PER_THREAD, 1, begin_bit, ActivePolicyT::SingleTilePolicy::RADIX_BITS);\n\n            // Invoke upsweep_kernel with same grid size as downsweep_kernel\n            single_tile_kernel<<<1, ActivePolicyT::SingleTilePolicy::BLOCK_THREADS, 0, stream>>>(\n                d_keys.Current(),\n                d_keys.Alternate(),\n                d_values.Current(),\n                d_values.Alternate(),\n                num_items,\n                begin_bit,\n                end_bit);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Update selector\n            d_keys.selector ^= 1;\n            d_values.selector ^= 1;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Normal problem size invocation\n    //------------------------------------------------------------------------------\n\n    /**\n     * Invoke a three-kernel sorting pass at the current bit.\n     */\n    template <typename PassConfigT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePass(\n        const KeyT      *d_keys_in,\n        KeyT            *d_keys_out,\n        const ValueT    *d_values_in,\n        ValueT          *d_values_out,\n        OffsetT         *d_spine,\n        int             spine_length,\n        int             &current_bit,\n        PassConfigT     &pass_config)\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            int pass_bits = CUB_MIN(pass_config.radix_bits, (end_bit - current_bit));\n\n            // Log upsweep_kernel configuration\n            if (debug_synchronous)\n                _CubLog(\"Invoking upsweep_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy, current bit %d, bit_grain %d\\n\",\n                pass_config.even_share.grid_size, pass_config.upsweep_config.block_threads, (long long) stream,\n                pass_config.upsweep_config.items_per_thread, pass_config.upsweep_config.sm_occupancy, current_bit, pass_bits);\n\n\t\t\t\t\t\t/*printf(\"running upsweep kernel with pass_bits %d\\n\", pass_bits);*/\n\t\t\t\t\t\t/*printf(\"Invoking upsweep_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy, current bit %d, bit_grain %d\\n\",*/\n\t\t\t\t\t\t\t\t/*pass_config.even_share.grid_size, pass_config.upsweep_config.block_threads, (long long) stream,*/\n\t\t\t\t\t\t\t\t/*pass_config.upsweep_config.items_per_thread, pass_config.upsweep_config.sm_occupancy, current_bit, pass_bits);*/\n\n            // Invoke upsweep_kernel with same grid size as downsweep_kernel\n            pass_config.upsweep_kernel<<<pass_config.even_share.grid_size, pass_config.upsweep_config.block_threads, 0, stream>>>(\n                d_keys_in,\n                d_spine,\n                num_items,\n                current_bit,\n                pass_bits,\n                pass_config.even_share);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Log scan_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking scan_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread\\n\",\n                1, pass_config.scan_config.block_threads, (long long) stream, pass_config.scan_config.items_per_thread);\n\n            // Invoke scan_kernel\n            pass_config.scan_kernel<<<1, pass_config.scan_config.block_threads, 0, stream>>>(\n                d_spine,\n                spine_length);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Log downsweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking downsweep_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                pass_config.even_share.grid_size, pass_config.downsweep_config.block_threads, (long long) stream,\n                pass_config.downsweep_config.items_per_thread, pass_config.downsweep_config.sm_occupancy);\n\n            // Invoke downsweep_kernel\n            pass_config.downsweep_kernel<<<pass_config.even_share.grid_size, pass_config.downsweep_config.block_threads, 0, stream>>>(\n                d_keys_in,\n                d_keys_out,\n                d_values_in,\n                d_values_out,\n                d_spine,\n                num_items,\n                current_bit,\n                pass_bits,\n                pass_config.even_share);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Update current bit\n            current_bit += pass_bits;\n        }\n        while (0);\n\n        return error;\n    }\n\n\n\n    /// Pass configuration structure\n    template <\n        typename UpsweepKernelT,\n        typename ScanKernelT,\n        typename DownsweepKernelT>\n    struct PassConfig\n    {\n        UpsweepKernelT          upsweep_kernel;\n        KernelConfig            upsweep_config;\n        ScanKernelT             scan_kernel;\n        KernelConfig            scan_config;\n        DownsweepKernelT        downsweep_kernel;\n        KernelConfig            downsweep_config;\n        int                     radix_bits;\n        int                     radix_digits;\n        int                     max_downsweep_grid_size;\n        GridEvenShare<OffsetT>  even_share;\n\n        /// Initialize pass configuration\n        template <\n            typename UpsweepPolicyT,\n            typename ScanPolicyT,\n            typename DownsweepPolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        cudaError_t InitPassConfig(\n            UpsweepKernelT      upsweep_kernel,\n            ScanKernelT         scan_kernel,\n            DownsweepKernelT    downsweep_kernel,\n            int                 ptx_version,\n            int                 sm_count,\n            int                 num_items)\n        {\n            cudaError error = cudaSuccess;\n            do\n            {\n                this->upsweep_kernel    = upsweep_kernel;\n                this->scan_kernel       = scan_kernel;\n                this->downsweep_kernel  = downsweep_kernel;\n                radix_bits              = DownsweepPolicyT::RADIX_BITS;\n                radix_digits            = 1 << radix_bits;\n\n                if (CubDebug(error = upsweep_config.Init<UpsweepPolicyT>(upsweep_kernel))) break;\n                if (CubDebug(error = scan_config.Init<ScanPolicyT>(scan_kernel))) break;\n                if (CubDebug(error = downsweep_config.Init<DownsweepPolicyT>(downsweep_kernel))) break;\n\n                max_downsweep_grid_size = (downsweep_config.sm_occupancy * sm_count) * CUB_SUBSCRIPTION_FACTOR(ptx_version);\n\n                even_share.DispatchInit(\n                    num_items,\n                    max_downsweep_grid_size,\n                    CUB_MAX(downsweep_config.tile_size, upsweep_config.tile_size));\n\n            }\n            while (0);\n            return error;\n        }\n\n    };\n\n\n    /// Invocation (run multiple digit passes)\n    template <\n        typename            ActivePolicyT,          ///< Umbrella policy active for the target device\n        typename            UpsweepKernelT,         ///< Function type of cub::DeviceRadixSortUpsweepKernel\n        typename            ScanKernelT,            ///< Function type of cub::SpineScanKernel\n        typename            DownsweepKernelT>       ///< Function type of cub::DeviceRadixSortDownsweepKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePasses(\n        UpsweepKernelT      upsweep_kernel,         ///< [in] Kernel function pointer to parameterization of cub::DeviceRadixSortUpsweepKernel\n        UpsweepKernelT      alt_upsweep_kernel,     ///< [in] Alternate kernel function pointer to parameterization of cub::DeviceRadixSortUpsweepKernel\n        ScanKernelT         scan_kernel,            ///< [in] Kernel function pointer to parameterization of cub::SpineScanKernel\n        DownsweepKernelT    downsweep_kernel,       ///< [in] Kernel function pointer to parameterization of cub::DeviceRadixSortDownsweepKernel\n        DownsweepKernelT    alt_downsweep_kernel)   ///< [in] Alternate kernel function pointer to parameterization of cub::DeviceRadixSortDownsweepKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n        (void)upsweep_kernel;\n        (void)alt_upsweep_kernel;\n        (void)scan_kernel;\n        (void)downsweep_kernel;\n        (void)alt_downsweep_kernel;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Init regular and alternate-digit kernel configurations\n            PassConfig<UpsweepKernelT, ScanKernelT, DownsweepKernelT> pass_config, alt_pass_config;\n            if ((error = pass_config.template InitPassConfig<\n                    typename ActivePolicyT::UpsweepPolicy,\n                    typename ActivePolicyT::ScanPolicy,\n                    typename ActivePolicyT::DownsweepPolicy>(\n                upsweep_kernel, scan_kernel, downsweep_kernel, ptx_version, sm_count, num_items))) break;\n\n            if ((error = alt_pass_config.template InitPassConfig<\n                    typename ActivePolicyT::AltUpsweepPolicy,\n                    typename ActivePolicyT::ScanPolicy,\n                    typename ActivePolicyT::AltDownsweepPolicy>(\n                alt_upsweep_kernel, scan_kernel, alt_downsweep_kernel, ptx_version, sm_count, num_items))) break;\n\n            // Get maximum spine length\n            int max_grid_size       = CUB_MAX(pass_config.max_downsweep_grid_size, alt_pass_config.max_downsweep_grid_size);\n            int spine_length        = (max_grid_size * pass_config.radix_digits) + pass_config.scan_config.tile_size;\n\n            // Temporary storage allocation requirements\n            void* allocations[3];\n            size_t allocation_sizes[3] =\n            {\n                spine_length * sizeof(OffsetT),                                         // bytes needed for privatized block digit histograms\n                (is_overwrite_okay) ? 0 : num_items * sizeof(KeyT),                     // bytes needed for 3rd keys buffer\n                (is_overwrite_okay || (KEYS_ONLY)) ? 0 : num_items * sizeof(ValueT),    // bytes needed for 3rd values buffer\n            };\n\n            // Alias the temporary allocations from the single storage blob (or compute the necessary size of the blob)\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n\n            // Return if the caller is simply requesting the size of the storage allocation\n            if (d_temp_storage == NULL)\n                return cudaSuccess;\n\n            // Pass planning.  Run passes of the alternate digit-size configuration until we have an even multiple of our preferred digit size\n            int num_bits            = end_bit - begin_bit;\n            int num_passes          = (num_bits + pass_config.radix_bits - 1) / pass_config.radix_bits;\n            bool is_num_passes_odd  = num_passes & 1;\n            int max_alt_passes      = (num_passes * pass_config.radix_bits) - num_bits;\n            int alt_end_bit         = CUB_MIN(end_bit, begin_bit + (max_alt_passes * alt_pass_config.radix_bits));\n\n            // Alias the temporary storage allocations\n            OffsetT *d_spine = static_cast<OffsetT*>(allocations[0]);\n\n            DoubleBuffer<KeyT> d_keys_remaining_passes(\n                (is_overwrite_okay || is_num_passes_odd) ? d_keys.Alternate() : static_cast<KeyT*>(allocations[1]),\n                (is_overwrite_okay) ? d_keys.Current() : (is_num_passes_odd) ? static_cast<KeyT*>(allocations[1]) : d_keys.Alternate());\n\n            DoubleBuffer<ValueT> d_values_remaining_passes(\n                (is_overwrite_okay || is_num_passes_odd) ? d_values.Alternate() : static_cast<ValueT*>(allocations[2]),\n                (is_overwrite_okay) ? d_values.Current() : (is_num_passes_odd) ? static_cast<ValueT*>(allocations[2]) : d_values.Alternate());\n\n            // Run first pass, consuming from the input's current buffers\n            int current_bit = begin_bit;\n            if (CubDebug(error = InvokePass(\n                d_keys.Current(), d_keys_remaining_passes.Current(),\n                d_values.Current(), d_values_remaining_passes.Current(),\n                d_spine, spine_length, current_bit,\n                (current_bit < alt_end_bit) ? alt_pass_config : pass_config))) break;\n\n            // Run remaining passes\n            while (current_bit < end_bit)\n            {\n                if (CubDebug(error = InvokePass(\n                    d_keys_remaining_passes.d_buffers[d_keys_remaining_passes.selector],    d_keys_remaining_passes.d_buffers[d_keys_remaining_passes.selector ^ 1],\n                    d_values_remaining_passes.d_buffers[d_keys_remaining_passes.selector],  d_values_remaining_passes.d_buffers[d_keys_remaining_passes.selector ^ 1],\n                    d_spine, spine_length, current_bit,\n                    (current_bit < alt_end_bit) ? alt_pass_config : pass_config))) break;;\n\n                // Invert selectors\n                d_keys_remaining_passes.selector ^= 1;\n                d_values_remaining_passes.selector ^= 1;\n            }\n\n            // Update selector\n            if (!is_overwrite_okay) {\n                num_passes = 1; // Sorted data always ends up in the other vector\n            }\n\n            d_keys.selector = (d_keys.selector + num_passes) & 1;\n            d_values.selector = (d_values.selector + num_passes) & 1;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Chained policy invocation\n    //------------------------------------------------------------------------------\n\n    /// Invocation\n    template <typename ActivePolicyT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t Invoke()\n    {\n        typedef typename DispatchRadixSort::MaxPolicy       MaxPolicyT;\n        typedef typename ActivePolicyT::SingleTilePolicy    SingleTilePolicyT;\n\n        // Force kernel code-generation in all compiler passes\n        if (num_items <= (SingleTilePolicyT::BLOCK_THREADS * SingleTilePolicyT::ITEMS_PER_THREAD))\n        {\n            // Small, single tile size\n            return InvokeSingleTile<ActivePolicyT>(\n                DeviceRadixSortSingleTileKernel<MaxPolicyT, IS_DESCENDING, KeyT, ValueT, OffsetT>);\n        }\n        else\n        {\n            // Regular size\n            return InvokePasses<ActivePolicyT>(\n                DeviceRadixSortUpsweepKernel<   MaxPolicyT, false,   IS_DESCENDING, KeyT, OffsetT>,\n                DeviceRadixSortUpsweepKernel<   MaxPolicyT, true,    IS_DESCENDING, KeyT, OffsetT>,\n                RadixSortScanBinsKernel<        MaxPolicyT, OffsetT>,\n                DeviceRadixSortDownsweepKernel< MaxPolicyT, false,   IS_DESCENDING, KeyT, ValueT, OffsetT>,\n                DeviceRadixSortDownsweepKernel< MaxPolicyT, true,    IS_DESCENDING, KeyT, ValueT, OffsetT>);\n        }\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Dispatch entrypoints\n    //------------------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                   d_temp_storage,         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                ///< [in,out] Double-buffer whose current buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,              ///< [in,out] Double-buffer whose current buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        OffsetT                 num_items,              ///< [in] Number of items to sort\n        int                     begin_bit,              ///< [in] The beginning (least-significant) bit index needed for key comparison\n        int                     end_bit,                ///< [in] The past-the-end (most-significant) bit index needed for key comparison\n        bool                    is_overwrite_okay,      ///< [in] Whether is okay to overwrite source buffers\n        cudaStream_t            stream,                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous)      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        typedef typename DispatchRadixSort::MaxPolicy MaxPolicyT;\n\n        cudaError_t error;\n        do {\n            // Get PTX version\n            int ptx_version;\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n\n            // Create dispatch functor\n            DispatchRadixSort dispatch(\n                d_temp_storage, temp_storage_bytes,\n                d_keys, d_values,\n                num_items, begin_bit, end_bit, is_overwrite_okay,\n                stream, debug_synchronous, ptx_version);\n\n            // Dispatch to chained policy\n            if (CubDebug(error = MaxPolicyT::Invoke(ptx_version, dispatch))) break;\n\n        } while (0);\n\n        return error;\n    }\n};\n\n\n\n\n/******************************************************************************\n * Segmented dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for segmented device-wide radix sort\n */\ntemplate <\n    bool     IS_DESCENDING,     ///< Whether or not the sorted-order is high-to-low\n    typename KeyT,              ///< Key type\n    typename ValueT,            ///< Value type\n    typename OffsetIteratorT,   ///< Random-access input iterator type for reading segment offsets \\iterator\n    typename OffsetT>           ///< Signed integer type for global offsets\nstruct DispatchSegmentedRadixSort :\n    DeviceRadixSortPolicy<KeyT, ValueT, OffsetT>\n{\n    //------------------------------------------------------------------------------\n    // Constants\n    //------------------------------------------------------------------------------\n\n    enum\n    {\n        // Whether this is a keys-only (or key-value) sort\n        KEYS_ONLY = (Equals<ValueT, NullType>::VALUE),\n    };\n\n\n    //------------------------------------------------------------------------------\n    // Parameter members\n    //------------------------------------------------------------------------------\n\n    void                    *d_temp_storage;        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n    size_t                  &temp_storage_bytes;    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n    DoubleBuffer<KeyT>      &d_keys;                ///< [in,out] Double-buffer whose current buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n    DoubleBuffer<ValueT>    &d_values;              ///< [in,out] Double-buffer whose current buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n    OffsetT                 num_items;              ///< [in] Number of items to sort\n    OffsetT                 num_segments;           ///< [in] The number of segments that comprise the sorting data\n    OffsetIteratorT         d_begin_offsets;        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n    OffsetIteratorT         d_end_offsets;          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n    int                     begin_bit;              ///< [in] The beginning (least-significant) bit index needed for key comparison\n    int                     end_bit;                ///< [in] The past-the-end (most-significant) bit index needed for key comparison\n    cudaStream_t            stream;                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n    bool                    debug_synchronous;      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    int                     ptx_version;            ///< [in] PTX version\n    bool                    is_overwrite_okay;      ///< [in] Whether is okay to overwrite source buffers\n\n\n    //------------------------------------------------------------------------------\n    // Constructors\n    //------------------------------------------------------------------------------\n\n    /// Constructor\n    CUB_RUNTIME_FUNCTION __forceinline__\n    DispatchSegmentedRadixSort(\n        void*                   d_temp_storage,\n        size_t                  &temp_storage_bytes,\n        DoubleBuffer<KeyT>      &d_keys,\n        DoubleBuffer<ValueT>    &d_values,\n        OffsetT                 num_items,\n        OffsetT                 num_segments,\n        OffsetIteratorT         d_begin_offsets,\n        OffsetIteratorT         d_end_offsets,\n        int                     begin_bit,\n        int                     end_bit,\n        bool                    is_overwrite_okay,\n        cudaStream_t            stream,\n        bool                    debug_synchronous,\n        int                     ptx_version)\n    :\n        d_temp_storage(d_temp_storage),\n        temp_storage_bytes(temp_storage_bytes),\n        d_keys(d_keys),\n        d_values(d_values),\n        num_items(num_items),\n        num_segments(num_segments),\n        d_begin_offsets(d_begin_offsets),\n        d_end_offsets(d_end_offsets),\n        begin_bit(begin_bit),\n        end_bit(end_bit),\n        is_overwrite_okay(is_overwrite_okay),\n        stream(stream),\n        debug_synchronous(debug_synchronous),\n        ptx_version(ptx_version)\n    {}\n\n\n    //------------------------------------------------------------------------------\n    // Multi-segment invocation\n    //------------------------------------------------------------------------------\n\n    /// Invoke a three-kernel sorting pass at the current bit.\n    template <typename PassConfigT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePass(\n        const KeyT      *d_keys_in,\n        KeyT            *d_keys_out,\n        const ValueT    *d_values_in,\n        ValueT          *d_values_out,\n        int             &current_bit,\n        PassConfigT     &pass_config)\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            int pass_bits = CUB_MIN(pass_config.radix_bits, (end_bit - current_bit));\n\n            // Log kernel configuration\n            if (debug_synchronous)\n                _CubLog(\"Invoking segmented_kernels<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy, current bit %d, bit_grain %d\\n\",\n                    num_segments, pass_config.segmented_config.block_threads, (long long) stream,\n                pass_config.segmented_config.items_per_thread, pass_config.segmented_config.sm_occupancy, current_bit, pass_bits);\n\n            pass_config.segmented_kernel<<<num_segments, pass_config.segmented_config.block_threads, 0, stream>>>(\n                d_keys_in, d_keys_out,\n                d_values_in,  d_values_out,\n                d_begin_offsets, d_end_offsets, num_segments,\n                current_bit, pass_bits);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Update current bit\n            current_bit += pass_bits;\n        }\n        while (0);\n\n        return error;\n    }\n\n\n    /// PassConfig data structure\n    template <typename SegmentedKernelT>\n    struct PassConfig\n    {\n        SegmentedKernelT    segmented_kernel;\n        KernelConfig        segmented_config;\n        int                 radix_bits;\n        int                 radix_digits;\n\n        /// Initialize pass configuration\n        template <typename SegmentedPolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        cudaError_t InitPassConfig(SegmentedKernelT segmented_kernel)\n        {\n            this->segmented_kernel  = segmented_kernel;\n            this->radix_bits        = SegmentedPolicyT::RADIX_BITS;\n            this->radix_digits      = 1 << radix_bits;\n\n            return CubDebug(segmented_config.Init<SegmentedPolicyT>(segmented_kernel));\n        }\n    };\n\n\n    /// Invocation (run multiple digit passes)\n    template <\n        typename                ActivePolicyT,          ///< Umbrella policy active for the target device\n        typename                SegmentedKernelT>       ///< Function type of cub::DeviceSegmentedRadixSortKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePasses(\n        SegmentedKernelT     segmented_kernel,          ///< [in] Kernel function pointer to parameterization of cub::DeviceSegmentedRadixSortKernel\n        SegmentedKernelT     alt_segmented_kernel)      ///< [in] Alternate kernel function pointer to parameterization of cub::DeviceSegmentedRadixSortKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n      (void)segmented_kernel;\n      (void)alt_segmented_kernel;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Init regular and alternate kernel configurations\n            PassConfig<SegmentedKernelT> pass_config, alt_pass_config;\n            if ((error = pass_config.template       InitPassConfig<typename ActivePolicyT::SegmentedPolicy>(segmented_kernel))) break;\n            if ((error = alt_pass_config.template   InitPassConfig<typename ActivePolicyT::AltSegmentedPolicy>(alt_segmented_kernel))) break;\n\n            // Temporary storage allocation requirements\n            void* allocations[2];\n            size_t allocation_sizes[2] =\n            {\n                (is_overwrite_okay) ? 0 : num_items * sizeof(KeyT),                      // bytes needed for 3rd keys buffer\n                (is_overwrite_okay || (KEYS_ONLY)) ? 0 : num_items * sizeof(ValueT),     // bytes needed for 3rd values buffer\n            };\n\n            // Alias the temporary allocations from the single storage blob (or compute the necessary size of the blob)\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n\n            // Return if the caller is simply requesting the size of the storage allocation\n            if (d_temp_storage == NULL)\n            {\n                if (temp_storage_bytes == 0)\n                    temp_storage_bytes = 1;\n                return cudaSuccess;\n            }\n\n            // Pass planning.  Run passes of the alternate digit-size configuration until we have an even multiple of our preferred digit size\n            int radix_bits          = ActivePolicyT::SegmentedPolicy::RADIX_BITS;\n            int alt_radix_bits      = ActivePolicyT::AltSegmentedPolicy::RADIX_BITS;\n            int num_bits            = end_bit - begin_bit;\n            int num_passes          = (num_bits + radix_bits - 1) / radix_bits;\n            bool is_num_passes_odd  = num_passes & 1;\n            int max_alt_passes      = (num_passes * radix_bits) - num_bits;\n            int alt_end_bit         = CUB_MIN(end_bit, begin_bit + (max_alt_passes * alt_radix_bits));\n\n            DoubleBuffer<KeyT> d_keys_remaining_passes(\n                (is_overwrite_okay || is_num_passes_odd) ? d_keys.Alternate() : static_cast<KeyT*>(allocations[0]),\n                (is_overwrite_okay) ? d_keys.Current() : (is_num_passes_odd) ? static_cast<KeyT*>(allocations[0]) : d_keys.Alternate());\n\n            DoubleBuffer<ValueT> d_values_remaining_passes(\n                (is_overwrite_okay || is_num_passes_odd) ? d_values.Alternate() : static_cast<ValueT*>(allocations[1]),\n                (is_overwrite_okay) ? d_values.Current() : (is_num_passes_odd) ? static_cast<ValueT*>(allocations[1]) : d_values.Alternate());\n\n            // Run first pass, consuming from the input's current buffers\n            int current_bit = begin_bit;\n\n            if (CubDebug(error = InvokePass(\n                d_keys.Current(), d_keys_remaining_passes.Current(),\n                d_values.Current(), d_values_remaining_passes.Current(),\n                current_bit,\n                (current_bit < alt_end_bit) ? alt_pass_config : pass_config))) break;\n\n            // Run remaining passes\n            while (current_bit < end_bit)\n            {\n                if (CubDebug(error = InvokePass(\n                    d_keys_remaining_passes.d_buffers[d_keys_remaining_passes.selector],    d_keys_remaining_passes.d_buffers[d_keys_remaining_passes.selector ^ 1],\n                    d_values_remaining_passes.d_buffers[d_keys_remaining_passes.selector],  d_values_remaining_passes.d_buffers[d_keys_remaining_passes.selector ^ 1],\n                    current_bit,\n                    (current_bit < alt_end_bit) ? alt_pass_config : pass_config))) break;\n\n                // Invert selectors and update current bit\n                d_keys_remaining_passes.selector ^= 1;\n                d_values_remaining_passes.selector ^= 1;\n            }\n\n            // Update selector\n            if (!is_overwrite_okay) {\n                num_passes = 1; // Sorted data always ends up in the other vector\n            }\n\n            d_keys.selector = (d_keys.selector + num_passes) & 1;\n            d_values.selector = (d_values.selector + num_passes) & 1;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Chained policy invocation\n    //------------------------------------------------------------------------------\n\n    /// Invocation\n    template <typename ActivePolicyT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t Invoke()\n    {\n        typedef typename DispatchSegmentedRadixSort::MaxPolicy MaxPolicyT;\n\n        // Force kernel code-generation in all compiler passes\n        return InvokePasses<ActivePolicyT>(\n            DeviceSegmentedRadixSortKernel<MaxPolicyT, false,   IS_DESCENDING, KeyT, ValueT, OffsetIteratorT, OffsetT>,\n            DeviceSegmentedRadixSortKernel<MaxPolicyT, true,    IS_DESCENDING, KeyT, ValueT, OffsetIteratorT, OffsetT>);\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Dispatch entrypoints\n    //------------------------------------------------------------------------------\n\n\n    /// Internal dispatch routine\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                   d_temp_storage,         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        DoubleBuffer<KeyT>      &d_keys,                ///< [in,out] Double-buffer whose current buffer contains the unsorted input keys and, upon return, is updated to point to the sorted output keys\n        DoubleBuffer<ValueT>    &d_values,              ///< [in,out] Double-buffer whose current buffer contains the unsorted input values and, upon return, is updated to point to the sorted output values\n        int                     num_items,              ///< [in] Number of items to sort\n        int                     num_segments,           ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT         d_begin_offsets,        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT         d_end_offsets,          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        int                     begin_bit,              ///< [in] The beginning (least-significant) bit index needed for key comparison\n        int                     end_bit,                ///< [in] The past-the-end (most-significant) bit index needed for key comparison\n        bool                    is_overwrite_okay,      ///< [in] Whether is okay to overwrite source buffers\n        cudaStream_t            stream,                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous)      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        typedef typename DispatchSegmentedRadixSort::MaxPolicy MaxPolicyT;\n\n        cudaError_t error;\n        do {\n            // Get PTX version\n            int ptx_version;\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n\n            // Create dispatch functor\n            DispatchSegmentedRadixSort dispatch(\n                d_temp_storage, temp_storage_bytes,\n                d_keys, d_values,\n                num_items, num_segments, d_begin_offsets, d_end_offsets,\n                begin_bit, end_bit, is_overwrite_okay,\n                stream, debug_synchronous, ptx_version);\n\n            // Dispatch to chained policy\n            if (CubDebug(error = MaxPolicyT::Invoke(ptx_version, dispatch))) break;\n\n        } while (0);\n\n        return error;\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_reduce.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceReduce provides device-wide, parallel operations for computing a reduction across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"../../agent/agent_reduce.cuh\"\n#include \"../../iterator/arg_index_input_iterator.cuh\"\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../grid/grid_even_share.cuh\"\n#include \"../../iterator/arg_index_input_iterator.cuh\"\n#include \"../../util_debug.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Reduce region kernel entry point (multi-block).  Computes privatized reductions, one per thread block.\n */\ntemplate <\n    typename                ChainedPolicyT,             ///< Chained tuning policy\n    typename                InputIteratorT,             ///< Random-access input iterator type for reading input items \\iterator\n    typename                OutputIteratorT,            ///< Output iterator type for recording the reduced aggregate \\iterator\n    typename                OffsetT,                    ///< Signed integer type for global offsets\n    typename                ReductionOpT>               ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n__launch_bounds__ (int(ChainedPolicyT::ActivePolicy::ReducePolicy::BLOCK_THREADS))\n__global__ void DeviceReduceKernel(\n    InputIteratorT          d_in,                       ///< [in] Pointer to the input sequence of data items\n    OutputIteratorT         d_out,                      ///< [out] Pointer to the output aggregate\n    OffsetT                 num_items,                  ///< [in] Total number of input data items\n    GridEvenShare<OffsetT>  even_share,                 ///< [in] Even-share descriptor for mapping an equal number of tiles onto each thread block\n    ReductionOpT            reduction_op)               ///< [in] Binary reduction functor\n{\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Thread block type for reducing input tiles\n    typedef AgentReduce<\n            typename ChainedPolicyT::ActivePolicy::ReducePolicy,\n            InputIteratorT,\n            OutputIteratorT,\n            OffsetT,\n            ReductionOpT>\n        AgentReduceT;\n\n    // Shared memory storage\n    __shared__ typename AgentReduceT::TempStorage temp_storage;\n\n    // Consume input tiles\n    OutputT block_aggregate = AgentReduceT(temp_storage, d_in, reduction_op).ConsumeTiles(even_share);\n\n    // Output result\n    if (threadIdx.x == 0)\n        d_out[blockIdx.x] = block_aggregate;\n}\n\n\n/**\n * Reduce a single tile kernel entry point (single-block).  Can be used to aggregate privatized thread block reductions from a previous multi-block reduction pass.\n */\ntemplate <\n    typename                ChainedPolicyT,             ///< Chained tuning policy\n    typename                InputIteratorT,             ///< Random-access input iterator type for reading input items \\iterator\n    typename                OutputIteratorT,            ///< Output iterator type for recording the reduced aggregate \\iterator\n    typename                OffsetT,                    ///< Signed integer type for global offsets\n    typename                ReductionOpT,               ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename                OuputT>                     ///< Data element type that is convertible to the \\p value type of \\p OutputIteratorT\n__launch_bounds__ (int(ChainedPolicyT::ActivePolicy::SingleTilePolicy::BLOCK_THREADS), 1)\n__global__ void DeviceReduceSingleTileKernel(\n    InputIteratorT          d_in,                       ///< [in] Pointer to the input sequence of data items\n    OutputIteratorT         d_out,                      ///< [out] Pointer to the output aggregate\n    OffsetT                 num_items,                  ///< [in] Total number of input data items\n    ReductionOpT            reduction_op,               ///< [in] Binary reduction functor\n    OuputT                  init)                       ///< [in] The initial value of the reduction\n{\n    // Thread block type for reducing input tiles\n    typedef AgentReduce<\n            typename ChainedPolicyT::ActivePolicy::SingleTilePolicy,\n            InputIteratorT,\n            OutputIteratorT,\n            OffsetT,\n            ReductionOpT>\n        AgentReduceT;\n\n    // Shared memory storage\n    __shared__ typename AgentReduceT::TempStorage temp_storage;\n\n    // Check if empty problem\n    if (num_items == 0)\n    {\n        if (threadIdx.x == 0)\n            *d_out = init;\n        return;\n    }\n\n    // Consume input tiles\n    OuputT block_aggregate = AgentReduceT(temp_storage, d_in, reduction_op).ConsumeRange(\n        OffsetT(0),\n        num_items);\n\n    // Output result\n    if (threadIdx.x == 0)\n        *d_out = reduction_op(init, block_aggregate);\n}\n\n\n/// Normalize input iterator to segment offset\ntemplate <typename T, typename OffsetT, typename IteratorT>\n__device__ __forceinline__\nvoid NormalizeReductionOutput(\n    T &/*val*/,\n    OffsetT /*base_offset*/,\n    IteratorT /*itr*/)\n{}\n\n\n/// Normalize input iterator to segment offset (specialized for arg-index)\ntemplate <typename KeyValuePairT, typename OffsetT, typename WrappedIteratorT, typename OutputValueT>\n__device__ __forceinline__\nvoid NormalizeReductionOutput(\n    KeyValuePairT &val,\n    OffsetT base_offset,\n    ArgIndexInputIterator<WrappedIteratorT, OffsetT, OutputValueT> /*itr*/)\n{\n    val.key -= base_offset;\n}\n\n\n/**\n * Segmented reduction (one block per segment)\n */\ntemplate <\n    typename                ChainedPolicyT,             ///< Chained tuning policy\n    typename                InputIteratorT,             ///< Random-access input iterator type for reading input items \\iterator\n    typename                OutputIteratorT,            ///< Output iterator type for recording the reduced aggregate \\iterator\n    typename                OffsetIteratorT,            ///< Random-access input iterator type for reading segment offsets \\iterator\n    typename                OffsetT,                    ///< Signed integer type for global offsets\n    typename                ReductionOpT,               ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename                OutputT>                    ///< Data element type that is convertible to the \\p value type of \\p OutputIteratorT\n__launch_bounds__ (int(ChainedPolicyT::ActivePolicy::ReducePolicy::BLOCK_THREADS))\n__global__ void DeviceSegmentedReduceKernel(\n    InputIteratorT          d_in,                       ///< [in] Pointer to the input sequence of data items\n    OutputIteratorT         d_out,                      ///< [out] Pointer to the output aggregate\n    OffsetIteratorT         d_begin_offsets,            ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n    OffsetIteratorT         d_end_offsets,              ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n    int                     /*num_segments*/,           ///< [in] The number of segments that comprise the sorting data\n    ReductionOpT            reduction_op,               ///< [in] Binary reduction functor \n    OutputT                 init)                       ///< [in] The initial value of the reduction\n{\n    // Thread block type for reducing input tiles\n    typedef AgentReduce<\n            typename ChainedPolicyT::ActivePolicy::ReducePolicy,\n            InputIteratorT,\n            OutputIteratorT,\n            OffsetT,\n            ReductionOpT>\n        AgentReduceT;\n\n    // Shared memory storage\n    __shared__ typename AgentReduceT::TempStorage temp_storage;\n\n    OffsetT segment_begin   = d_begin_offsets[blockIdx.x];\n    OffsetT segment_end     = d_end_offsets[blockIdx.x];\n\n    // Check if empty problem\n    if (segment_begin == segment_end)\n    {\n        if (threadIdx.x == 0)\n            d_out[blockIdx.x] = init;\n        return;\n    }\n\n    // Consume input tiles\n    OutputT block_aggregate = AgentReduceT(temp_storage, d_in, reduction_op).ConsumeRange(\n        segment_begin,\n        segment_end);\n\n    // Normalize as needed\n    NormalizeReductionOutput(block_aggregate, segment_begin, d_in);\n\n    if (threadIdx.x == 0)\n        d_out[blockIdx.x] = reduction_op(init, block_aggregate);;\n}\n\n\n\n\n/******************************************************************************\n * Policy\n ******************************************************************************/\n\ntemplate <\n    typename OuputT,            ///< Data type\n    typename OffsetT,           ///< Signed integer type for global offsets\n    typename ReductionOpT>      ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt> \nstruct DeviceReducePolicy\n{\n    //------------------------------------------------------------------------------\n    // Architecture-specific tuning policies\n    //------------------------------------------------------------------------------\n\n    /// SM13\n    struct Policy130 : ChainedPolicy<130, Policy130, Policy130>\n    {\n        // ReducePolicy\n        typedef AgentReducePolicy<\n                CUB_NOMINAL_CONFIG(128, 8, OuputT), ///< Threads per block, items per thread\n                2,                                  ///< Number of items per vectorized load\n                BLOCK_REDUCE_RAKING,                ///< Cooperative block-wide reduction algorithm to use\n                LOAD_DEFAULT>                       ///< Cache load modifier\n            ReducePolicy;\n\n        // SingleTilePolicy\n        typedef ReducePolicy SingleTilePolicy;\n\n        // SegmentedReducePolicy\n        typedef ReducePolicy SegmentedReducePolicy;\n    };\n\n\n    /// SM20\n    struct Policy200 : ChainedPolicy<200, Policy200, Policy130>\n    {\n        // ReducePolicy (GTX 580: 178.9 GB/s @ 48M 4B items, 158.1 GB/s @ 192M 1B items)\n        typedef AgentReducePolicy<\n                CUB_NOMINAL_CONFIG(128, 8, OuputT),     ///< Threads per block, items per thread\n                4,                                      ///< Number of items per vectorized load\n                BLOCK_REDUCE_RAKING,                    ///< Cooperative block-wide reduction algorithm to use\n                LOAD_DEFAULT>                           ///< Cache load modifier\n            ReducePolicy;\n\n        // SingleTilePolicy\n        typedef ReducePolicy SingleTilePolicy;\n\n        // SegmentedReducePolicy\n        typedef ReducePolicy SegmentedReducePolicy;\n    };\n\n\n    /// SM30\n    struct Policy300 : ChainedPolicy<300, Policy300, Policy200>\n    {\n        // ReducePolicy (GTX670: 154.0 @ 48M 4B items)\n        typedef AgentReducePolicy<\n                CUB_NOMINAL_CONFIG(256, 20, OuputT),    ///< Threads per block, items per thread\n                2,                                      ///< Number of items per vectorized load\n                BLOCK_REDUCE_WARP_REDUCTIONS,           ///< Cooperative block-wide reduction algorithm to use\n                LOAD_DEFAULT>                           ///< Cache load modifier\n            ReducePolicy;\n\n        // SingleTilePolicy\n        typedef ReducePolicy SingleTilePolicy;\n\n        // SegmentedReducePolicy\n        typedef ReducePolicy SegmentedReducePolicy;\n    };\n\n\n    /// SM35\n    struct Policy350 : ChainedPolicy<350, Policy350, Policy300>\n    {\n        // ReducePolicy (GTX Titan: 255.1 GB/s @ 48M 4B items; 228.7 GB/s @ 192M 1B items)\n        typedef AgentReducePolicy<\n                CUB_NOMINAL_CONFIG(256, 20, OuputT),    ///< Threads per block, items per thread\n                4,                                      ///< Number of items per vectorized load\n                BLOCK_REDUCE_WARP_REDUCTIONS,           ///< Cooperative block-wide reduction algorithm to use\n                LOAD_LDG>                               ///< Cache load modifier\n            ReducePolicy;\n\n        // SingleTilePolicy\n        typedef ReducePolicy SingleTilePolicy;\n\n        // SegmentedReducePolicy\n        typedef ReducePolicy SegmentedReducePolicy;\n    };\n\n    /// SM60\n    struct Policy600 : ChainedPolicy<600, Policy600, Policy350>\n    {\n        // ReducePolicy (P100: 591 GB/s @ 64M 4B items; 583 GB/s @ 256M 1B items)\n        typedef AgentReducePolicy<\n                CUB_NOMINAL_CONFIG(256, 16, OuputT),    ///< Threads per block, items per thread\n                4,                                      ///< Number of items per vectorized load\n                BLOCK_REDUCE_WARP_REDUCTIONS,           ///< Cooperative block-wide reduction algorithm to use\n                LOAD_LDG>                               ///< Cache load modifier\n            ReducePolicy;\n\n        // SingleTilePolicy\n        typedef ReducePolicy SingleTilePolicy;\n\n        // SegmentedReducePolicy\n        typedef ReducePolicy SegmentedReducePolicy;\n    };\n\n\n    /// MaxPolicy\n    typedef Policy600 MaxPolicy;\n\n};\n\n\n\n/******************************************************************************\n * Single-problem dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for device-wide reduction\n */\ntemplate <\n    typename InputIteratorT,    ///< Random-access input iterator type for reading input items \\iterator\n    typename OutputIteratorT,   ///< Output iterator type for recording the reduced aggregate \\iterator\n    typename OffsetT,           ///< Signed integer type for global offsets\n    typename ReductionOpT>      ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt> \nstruct DispatchReduce :\n    DeviceReducePolicy<\n        typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n            typename std::iterator_traits<InputIteratorT>::value_type,                                  // ... then the input iterator's value type,\n            typename std::iterator_traits<OutputIteratorT>::value_type>::Type,                          // ... else the output iterator's value type\n        OffsetT,\n        ReductionOpT>\n{\n    //------------------------------------------------------------------------------\n    // Constants\n    //------------------------------------------------------------------------------\n\n    // Data type of output iterator\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n\n    //------------------------------------------------------------------------------\n    // Problem state\n    //------------------------------------------------------------------------------\n\n    void                *d_temp_storage;                ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n    size_t              &temp_storage_bytes;            ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n    InputIteratorT      d_in;                           ///< [in] Pointer to the input sequence of data items\n    OutputIteratorT     d_out;                          ///< [out] Pointer to the output aggregate\n    OffsetT             num_items;                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n    ReductionOpT        reduction_op;                   ///< [in] Binary reduction functor \n    OutputT             init;                           ///< [in] The initial value of the reduction\n    cudaStream_t        stream;                         ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n    bool                debug_synchronous;              ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    int                 ptx_version;                    ///< [in] PTX version\n\n    //------------------------------------------------------------------------------\n    // Constructor\n    //------------------------------------------------------------------------------\n\n    /// Constructor\n    CUB_RUNTIME_FUNCTION __forceinline__\n    DispatchReduce(\n        void*                   d_temp_storage,\n        size_t                  &temp_storage_bytes,\n        InputIteratorT          d_in,\n        OutputIteratorT         d_out,\n        OffsetT                 num_items,\n        ReductionOpT            reduction_op,\n        OutputT                 init,\n        cudaStream_t            stream,\n        bool                    debug_synchronous,\n        int                     ptx_version)\n    :\n        d_temp_storage(d_temp_storage),\n        temp_storage_bytes(temp_storage_bytes),\n        d_in(d_in),\n        d_out(d_out),\n        num_items(num_items),\n        reduction_op(reduction_op),\n        init(init),\n        stream(stream),\n        debug_synchronous(debug_synchronous),\n        ptx_version(ptx_version)\n    {}\n\n\n    //------------------------------------------------------------------------------\n    // Small-problem (single tile) invocation\n    //------------------------------------------------------------------------------\n\n    /// Invoke a single block block to reduce in-core\n    template <\n        typename                ActivePolicyT,          ///< Umbrella policy active for the target device\n        typename                SingleTileKernelT>      ///< Function type of cub::DeviceReduceSingleTileKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokeSingleTile(\n        SingleTileKernelT       single_tile_kernel)     ///< [in] Kernel function pointer to parameterization of cub::DeviceReduceSingleTileKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n        (void)single_tile_kernel;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Return if the caller is simply requesting the size of the storage allocation\n            if (d_temp_storage == NULL)\n            {\n                temp_storage_bytes = 1;\n                break;\n            }\n\n            // Log single_reduce_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking DeviceReduceSingleTileKernel<<<1, %d, 0, %lld>>>(), %d items per thread\\n\",\n                ActivePolicyT::SingleTilePolicy::BLOCK_THREADS,\n                (long long) stream,\n                ActivePolicyT::SingleTilePolicy::ITEMS_PER_THREAD);\n\n            // Invoke single_reduce_sweep_kernel\n            single_tile_kernel<<<1, ActivePolicyT::SingleTilePolicy::BLOCK_THREADS, 0, stream>>>(\n                d_in,\n                d_out,\n                num_items,\n                reduction_op,\n                init);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Normal problem size invocation (two-pass)\n    //------------------------------------------------------------------------------\n\n    /// Invoke two-passes to reduce\n    template <\n        typename                ActivePolicyT,              ///< Umbrella policy active for the target device\n        typename                ReduceKernelT,              ///< Function type of cub::DeviceReduceKernel\n        typename                SingleTileKernelT>          ///< Function type of cub::DeviceReduceSingleTileKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePasses(\n        ReduceKernelT           reduce_kernel,          ///< [in] Kernel function pointer to parameterization of cub::DeviceReduceKernel\n        SingleTileKernelT       single_tile_kernel)     ///< [in] Kernel function pointer to parameterization of cub::DeviceReduceSingleTileKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n        (void)                  reduce_kernel;\n        (void)                  single_tile_kernel;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Init regular kernel configuration\n            KernelConfig reduce_config;\n            if (CubDebug(error = reduce_config.Init<typename ActivePolicyT::ReducePolicy>(reduce_kernel))) break;\n            int reduce_device_occupancy = reduce_config.sm_occupancy * sm_count;\n\n            // Even-share work distribution\n            int max_blocks = reduce_device_occupancy * CUB_SUBSCRIPTION_FACTOR(ptx_version);\n            GridEvenShare<OffsetT> even_share;\n            even_share.DispatchInit(num_items, max_blocks, reduce_config.tile_size);\n\n            // Temporary storage allocation requirements\n            void* allocations[1];\n            size_t allocation_sizes[1] =\n            {\n                max_blocks * sizeof(OutputT)    // bytes needed for privatized block reductions\n            };\n\n            // Alias the temporary allocations from the single storage blob (or compute the necessary size of the blob)\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                return cudaSuccess;\n            }\n\n            // Alias the allocation for the privatized per-block reductions\n            OutputT *d_block_reductions = (OutputT*) allocations[0];\n\n            // Get grid size for device_reduce_sweep_kernel\n            int reduce_grid_size = even_share.grid_size;\n\n            // Log device_reduce_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking DeviceReduceKernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                reduce_grid_size,\n                ActivePolicyT::ReducePolicy::BLOCK_THREADS,\n                (long long) stream,\n                ActivePolicyT::ReducePolicy::ITEMS_PER_THREAD,\n                reduce_config.sm_occupancy);\n\n            // Invoke DeviceReduceKernel\n            reduce_kernel<<<reduce_grid_size, ActivePolicyT::ReducePolicy::BLOCK_THREADS, 0, stream>>>(\n                d_in,\n                d_block_reductions,\n                num_items,\n                even_share,\n                reduction_op);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Log single_reduce_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking DeviceReduceSingleTileKernel<<<1, %d, 0, %lld>>>(), %d items per thread\\n\",\n                ActivePolicyT::SingleTilePolicy::BLOCK_THREADS,\n                (long long) stream,\n                ActivePolicyT::SingleTilePolicy::ITEMS_PER_THREAD);\n\n            // Invoke DeviceReduceSingleTileKernel\n            single_tile_kernel<<<1, ActivePolicyT::SingleTilePolicy::BLOCK_THREADS, 0, stream>>>(\n                d_block_reductions,\n                d_out,\n                reduce_grid_size,\n                reduction_op,\n                init);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Chained policy invocation\n    //------------------------------------------------------------------------------\n\n    /// Invocation\n    template <typename ActivePolicyT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t Invoke()\n    {\n        typedef typename ActivePolicyT::SingleTilePolicy    SingleTilePolicyT;\n        typedef typename DispatchReduce::MaxPolicy          MaxPolicyT;\n\n        // Force kernel code-generation in all compiler passes\n        if (num_items <= (SingleTilePolicyT::BLOCK_THREADS * SingleTilePolicyT::ITEMS_PER_THREAD))\n        {\n            // Small, single tile size\n            return InvokeSingleTile<ActivePolicyT>(\n                DeviceReduceSingleTileKernel<MaxPolicyT, InputIteratorT, OutputIteratorT, OffsetT, ReductionOpT, OutputT>);\n        }\n        else\n        {\n            // Regular size\n            return InvokePasses<ActivePolicyT>(\n                DeviceReduceKernel<typename DispatchReduce::MaxPolicy, InputIteratorT, OutputT*, OffsetT, ReductionOpT>,\n                DeviceReduceSingleTileKernel<MaxPolicyT, OutputT*, OutputIteratorT, OffsetT, ReductionOpT, OutputT>);\n        }\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Dispatch entrypoints\n    //------------------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine for computing a device-wide reduction\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void            *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t          &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                              ///< [out] Pointer to the output aggregate\n        OffsetT         num_items,                          ///< [in] Total number of input items (i.e., length of \\p d_in)\n        ReductionOpT    reduction_op,                       ///< [in] Binary reduction functor \n        OutputT         init,                               ///< [in] The initial value of the reduction\n        cudaStream_t    stream,                             ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous)                  ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        typedef typename DispatchReduce::MaxPolicy MaxPolicyT;\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n\n            // Create dispatch functor\n            DispatchReduce dispatch(\n                d_temp_storage, temp_storage_bytes,\n                d_in, d_out, num_items, reduction_op, init,\n                stream, debug_synchronous, ptx_version);\n\n            // Dispatch to chained policy\n            if (CubDebug(error = MaxPolicyT::Invoke(ptx_version, dispatch))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n\n/******************************************************************************\n * Segmented dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for device-wide reduction\n */\ntemplate <\n    typename InputIteratorT,    ///< Random-access input iterator type for reading input items \\iterator\n    typename OutputIteratorT,   ///< Output iterator type for recording the reduced aggregate \\iterator\n    typename OffsetIteratorT,   ///< Random-access input iterator type for reading segment offsets \\iterator\n    typename OffsetT,           ///< Signed integer type for global offsets\n    typename ReductionOpT>      ///< Binary reduction functor type having member <tt>T operator()(const T &a, const T &b)</tt> \nstruct DispatchSegmentedReduce :\n    DeviceReducePolicy<\n        typename std::iterator_traits<InputIteratorT>::value_type,\n        OffsetT,\n        ReductionOpT>\n{\n    //------------------------------------------------------------------------------\n    // Constants\n    //------------------------------------------------------------------------------\n\n    /// The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n\n    //------------------------------------------------------------------------------\n    // Problem state\n    //------------------------------------------------------------------------------\n\n    void                *d_temp_storage;        ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n    size_t              &temp_storage_bytes;    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n    InputIteratorT      d_in;                   ///< [in] Pointer to the input sequence of data items\n    OutputIteratorT     d_out;                  ///< [out] Pointer to the output aggregate\n    OffsetT             num_segments;           ///< [in] The number of segments that comprise the sorting data\n    OffsetIteratorT     d_begin_offsets;        ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n    OffsetIteratorT     d_end_offsets;          ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n    ReductionOpT        reduction_op;           ///< [in] Binary reduction functor \n    OutputT             init;                   ///< [in] The initial value of the reduction\n    cudaStream_t        stream;                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n    bool                debug_synchronous;      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    int                 ptx_version;            ///< [in] PTX version\n\n    //------------------------------------------------------------------------------\n    // Constructor\n    //------------------------------------------------------------------------------\n\n    /// Constructor\n    CUB_RUNTIME_FUNCTION __forceinline__\n    DispatchSegmentedReduce(\n        void*                   d_temp_storage,\n        size_t                  &temp_storage_bytes,\n        InputIteratorT          d_in,\n        OutputIteratorT         d_out,\n        OffsetT                 num_segments,\n        OffsetIteratorT         d_begin_offsets,\n        OffsetIteratorT         d_end_offsets,\n        ReductionOpT            reduction_op,\n        OutputT                 init,\n        cudaStream_t            stream,\n        bool                    debug_synchronous,\n        int                     ptx_version)\n    :\n        d_temp_storage(d_temp_storage),\n        temp_storage_bytes(temp_storage_bytes),\n        d_in(d_in),\n        d_out(d_out),\n        num_segments(num_segments),\n        d_begin_offsets(d_begin_offsets),\n        d_end_offsets(d_end_offsets),\n        reduction_op(reduction_op),\n        init(init),\n        stream(stream),\n        debug_synchronous(debug_synchronous),\n        ptx_version(ptx_version)\n    {}\n\n\n\n    //------------------------------------------------------------------------------\n    // Chained policy invocation\n    //------------------------------------------------------------------------------\n\n    /// Invocation\n    template <\n        typename                        ActivePolicyT,                  ///< Umbrella policy active for the target device\n        typename                        DeviceSegmentedReduceKernelT>   ///< Function type of cub::DeviceSegmentedReduceKernel\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t InvokePasses(\n        DeviceSegmentedReduceKernelT    segmented_reduce_kernel)        ///< [in] Kernel function pointer to parameterization of cub::DeviceSegmentedReduceKernel\n    {\n#ifndef CUB_RUNTIME_ENABLED\n        (void)segmented_reduce_kernel;\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n#else\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Return if the caller is simply requesting the size of the storage allocation\n            if (d_temp_storage == NULL)\n            {\n                temp_storage_bytes = 1;\n                return cudaSuccess;\n            }\n\n            // Init kernel configuration\n            KernelConfig segmented_reduce_config;\n            if (CubDebug(error = segmented_reduce_config.Init<typename ActivePolicyT::SegmentedReducePolicy>(segmented_reduce_kernel))) break;\n\n            // Log device_reduce_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking SegmentedDeviceReduceKernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                num_segments,\n                ActivePolicyT::SegmentedReducePolicy::BLOCK_THREADS,\n                (long long) stream,\n                ActivePolicyT::SegmentedReducePolicy::ITEMS_PER_THREAD,\n                segmented_reduce_config.sm_occupancy);\n\n            // Invoke DeviceReduceKernel\n            segmented_reduce_kernel<<<num_segments, ActivePolicyT::SegmentedReducePolicy::BLOCK_THREADS, 0, stream>>>(\n                d_in,\n                d_out,\n                d_begin_offsets,\n                d_end_offsets,\n                num_segments,\n                reduction_op,\n                init);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n\n    }\n\n\n    /// Invocation\n    template <typename ActivePolicyT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t Invoke()\n    {\n        typedef typename DispatchSegmentedReduce::MaxPolicy MaxPolicyT;\n\n        // Force kernel code-generation in all compiler passes\n        return InvokePasses<ActivePolicyT>(\n            DeviceSegmentedReduceKernel<MaxPolicyT, InputIteratorT, OutputIteratorT, OffsetIteratorT, OffsetT, ReductionOpT, OutputT>);\n    }\n\n\n    //------------------------------------------------------------------------------\n    // Dispatch entrypoints\n    //------------------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine for computing a device-wide reduction\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void            *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t          &temp_storage_bytes,                ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                               ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                              ///< [out] Pointer to the output aggregate\n        int             num_segments,                       ///< [in] The number of segments that comprise the sorting data\n        OffsetIteratorT d_begin_offsets,                    ///< [in] Pointer to the sequence of beginning offsets of length \\p num_segments, such that <tt>d_begin_offsets[i]</tt> is the first element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>\n        OffsetIteratorT d_end_offsets,                      ///< [in] Pointer to the sequence of ending offsets of length \\p num_segments, such that <tt>d_end_offsets[i]-1</tt> is the last element of the <em>i</em><sup>th</sup> data segment in <tt>d_keys_*</tt> and <tt>d_values_*</tt>.  If <tt>d_end_offsets[i]-1</tt> <= <tt>d_begin_offsets[i]</tt>, the <em>i</em><sup>th</sup> is considered empty.\n        ReductionOpT    reduction_op,                       ///< [in] Binary reduction functor \n        OutputT         init,                               ///< [in] The initial value of the reduction\n        cudaStream_t    stream,                             ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous)                  ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        typedef typename DispatchSegmentedReduce::MaxPolicy MaxPolicyT;\n\n        if (num_segments <= 0)\n            return cudaSuccess;\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n\n            // Create dispatch functor\n            DispatchSegmentedReduce dispatch(\n                d_temp_storage, temp_storage_bytes,\n                d_in, d_out,\n                num_segments, d_begin_offsets, d_end_offsets,\n                reduction_op, init,\n                stream, debug_synchronous, ptx_version);\n\n            // Dispatch to chained policy\n            if (CubDebug(error = MaxPolicyT::Invoke(ptx_version, dispatch))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_reduce_by_key.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceReduceByKey provides device-wide, parallel operations for reducing segments of values residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch_scan.cuh\"\n#include \"../../agent/agent_reduce_by_key.cuh\"\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Multi-block reduce-by-key sweep kernel entry point\n */\ntemplate <\n    typename            AgentReduceByKeyPolicyT,                 ///< Parameterized AgentReduceByKeyPolicyT tuning policy type\n    typename            KeysInputIteratorT,                     ///< Random-access input iterator type for keys\n    typename            UniqueOutputIteratorT,                  ///< Random-access output iterator type for keys\n    typename            ValuesInputIteratorT,                   ///< Random-access input iterator type for values\n    typename            AggregatesOutputIteratorT,              ///< Random-access output iterator type for values\n    typename            NumRunsOutputIteratorT,                 ///< Output iterator type for recording number of segments encountered\n    typename            ScanTileStateT,                         ///< Tile status interface type\n    typename            EqualityOpT,                            ///< KeyT equality operator type\n    typename            ReductionOpT,                           ///< ValueT reduction operator type\n    typename            OffsetT>                                ///< Signed integer type for global offsets\n__launch_bounds__ (int(AgentReduceByKeyPolicyT::BLOCK_THREADS))\n__global__ void DeviceReduceByKeyKernel(\n    KeysInputIteratorT          d_keys_in,                      ///< Pointer to the input sequence of keys\n    UniqueOutputIteratorT       d_unique_out,                   ///< Pointer to the output sequence of unique keys (one key per run)\n    ValuesInputIteratorT        d_values_in,                    ///< Pointer to the input sequence of corresponding values\n    AggregatesOutputIteratorT   d_aggregates_out,               ///< Pointer to the output sequence of value aggregates (one aggregate per run)\n    NumRunsOutputIteratorT      d_num_runs_out,                 ///< Pointer to total number of runs encountered (i.e., the length of d_unique_out)\n    ScanTileStateT              tile_state,                     ///< Tile status interface\n    int                         start_tile,                     ///< The starting tile for the current grid\n    EqualityOpT                 equality_op,                    ///< KeyT equality operator\n    ReductionOpT                reduction_op,                   ///< ValueT reduction operator\n    OffsetT                     num_items)                      ///< Total number of items to select from\n{\n    // Thread block type for reducing tiles of value segments\n    typedef AgentReduceByKey<\n            AgentReduceByKeyPolicyT,\n            KeysInputIteratorT,\n            UniqueOutputIteratorT,\n            ValuesInputIteratorT,\n            AggregatesOutputIteratorT,\n            NumRunsOutputIteratorT,\n            EqualityOpT,\n            ReductionOpT,\n            OffsetT>\n        AgentReduceByKeyT;\n\n    // Shared memory for AgentReduceByKey\n    __shared__ typename AgentReduceByKeyT::TempStorage temp_storage;\n\n    // Process tiles\n    AgentReduceByKeyT(temp_storage, d_keys_in, d_unique_out, d_values_in, d_aggregates_out, d_num_runs_out, equality_op, reduction_op).ConsumeRange(\n        num_items,\n        tile_state,\n        start_tile);\n}\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceReduceByKey\n */\ntemplate <\n    typename    KeysInputIteratorT,         ///< Random-access input iterator type for keys\n    typename    UniqueOutputIteratorT,      ///< Random-access output iterator type for keys\n    typename    ValuesInputIteratorT,       ///< Random-access input iterator type for values\n    typename    AggregatesOutputIteratorT,  ///< Random-access output iterator type for values\n    typename    NumRunsOutputIteratorT,     ///< Output iterator type for recording number of segments encountered\n    typename    EqualityOpT,                ///< KeyT equality operator type\n    typename    ReductionOpT,               ///< ValueT reduction operator type\n    typename    OffsetT>                    ///< Signed integer type for global offsets\nstruct DispatchReduceByKey\n{\n    //-------------------------------------------------------------------------\n    // Types and constants\n    //-------------------------------------------------------------------------\n\n    // The input keys type\n    typedef typename std::iterator_traits<KeysInputIteratorT>::value_type KeyInputT;\n\n    // The output keys type\n    typedef typename If<(Equals<typename std::iterator_traits<UniqueOutputIteratorT>::value_type, void>::VALUE),    // KeyOutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<KeysInputIteratorT>::value_type,                                              // ... then the input iterator's value type,\n        typename std::iterator_traits<UniqueOutputIteratorT>::value_type>::Type KeyOutputT;                         // ... else the output iterator's value type\n\n    // The input values type\n    typedef typename std::iterator_traits<ValuesInputIteratorT>::value_type ValueInputT;\n\n    // The output values type\n    typedef typename If<(Equals<typename std::iterator_traits<AggregatesOutputIteratorT>::value_type, void>::VALUE),    // ValueOutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<ValuesInputIteratorT>::value_type,                                                // ... then the input iterator's value type,\n        typename std::iterator_traits<AggregatesOutputIteratorT>::value_type>::Type ValueOutputT;                       // ... else the output iterator's value type\n\n    enum\n    {\n        INIT_KERNEL_THREADS     = 128,\n        MAX_INPUT_BYTES         = CUB_MAX(sizeof(KeyOutputT), sizeof(ValueOutputT)),\n        COMBINED_INPUT_BYTES    = sizeof(KeyOutputT) + sizeof(ValueOutputT),\n    };\n\n    // Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<ValueOutputT, OffsetT> ScanTileStateT;\n\n\n    //-------------------------------------------------------------------------\n    // Tuning policies\n    //-------------------------------------------------------------------------\n\n    /// SM35\n    struct Policy350\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 6,\n            ITEMS_PER_THREAD            = (MAX_INPUT_BYTES <= 8) ? 6 : CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, ((NOMINAL_4B_ITEMS_PER_THREAD * 8) + COMBINED_INPUT_BYTES - 1) / COMBINED_INPUT_BYTES)),\n        };\n\n        typedef AgentReduceByKeyPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                BLOCK_SCAN_WARP_SCANS>\n            ReduceByKeyPolicyT;\n    };\n\n    /// SM30\n    struct Policy300\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 6,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, ((NOMINAL_4B_ITEMS_PER_THREAD * 8) + COMBINED_INPUT_BYTES - 1) / COMBINED_INPUT_BYTES)),\n        };\n\n        typedef AgentReduceByKeyPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            ReduceByKeyPolicyT;\n    };\n\n    /// SM20\n    struct Policy200\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 11,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, ((NOMINAL_4B_ITEMS_PER_THREAD * 8) + COMBINED_INPUT_BYTES - 1) / COMBINED_INPUT_BYTES)),\n        };\n\n        typedef AgentReduceByKeyPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            ReduceByKeyPolicyT;\n    };\n\n    /// SM13\n    struct Policy130\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 7,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, ((NOMINAL_4B_ITEMS_PER_THREAD * 8) + COMBINED_INPUT_BYTES - 1) / COMBINED_INPUT_BYTES)),\n        };\n\n        typedef AgentReduceByKeyPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            ReduceByKeyPolicyT;\n    };\n\n    /// SM11\n    struct Policy110\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 5,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 8) / COMBINED_INPUT_BYTES)),\n        };\n\n        typedef AgentReduceByKeyPolicy<\n                64,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_RAKING>\n            ReduceByKeyPolicyT;\n    };\n\n\n    /******************************************************************************\n     * Tuning policies of current PTX compiler pass\n     ******************************************************************************/\n\n#if (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 130)\n    typedef Policy130 PtxPolicy;\n\n#else\n    typedef Policy110 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxReduceByKeyPolicy : PtxPolicy::ReduceByKeyPolicyT {};\n\n\n    /******************************************************************************\n     * Utilities\n     ******************************************************************************/\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static void InitConfigs(\n        int             ptx_version,\n        KernelConfig    &reduce_by_key_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n        (void)ptx_version;\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        reduce_by_key_config.template Init<PtxReduceByKeyPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 350)\n        {\n            reduce_by_key_config.template Init<typename Policy350::ReduceByKeyPolicyT>();\n        }\n        else if (ptx_version >= 300)\n        {\n            reduce_by_key_config.template Init<typename Policy300::ReduceByKeyPolicyT>();\n        }\n        else if (ptx_version >= 200)\n        {\n            reduce_by_key_config.template Init<typename Policy200::ReduceByKeyPolicyT>();\n        }\n        else if (ptx_version >= 130)\n        {\n            reduce_by_key_config.template Init<typename Policy130::ReduceByKeyPolicyT>();\n        }\n        else\n        {\n            reduce_by_key_config.template Init<typename Policy110::ReduceByKeyPolicyT>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration.\n     */\n    struct KernelConfig\n    {\n        int block_threads;\n        int items_per_thread;\n        int tile_items;\n\n        template <typename PolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Init()\n        {\n            block_threads       = PolicyT::BLOCK_THREADS;\n            items_per_thread    = PolicyT::ITEMS_PER_THREAD;\n            tile_items          = block_threads * items_per_thread;\n        }\n    };\n\n\n    //---------------------------------------------------------------------\n    // Dispatch entrypoints\n    //---------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine for computing a device-wide reduce-by-key using the\n     * specified kernel functions.\n     */\n    template <\n        typename                    ScanInitKernelT,         ///< Function type of cub::DeviceScanInitKernel\n        typename                    ReduceByKeyKernelT>      ///< Function type of cub::DeviceReduceByKeyKernelT\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,             ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,         ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        KeysInputIteratorT          d_keys_in,                  ///< [in] Pointer to the input sequence of keys\n        UniqueOutputIteratorT       d_unique_out,               ///< [out] Pointer to the output sequence of unique keys (one key per run)\n        ValuesInputIteratorT        d_values_in,                ///< [in] Pointer to the input sequence of corresponding values\n        AggregatesOutputIteratorT   d_aggregates_out,           ///< [out] Pointer to the output sequence of value aggregates (one aggregate per run)\n        NumRunsOutputIteratorT      d_num_runs_out,             ///< [out] Pointer to total number of runs encountered (i.e., the length of d_unique_out)\n        EqualityOpT                 equality_op,                ///< [in] KeyT equality operator\n        ReductionOpT                reduction_op,               ///< [in] ValueT reduction operator\n        OffsetT                     num_items,                  ///< [in] Total number of items to select from\n        cudaStream_t                stream,                     ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous,          ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        int                         /*ptx_version*/,            ///< [in] PTX version of dispatch kernels\n        ScanInitKernelT                init_kernel,                ///< [in] Kernel function pointer to parameterization of cub::DeviceScanInitKernel\n        ReduceByKeyKernelT             reduce_by_key_kernel,       ///< [in] Kernel function pointer to parameterization of cub::DeviceReduceByKeyKernel\n        KernelConfig                reduce_by_key_config)       ///< [in] Dispatch parameters that match the policy that \\p reduce_by_key_kernel was compiled for\n    {\n\n#ifndef CUB_RUNTIME_ENABLED\n      (void)d_temp_storage;\n      (void)temp_storage_bytes;\n      (void)d_keys_in;\n      (void)d_unique_out;\n      (void)d_values_in;\n      (void)d_aggregates_out;\n      (void)d_num_runs_out;\n      (void)equality_op;\n      (void)reduction_op;\n      (void)num_items;\n      (void)stream;\n      (void)debug_synchronous;\n      (void)init_kernel;\n      (void)reduce_by_key_kernel;\n      (void)reduce_by_key_config;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported);\n\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Number of input tiles\n            int tile_size = reduce_by_key_config.block_threads * reduce_by_key_config.items_per_thread;\n            int num_tiles = (num_items + tile_size - 1) / tile_size;\n\n            // Specify temporary storage allocation requirements\n            size_t  allocation_sizes[1];\n            if (CubDebug(error = ScanTileStateT::AllocationSize(num_tiles, allocation_sizes[0]))) break;    // bytes needed for tile status descriptors\n\n            // Compute allocation pointers into the single storage blob (or compute the necessary size of the blob)\n            void* allocations[1];\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Construct the tile status interface\n            ScanTileStateT tile_state;\n            if (CubDebug(error = tile_state.Init(num_tiles, allocations[0], allocation_sizes[0]))) break;\n\n            // Log init_kernel configuration\n            int init_grid_size = CUB_MAX(1, (num_tiles + INIT_KERNEL_THREADS - 1) / INIT_KERNEL_THREADS);\n            if (debug_synchronous) _CubLog(\"Invoking init_kernel<<<%d, %d, 0, %lld>>>()\\n\", init_grid_size, INIT_KERNEL_THREADS, (long long) stream);\n\n            // Invoke init_kernel to initialize tile descriptors\n            init_kernel<<<init_grid_size, INIT_KERNEL_THREADS, 0, stream>>>(\n                tile_state,\n                num_tiles,\n                d_num_runs_out);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Return if empty problem\n            if (num_items == 0)\n                break;\n\n            // Get SM occupancy for reduce_by_key_kernel\n            int reduce_by_key_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                reduce_by_key_sm_occupancy,            // out\n                reduce_by_key_kernel,\n                reduce_by_key_config.block_threads))) break;\n\n            // Get max x-dimension of grid\n            int max_dim_x;\n            if (CubDebug(error = cudaDeviceGetAttribute(&max_dim_x, cudaDevAttrMaxGridDimX, device_ordinal))) break;;\n\n            // Run grids in epochs (in case number of tiles exceeds max x-dimension\n            int scan_grid_size = CUB_MIN(num_tiles, max_dim_x);\n            for (int start_tile = 0; start_tile < num_tiles; start_tile += scan_grid_size)\n            {\n                // Log reduce_by_key_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking %d reduce_by_key_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                    start_tile, scan_grid_size, reduce_by_key_config.block_threads, (long long) stream, reduce_by_key_config.items_per_thread, reduce_by_key_sm_occupancy);\n\n                // Invoke reduce_by_key_kernel\n                reduce_by_key_kernel<<<scan_grid_size, reduce_by_key_config.block_threads, 0, stream>>>(\n                    d_keys_in,\n                    d_unique_out,\n                    d_values_in,\n                    d_aggregates_out,\n                    d_num_runs_out,\n                    tile_state,\n                    start_tile,\n                    equality_op,\n                    reduction_op,\n                    num_items);\n\n                // Check for failure to launch\n                if (CubDebug(error = cudaPeekAtLastError())) break;\n\n                // Sync the stream if specified to flush runtime errors\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n        }\n        while (0);\n\n        return error;\n\n#endif  // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        KeysInputIteratorT          d_keys_in,                      ///< [in] Pointer to the input sequence of keys\n        UniqueOutputIteratorT       d_unique_out,                   ///< [out] Pointer to the output sequence of unique keys (one key per run)\n        ValuesInputIteratorT        d_values_in,                    ///< [in] Pointer to the input sequence of corresponding values\n        AggregatesOutputIteratorT   d_aggregates_out,               ///< [out] Pointer to the output sequence of value aggregates (one aggregate per run)\n        NumRunsOutputIteratorT      d_num_runs_out,                 ///< [out] Pointer to total number of runs encountered (i.e., the length of d_unique_out)\n        EqualityOpT                 equality_op,                    ///< [in] KeyT equality operator\n        ReductionOpT                reduction_op,                   ///< [in] ValueT reduction operator\n        OffsetT                     num_items,                      ///< [in] Total number of items to select from\n        cudaStream_t                stream,                         ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous)              ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel kernel dispatch configurations\n            KernelConfig reduce_by_key_config;\n            InitConfigs(ptx_version, reduce_by_key_config);\n\n            // Dispatch\n            if (CubDebug(error = Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_keys_in,\n                d_unique_out,\n                d_values_in,\n                d_aggregates_out,\n                d_num_runs_out,\n                equality_op,\n                reduction_op,\n                num_items,\n                stream,\n                debug_synchronous,\n                ptx_version,\n                DeviceCompactInitKernel<ScanTileStateT, NumRunsOutputIteratorT>,\n                DeviceReduceByKeyKernel<PtxReduceByKeyPolicy, KeysInputIteratorT, UniqueOutputIteratorT, ValuesInputIteratorT, AggregatesOutputIteratorT, NumRunsOutputIteratorT, ScanTileStateT, EqualityOpT, ReductionOpT, OffsetT>,\n                reduce_by_key_config))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_rle.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceRle provides device-wide, parallel operations for run-length-encoding sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch_scan.cuh\"\n#include \"../../agent/agent_rle.cuh\"\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Select kernel entry point (multi-block)\n *\n * Performs functor-based selection if SelectOp functor type != NullType\n * Otherwise performs flag-based selection if FlagIterator's value type != NullType\n * Otherwise performs discontinuity selection (keep unique)\n */\ntemplate <\n    typename            AgentRlePolicyT,        ///< Parameterized AgentRlePolicyT tuning policy type\n    typename            InputIteratorT,             ///< Random-access input iterator type for reading input items \\iterator\n    typename            OffsetsOutputIteratorT,     ///< Random-access output iterator type for writing run-offset values \\iterator\n    typename            LengthsOutputIteratorT,     ///< Random-access output iterator type for writing run-length values \\iterator\n    typename            NumRunsOutputIteratorT,     ///< Output iterator type for recording the number of runs encountered \\iterator\n    typename            ScanTileStateT,              ///< Tile status interface type\n    typename            EqualityOpT,                 ///< T equality operator type\n    typename            OffsetT>                    ///< Signed integer type for global offsets\n__launch_bounds__ (int(AgentRlePolicyT::BLOCK_THREADS))\n__global__ void DeviceRleSweepKernel(\n    InputIteratorT              d_in,               ///< [in] Pointer to input sequence of data items\n    OffsetsOutputIteratorT      d_offsets_out,      ///< [out] Pointer to output sequence of run-offsets\n    LengthsOutputIteratorT      d_lengths_out,      ///< [out] Pointer to output sequence of run-lengths\n    NumRunsOutputIteratorT      d_num_runs_out,     ///< [out] Pointer to total number of runs (i.e., length of \\p d_offsets_out)\n    ScanTileStateT              tile_status,        ///< [in] Tile status interface\n    EqualityOpT                 equality_op,        ///< [in] Equality operator for input items\n    OffsetT                     num_items,          ///< [in] Total number of input items (i.e., length of \\p d_in)\n    int                         num_tiles)          ///< [in] Total number of tiles for the entire problem\n{\n    // Thread block type for selecting data from input tiles\n    typedef AgentRle<\n        AgentRlePolicyT,\n        InputIteratorT,\n        OffsetsOutputIteratorT,\n        LengthsOutputIteratorT,\n        EqualityOpT,\n        OffsetT> AgentRleT;\n\n    // Shared memory for AgentRle\n    __shared__ typename AgentRleT::TempStorage temp_storage;\n\n    // Process tiles\n    AgentRleT(temp_storage, d_in, d_offsets_out, d_lengths_out, equality_op, num_items).ConsumeRange(\n        num_tiles,\n        tile_status,\n        d_num_runs_out);\n}\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceRle\n */\ntemplate <\n    typename            InputIteratorT,             ///< Random-access input iterator type for reading input items \\iterator\n    typename            OffsetsOutputIteratorT,     ///< Random-access output iterator type for writing run-offset values \\iterator\n    typename            LengthsOutputIteratorT,     ///< Random-access output iterator type for writing run-length values \\iterator\n    typename            NumRunsOutputIteratorT,     ///< Output iterator type for recording the number of runs encountered \\iterator\n    typename            EqualityOpT,                ///< T equality operator type\n    typename            OffsetT>                    ///< Signed integer type for global offsets\nstruct DeviceRleDispatch\n{\n    /******************************************************************************\n     * Types and constants\n     ******************************************************************************/\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type T;\n\n    // The lengths output value type\n    typedef typename If<(Equals<typename std::iterator_traits<LengthsOutputIteratorT>::value_type, void>::VALUE),   // LengthT =  (if output iterator's value type is void) ?\n        OffsetT,                                                                                                    // ... then the OffsetT type,\n        typename std::iterator_traits<LengthsOutputIteratorT>::value_type>::Type LengthT;                           // ... else the output iterator's value type\n\n    enum\n    {\n        INIT_KERNEL_THREADS = 128,\n    };\n\n    // Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<LengthT, OffsetT> ScanTileStateT;\n\n\n    /******************************************************************************\n     * Tuning policies\n     ******************************************************************************/\n\n    /// SM35\n    struct Policy350\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 15,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(T)))),\n        };\n\n        typedef AgentRlePolicy<\n                96,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                true,\n                BLOCK_SCAN_WARP_SCANS>\n            RleSweepPolicy;\n    };\n\n    /// SM30\n    struct Policy300\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 5,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(T)))),\n        };\n\n        typedef AgentRlePolicy<\n                256,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                true,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            RleSweepPolicy;\n    };\n\n    /// SM20\n    struct Policy200\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 15,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(T)))),\n        };\n\n        typedef AgentRlePolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                false,\n                BLOCK_SCAN_WARP_SCANS>\n            RleSweepPolicy;\n    };\n\n    /// SM13\n    struct Policy130\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 9,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(T)))),\n        };\n\n        typedef AgentRlePolicy<\n                64,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                true,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            RleSweepPolicy;\n    };\n\n    /// SM10\n    struct Policy100\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 9,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(T)))),\n        };\n\n        typedef AgentRlePolicy<\n                256,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                true,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            RleSweepPolicy;\n    };\n\n\n    /******************************************************************************\n     * Tuning policies of current PTX compiler pass\n     ******************************************************************************/\n\n#if (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 130)\n    typedef Policy130 PtxPolicy;\n\n#else\n    typedef Policy100 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxRleSweepPolicy : PtxPolicy::RleSweepPolicy {};\n\n\n    /******************************************************************************\n     * Utilities\n     ******************************************************************************/\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static void InitConfigs(\n        int             ptx_version,\n        KernelConfig&   device_rle_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        device_rle_config.template Init<PtxRleSweepPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 350)\n        {\n            device_rle_config.template Init<typename Policy350::RleSweepPolicy>();\n        }\n        else if (ptx_version >= 300)\n        {\n            device_rle_config.template Init<typename Policy300::RleSweepPolicy>();\n        }\n        else if (ptx_version >= 200)\n        {\n            device_rle_config.template Init<typename Policy200::RleSweepPolicy>();\n        }\n        else if (ptx_version >= 130)\n        {\n            device_rle_config.template Init<typename Policy130::RleSweepPolicy>();\n        }\n        else\n        {\n            device_rle_config.template Init<typename Policy100::RleSweepPolicy>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration.  Mirrors the constants within AgentRlePolicyT.\n     */\n    struct KernelConfig\n    {\n        int                     block_threads;\n        int                     items_per_thread;\n        BlockLoadAlgorithm      load_policy;\n        bool                    store_warp_time_slicing;\n        BlockScanAlgorithm      scan_algorithm;\n\n        template <typename AgentRlePolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Init()\n        {\n            block_threads               = AgentRlePolicyT::BLOCK_THREADS;\n            items_per_thread            = AgentRlePolicyT::ITEMS_PER_THREAD;\n            load_policy                 = AgentRlePolicyT::LOAD_ALGORITHM;\n            store_warp_time_slicing     = AgentRlePolicyT::STORE_WARP_TIME_SLICING;\n            scan_algorithm              = AgentRlePolicyT::SCAN_ALGORITHM;\n        }\n\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Print()\n        {\n            printf(\"%d, %d, %d, %d, %d\",\n                block_threads,\n                items_per_thread,\n                load_policy,\n                store_warp_time_slicing,\n                scan_algorithm);\n        }\n    };\n\n\n    /******************************************************************************\n     * Dispatch entrypoints\n     ******************************************************************************/\n\n    /**\n     * Internal dispatch routine for computing a device-wide run-length-encode using the\n     * specified kernel functions.\n     */\n    template <\n        typename                    DeviceScanInitKernelPtr,        ///< Function type of cub::DeviceScanInitKernel\n        typename                    DeviceRleSweepKernelPtr>        ///< Function type of cub::DeviceRleSweepKernelPtr\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        OffsetsOutputIteratorT      d_offsets_out,                  ///< [out] Pointer to the output sequence of run-offsets\n        LengthsOutputIteratorT      d_lengths_out,                  ///< [out] Pointer to the output sequence of run-lengths\n        NumRunsOutputIteratorT      d_num_runs_out,                 ///< [out] Pointer to the total number of runs encountered (i.e., length of \\p d_offsets_out)\n        EqualityOpT                 equality_op,                    ///< [in] Equality operator for input items\n        OffsetT                     num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream,                         ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous,              ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        int                         ptx_version,                    ///< [in] PTX version of dispatch kernels\n        DeviceScanInitKernelPtr     device_scan_init_kernel,        ///< [in] Kernel function pointer to parameterization of cub::DeviceScanInitKernel\n        DeviceRleSweepKernelPtr     device_rle_sweep_kernel,        ///< [in] Kernel function pointer to parameterization of cub::DeviceRleSweepKernel\n        KernelConfig                device_rle_config)              ///< [in] Dispatch parameters that match the policy that \\p device_rle_sweep_kernel was compiled for\n    {\n\n#ifndef CUB_RUNTIME_ENABLED\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported);\n\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Number of input tiles\n            int tile_size = device_rle_config.block_threads * device_rle_config.items_per_thread;\n            int num_tiles = (num_items + tile_size - 1) / tile_size;\n\n            // Specify temporary storage allocation requirements\n            size_t  allocation_sizes[1];\n            if (CubDebug(error = ScanTileStateT::AllocationSize(num_tiles, allocation_sizes[0]))) break;    // bytes needed for tile status descriptors\n\n            // Compute allocation pointers into the single storage blob (or compute the necessary size of the blob)\n            void* allocations[1];\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Construct the tile status interface\n            ScanTileStateT tile_status;\n            if (CubDebug(error = tile_status.Init(num_tiles, allocations[0], allocation_sizes[0]))) break;\n\n            // Log device_scan_init_kernel configuration\n            int init_grid_size = CUB_MAX(1, (num_tiles + INIT_KERNEL_THREADS - 1) / INIT_KERNEL_THREADS);\n            if (debug_synchronous) _CubLog(\"Invoking device_scan_init_kernel<<<%d, %d, 0, %lld>>>()\\n\", init_grid_size, INIT_KERNEL_THREADS, (long long) stream);\n\n            // Invoke device_scan_init_kernel to initialize tile descriptors and queue descriptors\n            device_scan_init_kernel<<<init_grid_size, INIT_KERNEL_THREADS, 0, stream>>>(\n                tile_status,\n                num_tiles,\n                d_num_runs_out);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Return if empty problem\n            if (num_items == 0)\n                break;\n\n            // Get SM occupancy for device_rle_sweep_kernel\n            int device_rle_kernel_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                device_rle_kernel_sm_occupancy,            // out\n                device_rle_sweep_kernel,\n                device_rle_config.block_threads))) break;\n\n            // Get max x-dimension of grid\n            int max_dim_x;\n            if (CubDebug(error = cudaDeviceGetAttribute(&max_dim_x, cudaDevAttrMaxGridDimX, device_ordinal))) break;;\n\n            // Get grid size for scanning tiles\n            dim3 scan_grid_size;\n            scan_grid_size.z = 1;\n            scan_grid_size.y = ((unsigned int) num_tiles + max_dim_x - 1) / max_dim_x;\n            scan_grid_size.x = CUB_MIN(num_tiles, max_dim_x);\n\n            // Log device_rle_sweep_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking device_rle_sweep_kernel<<<{%d,%d,%d}, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                scan_grid_size.x, scan_grid_size.y, scan_grid_size.z, device_rle_config.block_threads, (long long) stream, device_rle_config.items_per_thread, device_rle_kernel_sm_occupancy);\n\n            // Invoke device_rle_sweep_kernel\n            device_rle_sweep_kernel<<<scan_grid_size, device_rle_config.block_threads, 0, stream>>>(\n                d_in,\n                d_offsets_out,\n                d_lengths_out,\n                d_num_runs_out,\n                tile_status,\n                equality_op,\n                num_items,\n                num_tiles);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n        }\n        while (0);\n\n        return error;\n\n#endif  // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to input sequence of data items\n        OffsetsOutputIteratorT      d_offsets_out,                  ///< [out] Pointer to output sequence of run-offsets\n        LengthsOutputIteratorT      d_lengths_out,                  ///< [out] Pointer to output sequence of run-lengths\n        NumRunsOutputIteratorT      d_num_runs_out,                 ///< [out] Pointer to total number of runs (i.e., length of \\p d_offsets_out)\n        EqualityOpT                 equality_op,                    ///< [in] Equality operator for input items\n        OffsetT                     num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream,                         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous)              ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel kernel dispatch configurations\n            KernelConfig device_rle_config;\n            InitConfigs(ptx_version, device_rle_config);\n\n            // Dispatch\n            if (CubDebug(error = Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_in,\n                d_offsets_out,\n                d_lengths_out,\n                d_num_runs_out,\n                equality_op,\n                num_items,\n                stream,\n                debug_synchronous,\n                ptx_version,\n                DeviceCompactInitKernel<ScanTileStateT, NumRunsOutputIteratorT>,\n                DeviceRleSweepKernel<PtxRleSweepPolicy, InputIteratorT, OffsetsOutputIteratorT, LengthsOutputIteratorT, NumRunsOutputIteratorT, ScanTileStateT, EqualityOpT, OffsetT>,\n                device_rle_config))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_scan.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceScan provides device-wide, parallel operations for computing a prefix scan across a sequence of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"../../agent/agent_scan.cuh\"\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_arch.cuh\"\n#include \"../../util_debug.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Initialization kernel for tile status initialization (multi-block)\n */\ntemplate <\n    typename            ScanTileStateT>     ///< Tile status interface type\n__global__ void DeviceScanInitKernel(\n    ScanTileStateT      tile_state,         ///< [in] Tile status interface\n    int                 num_tiles)          ///< [in] Number of tiles\n{\n    // Initialize tile status\n    tile_state.InitializeStatus(num_tiles);\n}\n\n/**\n * Initialization kernel for tile status initialization (multi-block)\n */\ntemplate <\n    typename                ScanTileStateT,         ///< Tile status interface type\n    typename                NumSelectedIteratorT>   ///< Output iterator type for recording the number of items selected\n__global__ void DeviceCompactInitKernel(\n    ScanTileStateT          tile_state,             ///< [in] Tile status interface\n    int                     num_tiles,              ///< [in] Number of tiles\n    NumSelectedIteratorT    d_num_selected_out)     ///< [out] Pointer to the total number of items selected (i.e., length of \\p d_selected_out)\n{\n    // Initialize tile status\n    tile_state.InitializeStatus(num_tiles);\n\n    // Initialize d_num_selected_out\n    if ((blockIdx.x == 0) && (threadIdx.x == 0))\n        *d_num_selected_out = 0;\n}\n\n\n/**\n * Scan kernel entry point (multi-block)\n */\ntemplate <\n    typename            ScanPolicyT,        ///< Parameterized ScanPolicyT tuning policy type\n    typename            InputIteratorT,     ///< Random-access input iterator type for reading scan inputs \\iterator\n    typename            OutputIteratorT,    ///< Random-access output iterator type for writing scan outputs \\iterator\n    typename            ScanTileStateT,     ///< Tile status interface type\n    typename            ScanOpT,            ///< Binary scan functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename            InitValueT,         ///< Initial value to seed the exclusive scan (cub::NullType for inclusive scans)\n    typename            OffsetT>            ///< Signed integer type for global offsets\n__launch_bounds__ (int(ScanPolicyT::BLOCK_THREADS))\n__global__ void DeviceScanKernel(\n    InputIteratorT      d_in,               ///< Input data\n    OutputIteratorT     d_out,              ///< Output data\n    ScanTileStateT      tile_state,         ///< Tile status interface\n    int                 start_tile,         ///< The starting tile for the current grid\n    ScanOpT             scan_op,            ///< Binary scan functor \n    InitValueT          init_value,         ///< Initial value to seed the exclusive scan\n    OffsetT             num_items)          ///< Total number of scan items for the entire problem\n{\n    // Thread block type for scanning input tiles\n    typedef AgentScan<\n        ScanPolicyT,\n        InputIteratorT,\n        OutputIteratorT,\n        ScanOpT,\n        InitValueT,\n        OffsetT> AgentScanT;\n\n    // Shared memory for AgentScan\n    __shared__ typename AgentScanT::TempStorage temp_storage;\n\n    // Process tiles\n    AgentScanT(temp_storage, d_in, d_out, scan_op, init_value).ConsumeRange(\n        num_items,\n        tile_state,\n        start_tile);\n}\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceScan\n */\ntemplate <\n    typename InputIteratorT,     ///< Random-access input iterator type for reading scan inputs \\iterator\n    typename OutputIteratorT,    ///< Random-access output iterator type for writing scan outputs \\iterator\n    typename ScanOpT,            ///< Binary scan functor type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename InitValueT,          ///< The init_value element type for ScanOpT (cub::NullType for inclusive scans)\n    typename OffsetT>            ///< Signed integer type for global offsets\nstruct DispatchScan\n{\n    //---------------------------------------------------------------------\n    // Constants and Types\n    //---------------------------------------------------------------------\n\n    enum\n    {\n        INIT_KERNEL_THREADS = 128\n    };\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Tile status descriptor interface type\n    typedef ScanTileState<OutputT> ScanTileStateT;\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies\n    //---------------------------------------------------------------------\n\n    /// SM600\n    struct Policy600\n    {\n        typedef AgentScanPolicy<\n            CUB_NOMINAL_CONFIG(128, 15, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_STORE_TRANSPOSE,\n                BLOCK_SCAN_WARP_SCANS>\n            ScanPolicyT;\n    };\n\n\n    /// SM520\n    struct Policy520\n    {\n        // Titan X: 32.47B items/s @ 48M 32-bit T\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(128, 12, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                BLOCK_STORE_WARP_TRANSPOSE,\n                BLOCK_SCAN_WARP_SCANS>\n            ScanPolicyT;\n    };\n\n\n    /// SM35\n    struct Policy350\n    {\n        // GTX Titan: 29.5B items/s (232.4 GB/s) @ 48M 32-bit T\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(128, 12, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                BLOCK_STORE_WARP_TRANSPOSE_TIMESLICED,\n                BLOCK_SCAN_RAKING>\n            ScanPolicyT;\n    };\n\n    /// SM30\n    struct Policy300\n    {\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(256, 9, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_STORE_WARP_TRANSPOSE,\n                BLOCK_SCAN_WARP_SCANS>\n            ScanPolicyT;\n    };\n\n    /// SM20\n    struct Policy200\n    {\n        // GTX 580: 20.3B items/s (162.3 GB/s) @ 48M 32-bit T\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(128, 12, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_STORE_WARP_TRANSPOSE,\n                BLOCK_SCAN_WARP_SCANS>\n            ScanPolicyT;\n    };\n\n    /// SM13\n    struct Policy130\n    {\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(96, 21, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_STORE_WARP_TRANSPOSE,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            ScanPolicyT;\n    };\n\n    /// SM10\n    struct Policy100\n    {\n        typedef AgentScanPolicy<\n                CUB_NOMINAL_CONFIG(64, 9, OutputT),      ///< Threads per block, items per thread\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_STORE_WARP_TRANSPOSE,\n                BLOCK_SCAN_WARP_SCANS>\n            ScanPolicyT;\n    };\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies of current PTX compiler pass\n    //---------------------------------------------------------------------\n\n#if (CUB_PTX_ARCH >= 600)\n    typedef Policy600 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 520)\n    typedef Policy520 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 130)\n    typedef Policy130 PtxPolicy;\n\n#else\n    typedef Policy100 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxAgentScanPolicy : PtxPolicy::ScanPolicyT {};\n\n\n    //---------------------------------------------------------------------\n    // Utilities\n    //---------------------------------------------------------------------\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static void InitConfigs(\n        int             ptx_version,\n        KernelConfig    &scan_kernel_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n        (void)ptx_version;\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        scan_kernel_config.template Init<PtxAgentScanPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 600)\n        {\n            scan_kernel_config.template Init<typename Policy600::ScanPolicyT>();\n        }\n        else if (ptx_version >= 520)\n        {\n            scan_kernel_config.template Init<typename Policy520::ScanPolicyT>();\n        }\n        else if (ptx_version >= 350)\n        {\n            scan_kernel_config.template Init<typename Policy350::ScanPolicyT>();\n        }\n        else if (ptx_version >= 300)\n        {\n            scan_kernel_config.template Init<typename Policy300::ScanPolicyT>();\n        }\n        else if (ptx_version >= 200)\n        {\n            scan_kernel_config.template Init<typename Policy200::ScanPolicyT>();\n        }\n        else if (ptx_version >= 130)\n        {\n            scan_kernel_config.template Init<typename Policy130::ScanPolicyT>();\n        }\n        else\n        {\n            scan_kernel_config.template Init<typename Policy100::ScanPolicyT>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration.\n     */\n    struct KernelConfig\n    {\n        int block_threads;\n        int items_per_thread;\n        int tile_items;\n\n        template <typename PolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Init()\n        {\n            block_threads       = PolicyT::BLOCK_THREADS;\n            items_per_thread    = PolicyT::ITEMS_PER_THREAD;\n            tile_items          = block_threads * items_per_thread;\n        }\n    };\n\n\n    //---------------------------------------------------------------------\n    // Dispatch entrypoints\n    //---------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine for computing a device-wide prefix scan using the\n     * specified kernel functions.\n     */\n    template <\n        typename            ScanInitKernelPtrT,     ///< Function type of cub::DeviceScanInitKernel\n        typename            ScanSweepKernelPtrT>    ///< Function type of cub::DeviceScanKernelPtrT\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*               d_temp_storage,         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&             temp_storage_bytes,     ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT      d_in,                   ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT     d_out,                  ///< [out] Pointer to the output sequence of data items\n        ScanOpT             scan_op,                ///< [in] Binary scan functor \n        InitValueT          init_value,             ///< [in] Initial value to seed the exclusive scan\n        OffsetT             num_items,              ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t        stream,                 ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                debug_synchronous,      ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        int                 /*ptx_version*/,        ///< [in] PTX version of dispatch kernels\n        ScanInitKernelPtrT  init_kernel,            ///< [in] Kernel function pointer to parameterization of cub::DeviceScanInitKernel\n        ScanSweepKernelPtrT scan_kernel,            ///< [in] Kernel function pointer to parameterization of cub::DeviceScanKernel\n        KernelConfig        scan_kernel_config)     ///< [in] Dispatch parameters that match the policy that \\p scan_kernel was compiled for\n    {\n\n#ifndef CUB_RUNTIME_ENABLED\n        (void)d_temp_storage;\n        (void)temp_storage_bytes;\n        (void)d_in;\n        (void)d_out;\n        (void)scan_op;\n        (void)init_value;\n        (void)num_items;\n        (void)stream;\n        (void)debug_synchronous;\n        (void)init_kernel;\n        (void)scan_kernel;\n        (void)scan_kernel_config;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported);\n\n#else\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Number of input tiles\n            int tile_size = scan_kernel_config.block_threads * scan_kernel_config.items_per_thread;\n            int num_tiles = (num_items + tile_size - 1) / tile_size;\n\n            // Specify temporary storage allocation requirements\n            size_t  allocation_sizes[1];\n            if (CubDebug(error = ScanTileStateT::AllocationSize(num_tiles, allocation_sizes[0]))) break;    // bytes needed for tile status descriptors\n\n            // Compute allocation pointers into the single storage blob (or compute the necessary size of the blob)\n            void* allocations[1];\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Return if empty problem\n            if (num_items == 0)\n                break;\n\n            // Construct the tile status interface\n            ScanTileStateT tile_state;\n            if (CubDebug(error = tile_state.Init(num_tiles, allocations[0], allocation_sizes[0]))) break;\n\n            // Log init_kernel configuration\n            int init_grid_size = (num_tiles + INIT_KERNEL_THREADS - 1) / INIT_KERNEL_THREADS;\n            if (debug_synchronous) _CubLog(\"Invoking init_kernel<<<%d, %d, 0, %lld>>>()\\n\", init_grid_size, INIT_KERNEL_THREADS, (long long) stream);\n\n            // Invoke init_kernel to initialize tile descriptors\n            init_kernel<<<init_grid_size, INIT_KERNEL_THREADS, 0, stream>>>(\n                tile_state,\n                num_tiles);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Get SM occupancy for scan_kernel\n            int scan_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                scan_sm_occupancy,            // out\n                scan_kernel,\n                scan_kernel_config.block_threads))) break;\n\n            // Get max x-dimension of grid\n            int max_dim_x;\n            if (CubDebug(error = cudaDeviceGetAttribute(&max_dim_x, cudaDevAttrMaxGridDimX, device_ordinal))) break;;\n\n            // Run grids in epochs (in case number of tiles exceeds max x-dimension\n            int scan_grid_size = CUB_MIN(num_tiles, max_dim_x);\n            for (int start_tile = 0; start_tile < num_tiles; start_tile += scan_grid_size)\n            {\n                // Log scan_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking %d scan_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                    start_tile, scan_grid_size, scan_kernel_config.block_threads, (long long) stream, scan_kernel_config.items_per_thread, scan_sm_occupancy);\n\n                // Invoke scan_kernel\n                scan_kernel<<<scan_grid_size, scan_kernel_config.block_threads, 0, stream>>>(\n                    d_in,\n                    d_out,\n                    tile_state,\n                    start_tile,\n                    scan_op,\n                    init_value,\n                    num_items);\n\n                // Check for failure to launch\n                if (CubDebug(error = cudaPeekAtLastError())) break;\n\n                // Sync the stream if specified to flush runtime errors\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n        }\n        while (0);\n\n        return error;\n\n#endif  // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*           d_temp_storage,         ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&         temp_storage_bytes,     ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT  d_in,                   ///< [in] Pointer to the input sequence of data items\n        OutputIteratorT d_out,                  ///< [out] Pointer to the output sequence of data items\n        ScanOpT         scan_op,                ///< [in] Binary scan functor \n        InitValueT      init_value,             ///< [in] Initial value to seed the exclusive scan\n        OffsetT         num_items,              ///< [in] Total number of input items (i.e., the length of \\p d_in)\n        cudaStream_t    stream,                 ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool            debug_synchronous)      ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n\n            // Get kernel kernel dispatch configurations\n            KernelConfig scan_kernel_config;\n            InitConfigs(ptx_version, scan_kernel_config);\n\n            // Dispatch\n            if (CubDebug(error = Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_in,\n                d_out,\n                scan_op,\n                init_value,\n                num_items,\n                stream,\n                debug_synchronous,\n                ptx_version,\n                DeviceScanInitKernel<ScanTileStateT>,\n                DeviceScanKernel<PtxAgentScanPolicy, InputIteratorT, OutputIteratorT, ScanTileStateT, ScanOpT, InitValueT, OffsetT>,\n                scan_kernel_config))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_select_if.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSelect provides device-wide, parallel operations for selecting items from sequences of data items residing within device-accessible memory.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"dispatch_scan.cuh\"\n#include \"../../agent/agent_select_if.cuh\"\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/******************************************************************************\n * Kernel entry points\n *****************************************************************************/\n\n/**\n * Select kernel entry point (multi-block)\n *\n * Performs functor-based selection if SelectOpT functor type != NullType\n * Otherwise performs flag-based selection if FlagsInputIterator's value type != NullType\n * Otherwise performs discontinuity selection (keep unique)\n */\ntemplate <\n    typename            AgentSelectIfPolicyT,       ///< Parameterized AgentSelectIfPolicyT tuning policy type\n    typename            InputIteratorT,             ///< Random-access input iterator type for reading input items\n    typename            FlagsInputIteratorT,        ///< Random-access input iterator type for reading selection flags (NullType* if a selection functor or discontinuity flagging is to be used for selection)\n    typename            SelectedOutputIteratorT,    ///< Random-access output iterator type for writing selected items\n    typename            NumSelectedIteratorT,       ///< Output iterator type for recording the number of items selected\n    typename            ScanTileStateT,             ///< Tile status interface type\n    typename            SelectOpT,                  ///< Selection operator type (NullType if selection flags or discontinuity flagging is to be used for selection)\n    typename            EqualityOpT,                ///< Equality operator type (NullType if selection functor or selection flags is to be used for selection)\n    typename            OffsetT,                    ///< Signed integer type for global offsets\n    bool                KEEP_REJECTS>               ///< Whether or not we push rejected items to the back of the output\n__launch_bounds__ (int(AgentSelectIfPolicyT::BLOCK_THREADS))\n__global__ void DeviceSelectSweepKernel(\n    InputIteratorT          d_in,                   ///< [in] Pointer to the input sequence of data items\n    FlagsInputIteratorT     d_flags,                ///< [in] Pointer to the input sequence of selection flags (if applicable)\n    SelectedOutputIteratorT d_selected_out,         ///< [out] Pointer to the output sequence of selected data items\n    NumSelectedIteratorT    d_num_selected_out,     ///< [out] Pointer to the total number of items selected (i.e., length of \\p d_selected_out)\n    ScanTileStateT          tile_status,            ///< [in] Tile status interface\n    SelectOpT               select_op,              ///< [in] Selection operator\n    EqualityOpT             equality_op,            ///< [in] Equality operator\n    OffsetT                 num_items,              ///< [in] Total number of input items (i.e., length of \\p d_in)\n    int                     num_tiles)              ///< [in] Total number of tiles for the entire problem\n{\n    // Thread block type for selecting data from input tiles\n    typedef AgentSelectIf<\n        AgentSelectIfPolicyT,\n        InputIteratorT,\n        FlagsInputIteratorT,\n        SelectedOutputIteratorT,\n        SelectOpT,\n        EqualityOpT,\n        OffsetT,\n        KEEP_REJECTS> AgentSelectIfT;\n\n    // Shared memory for AgentSelectIf\n    __shared__ typename AgentSelectIfT::TempStorage temp_storage;\n\n    // Process tiles\n    AgentSelectIfT(temp_storage, d_in, d_flags, d_selected_out, select_op, equality_op, num_items).ConsumeRange(\n        num_tiles,\n        tile_status,\n        d_num_selected_out);\n}\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceSelect\n */\ntemplate <\n    typename    InputIteratorT,                 ///< Random-access input iterator type for reading input items\n    typename    FlagsInputIteratorT,            ///< Random-access input iterator type for reading selection flags (NullType* if a selection functor or discontinuity flagging is to be used for selection)\n    typename    SelectedOutputIteratorT,        ///< Random-access output iterator type for writing selected items\n    typename    NumSelectedIteratorT,           ///< Output iterator type for recording the number of items selected\n    typename    SelectOpT,                      ///< Selection operator type (NullType if selection flags or discontinuity flagging is to be used for selection)\n    typename    EqualityOpT,                    ///< Equality operator type (NullType if selection functor or selection flags is to be used for selection)\n    typename    OffsetT,                        ///< Signed integer type for global offsets\n    bool        KEEP_REJECTS>                   ///< Whether or not we push rejected items to the back of the output\nstruct DispatchSelectIf\n{\n    /******************************************************************************\n     * Types and constants\n     ******************************************************************************/\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<SelectedOutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                                  // ... then the input iterator's value type,\n        typename std::iterator_traits<SelectedOutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // The flag value type\n    typedef typename std::iterator_traits<FlagsInputIteratorT>::value_type FlagT;\n\n    enum\n    {\n        INIT_KERNEL_THREADS = 128,\n    };\n\n    // Tile status descriptor interface type\n    typedef ScanTileState<OffsetT> ScanTileStateT;\n\n\n    /******************************************************************************\n     * Tuning policies\n     ******************************************************************************/\n\n    /// SM35\n    struct Policy350\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 10,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(OutputT)))),\n        };\n\n        typedef AgentSelectIfPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_DIRECT,\n                LOAD_LDG,\n                BLOCK_SCAN_WARP_SCANS>\n            SelectIfPolicyT;\n    };\n\n    /// SM30\n    struct Policy300\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 7,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(3, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(OutputT)))),\n        };\n\n        typedef AgentSelectIfPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            SelectIfPolicyT;\n    };\n\n    /// SM20\n    struct Policy200\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = (KEEP_REJECTS) ? 7 : 15,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(OutputT)))),\n        };\n\n        typedef AgentSelectIfPolicy<\n                128,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            SelectIfPolicyT;\n    };\n\n    /// SM13\n    struct Policy130\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 9,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(OutputT)))),\n        };\n\n        typedef AgentSelectIfPolicy<\n                64,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            SelectIfPolicyT;\n    };\n\n    /// SM10\n    struct Policy100\n    {\n        enum {\n            NOMINAL_4B_ITEMS_PER_THREAD = 9,\n            ITEMS_PER_THREAD            = CUB_MIN(NOMINAL_4B_ITEMS_PER_THREAD, CUB_MAX(1, (NOMINAL_4B_ITEMS_PER_THREAD * 4 / sizeof(OutputT)))),\n        };\n\n        typedef AgentSelectIfPolicy<\n                64,\n                ITEMS_PER_THREAD,\n                BLOCK_LOAD_WARP_TRANSPOSE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_RAKING>\n            SelectIfPolicyT;\n    };\n\n\n    /******************************************************************************\n     * Tuning policies of current PTX compiler pass\n     ******************************************************************************/\n\n#if (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 130)\n    typedef Policy130 PtxPolicy;\n\n#else\n    typedef Policy100 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxSelectIfPolicyT : PtxPolicy::SelectIfPolicyT {};\n\n\n    /******************************************************************************\n     * Utilities\n     ******************************************************************************/\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static void InitConfigs(\n        int             ptx_version,\n        KernelConfig    &select_if_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n        (void)ptx_version;\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        select_if_config.template Init<PtxSelectIfPolicyT>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 350)\n        {\n            select_if_config.template Init<typename Policy350::SelectIfPolicyT>();\n        }\n        else if (ptx_version >= 300)\n        {\n            select_if_config.template Init<typename Policy300::SelectIfPolicyT>();\n        }\n        else if (ptx_version >= 200)\n        {\n            select_if_config.template Init<typename Policy200::SelectIfPolicyT>();\n        }\n        else if (ptx_version >= 130)\n        {\n            select_if_config.template Init<typename Policy130::SelectIfPolicyT>();\n        }\n        else\n        {\n            select_if_config.template Init<typename Policy100::SelectIfPolicyT>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration.\n     */\n    struct KernelConfig\n    {\n        int block_threads;\n        int items_per_thread;\n        int tile_items;\n\n        template <typename PolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Init()\n        {\n            block_threads       = PolicyT::BLOCK_THREADS;\n            items_per_thread    = PolicyT::ITEMS_PER_THREAD;\n            tile_items          = block_threads * items_per_thread;\n        }\n    };\n\n\n    /******************************************************************************\n     * Dispatch entrypoints\n     ******************************************************************************/\n\n    /**\n     * Internal dispatch routine for computing a device-wide selection using the\n     * specified kernel functions.\n     */\n    template <\n        typename                    ScanInitKernelPtrT,             ///< Function type of cub::DeviceScanInitKernel\n        typename                    SelectIfKernelPtrT>             ///< Function type of cub::SelectIfKernelPtrT\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        FlagsInputIteratorT         d_flags,                        ///< [in] Pointer to the input sequence of selection flags (if applicable)\n        SelectedOutputIteratorT     d_selected_out,                 ///< [in] Pointer to the output sequence of selected data items\n        NumSelectedIteratorT        d_num_selected_out,             ///< [in] Pointer to the total number of items selected (i.e., length of \\p d_selected_out)\n        SelectOpT                   select_op,                      ///< [in] Selection operator\n        EqualityOpT                 equality_op,                    ///< [in] Equality operator\n        OffsetT                     num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream,                         ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous,              ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        int                         /*ptx_version*/,                ///< [in] PTX version of dispatch kernels\n        ScanInitKernelPtrT          scan_init_kernel,               ///< [in] Kernel function pointer to parameterization of cub::DeviceScanInitKernel\n        SelectIfKernelPtrT          select_if_kernel,               ///< [in] Kernel function pointer to parameterization of cub::DeviceSelectSweepKernel\n        KernelConfig                select_if_config)               ///< [in] Dispatch parameters that match the policy that \\p select_if_kernel was compiled for\n    {\n\n#ifndef CUB_RUNTIME_ENABLED\n        (void)d_temp_storage;\n        (void)temp_storage_bytes;\n        (void)d_in;\n        (void)d_flags;\n        (void)d_selected_out;\n        (void)d_num_selected_out;\n        (void)select_op;\n        (void)equality_op;\n        (void)num_items;\n        (void)stream;\n        (void)debug_synchronous;\n        (void)scan_init_kernel;\n        (void)select_if_kernel;\n        (void)select_if_config;\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported);\n\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Number of input tiles\n            int tile_size = select_if_config.block_threads * select_if_config.items_per_thread;\n            int num_tiles = (num_items + tile_size - 1) / tile_size;\n\n            // Specify temporary storage allocation requirements\n            size_t  allocation_sizes[1];\n            if (CubDebug(error = ScanTileStateT::AllocationSize(num_tiles, allocation_sizes[0]))) break;    // bytes needed for tile status descriptors\n\n            // Compute allocation pointers into the single storage blob (or compute the necessary size of the blob)\n            void* allocations[1];\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Construct the tile status interface\n            ScanTileStateT tile_status;\n            if (CubDebug(error = tile_status.Init(num_tiles, allocations[0], allocation_sizes[0]))) break;\n\n            // Log scan_init_kernel configuration\n            int init_grid_size = CUB_MAX(1, (num_tiles + INIT_KERNEL_THREADS - 1) / INIT_KERNEL_THREADS);\n            if (debug_synchronous) _CubLog(\"Invoking scan_init_kernel<<<%d, %d, 0, %lld>>>()\\n\", init_grid_size, INIT_KERNEL_THREADS, (long long) stream);\n\n            // Invoke scan_init_kernel to initialize tile descriptors\n            scan_init_kernel<<<init_grid_size, INIT_KERNEL_THREADS, 0, stream>>>(\n                tile_status,\n                num_tiles,\n                d_num_selected_out);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Return if empty problem\n            if (num_items == 0)\n                break;\n\n            // Get SM occupancy for select_if_kernel\n            int range_select_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                range_select_sm_occupancy,            // out\n                select_if_kernel,\n                select_if_config.block_threads))) break;\n\n            // Get max x-dimension of grid\n            int max_dim_x;\n            if (CubDebug(error = cudaDeviceGetAttribute(&max_dim_x, cudaDevAttrMaxGridDimX, device_ordinal))) break;;\n\n            // Get grid size for scanning tiles\n            dim3 scan_grid_size;\n            scan_grid_size.z = 1;\n            scan_grid_size.y = ((unsigned int) num_tiles + max_dim_x - 1) / max_dim_x;\n            scan_grid_size.x = CUB_MIN(num_tiles, max_dim_x);\n\n            // Log select_if_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking select_if_kernel<<<{%d,%d,%d}, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                scan_grid_size.x, scan_grid_size.y, scan_grid_size.z, select_if_config.block_threads, (long long) stream, select_if_config.items_per_thread, range_select_sm_occupancy);\n\n            // Invoke select_if_kernel\n            select_if_kernel<<<scan_grid_size, select_if_config.block_threads, 0, stream>>>(\n                d_in,\n                d_flags,\n                d_selected_out,\n                d_num_selected_out,\n                tile_status,\n                select_op,\n                equality_op,\n                num_items,\n                num_tiles);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n        }\n        while (0);\n\n        return error;\n\n#endif  // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                       d_temp_storage,                 ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                     temp_storage_bytes,             ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        InputIteratorT              d_in,                           ///< [in] Pointer to the input sequence of data items\n        FlagsInputIteratorT         d_flags,                        ///< [in] Pointer to the input sequence of selection flags (if applicable)\n        SelectedOutputIteratorT     d_selected_out,                 ///< [in] Pointer to the output sequence of selected data items\n        NumSelectedIteratorT        d_num_selected_out,             ///< [in] Pointer to the total number of items selected (i.e., length of \\p d_selected_out)\n        SelectOpT                   select_op,                      ///< [in] Selection operator\n        EqualityOpT                 equality_op,                    ///< [in] Equality operator\n        OffsetT                     num_items,                      ///< [in] Total number of input items (i.e., length of \\p d_in)\n        cudaStream_t                stream,                         ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                        debug_synchronous)              ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel kernel dispatch configurations\n            KernelConfig select_if_config;\n            InitConfigs(ptx_version, select_if_config);\n\n            // Dispatch\n            if (CubDebug(error = Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_in,\n                d_flags,\n                d_selected_out,\n                d_num_selected_out,\n                select_op,\n                equality_op,\n                num_items,\n                stream,\n                debug_synchronous,\n                ptx_version,\n                DeviceCompactInitKernel<ScanTileStateT, NumSelectedIteratorT>,\n                DeviceSelectSweepKernel<PtxSelectIfPolicyT, InputIteratorT, FlagsInputIteratorT, SelectedOutputIteratorT, NumSelectedIteratorT, ScanTileStateT, SelectOpT, EqualityOpT, OffsetT, KEEP_REJECTS>,\n                select_if_config))) break;\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/device/dispatch/dispatch_spmv_orig.cuh",
    "content": "\n/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::DeviceSpmv provides device-wide parallel operations for performing sparse-matrix * vector multiplication (SpMV).\n */\n\n#pragma once\n\n#include <stdio.h>\n#include <iterator>\n\n#include \"../../agent/single_pass_scan_operators.cuh\"\n#include \"../../agent/agent_segment_fixup.cuh\"\n#include \"../../agent/agent_spmv_orig.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_debug.cuh\"\n#include \"../../util_device.cuh\"\n#include \"../../thread/thread_search.cuh\"\n#include \"../../grid/grid_queue.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * SpMV kernel entry points\n *****************************************************************************/\n\n/**\n * Spmv search kernel. Identifies merge path starting coordinates for each tile.\n */\ntemplate <\n    typename    AgentSpmvPolicyT,           ///< Parameterized SpmvPolicy tuning policy type\n    typename    ValueT,                     ///< Matrix and vector value type\n    typename    OffsetT>                    ///< Signed integer type for sequence offsets\n__global__ void DeviceSpmv1ColKernel(\n    SpmvParams<ValueT, OffsetT> spmv_params)                ///< [in] SpMV input parameter bundle\n{\n    typedef CacheModifiedInputIterator<\n            AgentSpmvPolicyT::VECTOR_VALUES_LOAD_MODIFIER,\n            ValueT,\n            OffsetT>\n        VectorValueIteratorT;\n\n    VectorValueIteratorT wrapped_vector_x(spmv_params.d_vector_x);\n\n    int row_idx = (blockIdx.x * blockDim.x) + threadIdx.x;\n    if (row_idx < spmv_params.num_rows)\n    {\n        OffsetT     end_nonzero_idx = spmv_params.d_row_end_offsets[row_idx];\n        OffsetT     nonzero_idx = spmv_params.d_row_end_offsets[row_idx - 1];\n\n        ValueT value = 0.0;\n        if (end_nonzero_idx != nonzero_idx)\n        {\n            value = spmv_params.d_values[nonzero_idx] * wrapped_vector_x[spmv_params.d_column_indices[nonzero_idx]];\n        }\n\n        spmv_params.d_vector_y[row_idx] = value;\n    }\n}\n\n\n/**\n * Spmv search kernel. Identifies merge path starting coordinates for each tile.\n */\ntemplate <\n    typename    SpmvPolicyT,                    ///< Parameterized SpmvPolicy tuning policy type\n    typename    OffsetT,                        ///< Signed integer type for sequence offsets\n    typename    CoordinateT,                    ///< Merge path coordinate type\n    typename    SpmvParamsT>                    ///< SpmvParams type\n__global__ void DeviceSpmvSearchKernel(\n    int             num_merge_tiles,            ///< [in] Number of SpMV merge tiles (spmv grid size)\n    CoordinateT*    d_tile_coordinates,         ///< [out] Pointer to the temporary array of tile starting coordinates\n    SpmvParamsT     spmv_params)                ///< [in] SpMV input parameter bundle\n{\n    /// Constants\n    enum\n    {\n        BLOCK_THREADS           = SpmvPolicyT::BLOCK_THREADS,\n        ITEMS_PER_THREAD        = SpmvPolicyT::ITEMS_PER_THREAD,\n        TILE_ITEMS              = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    typedef CacheModifiedInputIterator<\n            SpmvPolicyT::ROW_OFFSETS_SEARCH_LOAD_MODIFIER,\n            OffsetT,\n            OffsetT>\n        RowOffsetsSearchIteratorT;\n\n    // Find the starting coordinate for all tiles (plus the end coordinate of the last one)\n    int tile_idx = (blockIdx.x * blockDim.x) + threadIdx.x;\n    if (tile_idx < num_merge_tiles + 1)\n    {\n        OffsetT                         diagonal = (tile_idx * TILE_ITEMS);\n        CoordinateT                     tile_coordinate;\n        CountingInputIterator<OffsetT>  nonzero_indices(0);\n\n        // Search the merge path\n        MergePathSearch(\n            diagonal,\n            RowOffsetsSearchIteratorT(spmv_params.d_row_end_offsets),\n            nonzero_indices,\n            spmv_params.num_rows,\n            spmv_params.num_nonzeros,\n            tile_coordinate);\n\n        // Output starting offset\n        d_tile_coordinates[tile_idx] = tile_coordinate;\n    }\n}\n\n\n/**\n * Spmv agent entry point\n */\ntemplate <\n    typename        SpmvPolicyT,                ///< Parameterized SpmvPolicy tuning policy type\n    typename        ScanTileStateT,             ///< Tile status interface type\n    typename        ValueT,                     ///< Matrix and vector value type\n    typename        OffsetT,                    ///< Signed integer type for sequence offsets\n    typename        CoordinateT,                ///< Merge path coordinate type\n    bool            HAS_ALPHA,                  ///< Whether the input parameter Alpha is 1\n    bool            HAS_BETA>                   ///< Whether the input parameter Beta is 0\n__launch_bounds__ (int(SpmvPolicyT::BLOCK_THREADS))\n__global__ void DeviceSpmvKernel(\n    SpmvParams<ValueT, OffsetT>     spmv_params,                ///< [in] SpMV input parameter bundle\n    CoordinateT*                    d_tile_coordinates,         ///< [in] Pointer to the temporary array of tile starting coordinates\n    KeyValuePair<OffsetT,ValueT>*   d_tile_carry_pairs,         ///< [out] Pointer to the temporary array carry-out dot product row-ids, one per block\n    int                             num_tiles,                  ///< [in] Number of merge tiles\n    ScanTileStateT                  tile_state,                 ///< [in] Tile status interface for fixup reduce-by-key kernel\n    int                             num_segment_fixup_tiles)    ///< [in] Number of reduce-by-key tiles (fixup grid size)\n{\n    // Spmv agent type specialization\n    typedef AgentSpmv<\n            SpmvPolicyT,\n            ValueT,\n            OffsetT,\n            HAS_ALPHA,\n            HAS_BETA>\n        AgentSpmvT;\n\n    // Shared memory for AgentSpmv\n    __shared__ typename AgentSpmvT::TempStorage temp_storage;\n\n    AgentSpmvT(temp_storage, spmv_params).ConsumeTile(\n        d_tile_coordinates,\n        d_tile_carry_pairs,\n        num_tiles);\n\n    // Initialize fixup tile status\n    tile_state.InitializeStatus(num_segment_fixup_tiles);\n\n}\n\n\n/**\n * Multi-block reduce-by-key sweep kernel entry point\n */\ntemplate <\n    typename    AgentSegmentFixupPolicyT,       ///< Parameterized AgentSegmentFixupPolicy tuning policy type\n    typename    PairsInputIteratorT,            ///< Random-access input iterator type for keys\n    typename    AggregatesOutputIteratorT,      ///< Random-access output iterator type for values\n    typename    OffsetT,                        ///< Signed integer type for global offsets\n    typename    ScanTileStateT>                 ///< Tile status interface type\n__launch_bounds__ (int(AgentSegmentFixupPolicyT::BLOCK_THREADS))\n__global__ void DeviceSegmentFixupKernel(\n    PairsInputIteratorT         d_pairs_in,         ///< [in] Pointer to the array carry-out dot product row-ids, one per spmv block\n    AggregatesOutputIteratorT   d_aggregates_out,   ///< [in,out] Output value aggregates\n    OffsetT                     num_items,          ///< [in] Total number of items to select from\n    int                         num_tiles,          ///< [in] Total number of tiles for the entire problem\n    ScanTileStateT              tile_state)         ///< [in] Tile status interface\n{\n    // Thread block type for reducing tiles of value segments\n    typedef AgentSegmentFixup<\n            AgentSegmentFixupPolicyT,\n            PairsInputIteratorT,\n            AggregatesOutputIteratorT,\n            cub::Equality,\n            cub::Sum,\n            OffsetT>\n        AgentSegmentFixupT;\n\n    // Shared memory for AgentSegmentFixup\n    __shared__ typename AgentSegmentFixupT::TempStorage temp_storage;\n\n    // Process tiles\n    AgentSegmentFixupT(temp_storage, d_pairs_in, d_aggregates_out, cub::Equality(), cub::Sum()).ConsumeRange(\n        num_items,\n        num_tiles,\n        tile_state);\n}\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceSpmv\n */\ntemplate <\n    typename    ValueT,                     ///< Matrix and vector value type\n    typename    OffsetT>                    ///< Signed integer type for global offsets\nstruct DispatchSpmv\n{\n    //---------------------------------------------------------------------\n    // Constants and Types\n    //---------------------------------------------------------------------\n\n    enum\n    {\n        INIT_KERNEL_THREADS = 128\n    };\n\n    // SpmvParams bundle type\n    typedef SpmvParams<ValueT, OffsetT> SpmvParamsT;\n\n    // 2D merge path coordinate type\n    typedef typename CubVector<OffsetT, 2>::Type CoordinateT;\n\n    // Tile status descriptor interface type\n    typedef ReduceByKeyScanTileState<ValueT, OffsetT> ScanTileStateT;\n\n    // Tuple type for scanning (pairs accumulated segment-value with segment-index)\n    typedef KeyValuePair<OffsetT, ValueT> KeyValuePairT;\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies\n    //---------------------------------------------------------------------\n\n    /// SM11\n    struct Policy110\n    {\n        typedef AgentSpmvPolicy<\n                128,\n                1,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                false,\n                BLOCK_SCAN_WARP_SCANS>\n            SpmvPolicyT;\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                4,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            SegmentFixupPolicyT;\n    };\n\n    /// SM20\n    struct Policy200 \n    {\n        typedef AgentSpmvPolicy<\n                96,\n                18,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                false,\n                BLOCK_SCAN_RAKING>\n            SpmvPolicyT;\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                4,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            SegmentFixupPolicyT;\n\n    };\n\n\n\n    /// SM30\n    struct Policy300 \n    {\n        typedef AgentSpmvPolicy<\n                96,\n                6,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                LOAD_DEFAULT,\n                false,\n                BLOCK_SCAN_WARP_SCANS>\n            SpmvPolicyT;\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                4,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_DEFAULT,\n                BLOCK_SCAN_WARP_SCANS>\n            SegmentFixupPolicyT;\n\n    };\n\n\n    /// SM35\n    struct Policy350\n    {\n        typedef AgentSpmvPolicy<\n                (sizeof(ValueT) > 4) ? 96 : 128,\n                (sizeof(ValueT) > 4) ? 4 : 7,\n                LOAD_LDG,\n                LOAD_CA,\n                LOAD_LDG,\n                LOAD_LDG,\n                LOAD_LDG,\n                (sizeof(ValueT) > 4) ? true : false,\n                BLOCK_SCAN_WARP_SCANS>\n            SpmvPolicyT;\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                3,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_LDG,\n                BLOCK_SCAN_WARP_SCANS>\n            SegmentFixupPolicyT;\n    };\n\n\n    /// SM37\n    struct Policy370\n    {\n\n        typedef AgentSpmvPolicy<\n                (sizeof(ValueT) > 4) ? 128 : 128,\n                (sizeof(ValueT) > 4) ? 9 : 14,\n                LOAD_LDG,\n                LOAD_CA,\n                LOAD_LDG,\n                LOAD_LDG,\n                LOAD_LDG,\n                false, \n                BLOCK_SCAN_WARP_SCANS>\n            SpmvPolicyT;\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                3,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_LDG,\n                BLOCK_SCAN_WARP_SCANS>\n            SegmentFixupPolicyT;\n    };\n\n    /// SM50\n    struct Policy500\n    {\n        typedef AgentSpmvPolicy<\n                (sizeof(ValueT) > 4) ? 64 : 128,\n                (sizeof(ValueT) > 4) ? 6 : 7,\n                LOAD_LDG,\n                LOAD_DEFAULT,\n                (sizeof(ValueT) > 4) ? LOAD_LDG : LOAD_DEFAULT,\n                (sizeof(ValueT) > 4) ? LOAD_LDG : LOAD_DEFAULT,\n                LOAD_LDG,\n                (sizeof(ValueT) > 4) ? true : false,\n                (sizeof(ValueT) > 4) ? BLOCK_SCAN_WARP_SCANS : BLOCK_SCAN_RAKING_MEMOIZE>\n            SpmvPolicyT;\n\n\n        typedef AgentSegmentFixupPolicy<\n                128,\n                3,\n                BLOCK_LOAD_VECTORIZE,\n                LOAD_LDG,\n                BLOCK_SCAN_RAKING_MEMOIZE>\n            SegmentFixupPolicyT;\n    };\n\n\n\n    //---------------------------------------------------------------------\n    // Tuning policies of current PTX compiler pass\n    //---------------------------------------------------------------------\n\n#if (CUB_PTX_ARCH >= 500)\n    typedef Policy500 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 370)\n    typedef Policy370 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#else\n    typedef Policy110 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxSpmvPolicyT : PtxPolicy::SpmvPolicyT {};\n    struct PtxSegmentFixupPolicy : PtxPolicy::SegmentFixupPolicyT {};\n\n\n    //---------------------------------------------------------------------\n    // Utilities\n    //---------------------------------------------------------------------\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <typename KernelConfig>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static void InitConfigs(\n        int             ptx_version,\n        KernelConfig    &spmv_config,\n        KernelConfig    &segment_fixup_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        spmv_config.template Init<PtxSpmvPolicyT>();\n        segment_fixup_config.template Init<PtxSegmentFixupPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 500)\n        {\n            spmv_config.template            Init<typename Policy500::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy500::SegmentFixupPolicyT>();\n        }\n        else if (ptx_version >= 370)\n        {\n            spmv_config.template            Init<typename Policy370::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy370::SegmentFixupPolicyT>();\n        }\n        else if (ptx_version >= 350)\n        {\n            spmv_config.template            Init<typename Policy350::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy350::SegmentFixupPolicyT>();\n        }\n        else if (ptx_version >= 300)\n        {\n            spmv_config.template            Init<typename Policy300::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy300::SegmentFixupPolicyT>();\n\n        }\n        else if (ptx_version >= 200)\n        {\n            spmv_config.template            Init<typename Policy200::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy200::SegmentFixupPolicyT>();\n        }\n        else\n        {\n            spmv_config.template            Init<typename Policy110::SpmvPolicyT>();\n            segment_fixup_config.template   Init<typename Policy110::SegmentFixupPolicyT>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * Kernel kernel dispatch configuration.\n     */\n    struct KernelConfig\n    {\n        int block_threads;\n        int items_per_thread;\n        int tile_items;\n\n        template <typename PolicyT>\n        CUB_RUNTIME_FUNCTION __forceinline__\n        void Init()\n        {\n            block_threads       = PolicyT::BLOCK_THREADS;\n            items_per_thread    = PolicyT::ITEMS_PER_THREAD;\n            tile_items          = block_threads * items_per_thread;\n        }\n    };\n\n\n    //---------------------------------------------------------------------\n    // Dispatch entrypoints\n    //---------------------------------------------------------------------\n\n    /**\n     * Internal dispatch routine for computing a device-wide reduction using the\n     * specified kernel functions.\n     *\n     * If the input is larger than a single tile, this method uses two-passes of\n     * kernel invocations.\n     */\n    template <\n        typename                Spmv1ColKernelT,                    ///< Function type of cub::DeviceSpmv1ColKernel\n        typename                SpmvSearchKernelT,                  ///< Function type of cub::AgentSpmvSearchKernel\n        typename                SpmvKernelT,                        ///< Function type of cub::AgentSpmvKernel\n        typename                SegmentFixupKernelT>                 ///< Function type of cub::DeviceSegmentFixupKernelT\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                   d_temp_storage,                     ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                 temp_storage_bytes,                 ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SpmvParamsT&            spmv_params,                        ///< SpMV input parameter bundle\n        cudaStream_t            stream,                             ///< [in] CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous,                  ///< [in] Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        Spmv1ColKernelT         spmv_1col_kernel,                   ///< [in] Kernel function pointer to parameterization of DeviceSpmv1ColKernel\n        SpmvSearchKernelT       spmv_search_kernel,                 ///< [in] Kernel function pointer to parameterization of AgentSpmvSearchKernel\n        SpmvKernelT             spmv_kernel,                        ///< [in] Kernel function pointer to parameterization of AgentSpmvKernel\n        SegmentFixupKernelT     segment_fixup_kernel,               ///< [in] Kernel function pointer to parameterization of cub::DeviceSegmentFixupKernel\n        KernelConfig            spmv_config,                        ///< [in] Dispatch parameters that match the policy that \\p spmv_kernel was compiled for\n        KernelConfig            segment_fixup_config)               ///< [in] Dispatch parameters that match the policy that \\p segment_fixup_kernel was compiled for\n    {\n#ifndef CUB_RUNTIME_ENABLED\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n\n#else\n        cudaError error = cudaSuccess;\n        do\n        {\n            if (spmv_params.num_cols == 1)\n            {\n                if (d_temp_storage == NULL)\n                {\n                    // Return if the caller is simply requesting the size of the storage allocation\n                    temp_storage_bytes = 1;\n                    break;\n                }\n\n                // Get search/init grid dims\n                int degen_col_kernel_block_size     = INIT_KERNEL_THREADS;\n                int degen_col_kernel_grid_size      = (spmv_params.num_rows + degen_col_kernel_block_size - 1) / degen_col_kernel_block_size;\n\n                if (debug_synchronous) _CubLog(\"Invoking spmv_1col_kernel<<<%d, %d, 0, %lld>>>()\\n\",\n                    degen_col_kernel_grid_size, degen_col_kernel_block_size, (long long) stream);\n\n                // Invoke spmv_search_kernel\n                spmv_1col_kernel<<<degen_col_kernel_grid_size, degen_col_kernel_block_size, 0, stream>>>(\n                    spmv_params);\n\n                // Check for failure to launch\n                if (CubDebug(error = cudaPeekAtLastError())) break;\n\n                // Sync the stream if specified to flush runtime errors\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n                break;\n            }\n\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Get max x-dimension of grid\n            int max_dim_x;\n            if (CubDebug(error = cudaDeviceGetAttribute(&max_dim_x, cudaDevAttrMaxGridDimX, device_ordinal))) break;;\n\n            // Total number of spmv work items\n            int num_merge_items = spmv_params.num_rows + spmv_params.num_nonzeros;\n\n            // Tile sizes of kernels\n            int merge_tile_size              = spmv_config.block_threads * spmv_config.items_per_thread;\n            int segment_fixup_tile_size     = segment_fixup_config.block_threads * segment_fixup_config.items_per_thread;\n\n            // Number of tiles for kernels\n            unsigned int num_merge_tiles            = (num_merge_items + merge_tile_size - 1) / merge_tile_size;\n            unsigned int num_segment_fixup_tiles    = (num_merge_tiles + segment_fixup_tile_size - 1) / segment_fixup_tile_size;\n\n            // Get SM occupancy for kernels\n            int spmv_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                spmv_sm_occupancy,\n                spmv_kernel,\n                spmv_config.block_threads))) break;\n\n            int segment_fixup_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                segment_fixup_sm_occupancy,\n                segment_fixup_kernel,\n                segment_fixup_config.block_threads))) break;\n\n            // Get grid dimensions\n            dim3 spmv_grid_size(\n                CUB_MIN(num_merge_tiles, max_dim_x),\n                (num_merge_tiles + max_dim_x - 1) / max_dim_x,\n                1);\n\n            dim3 segment_fixup_grid_size(\n                CUB_MIN(num_segment_fixup_tiles, max_dim_x),\n                (num_segment_fixup_tiles + max_dim_x - 1) / max_dim_x,\n                1);\n\n            // Get the temporary storage allocation requirements\n            size_t allocation_sizes[3];\n            if (CubDebug(error = ScanTileStateT::AllocationSize(num_segment_fixup_tiles, allocation_sizes[0]))) break;    // bytes needed for reduce-by-key tile status descriptors\n            allocation_sizes[1] = num_merge_tiles * sizeof(KeyValuePairT);       // bytes needed for block carry-out pairs\n            allocation_sizes[2] = (num_merge_tiles + 1) * sizeof(CoordinateT);   // bytes needed for tile starting coordinates\n\n            // Alias the temporary allocations from the single storage blob (or compute the necessary size of the blob)\n            void* allocations[3];\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                break;\n            }\n\n            // Construct the tile status interface\n            ScanTileStateT tile_state;\n            if (CubDebug(error = tile_state.Init(num_segment_fixup_tiles, allocations[0], allocation_sizes[0]))) break;\n\n            // Alias the other allocations\n            KeyValuePairT*  d_tile_carry_pairs      = (KeyValuePairT*) allocations[1];  // Agent carry-out pairs\n            CoordinateT*    d_tile_coordinates      = (CoordinateT*) allocations[2];    // Agent starting coordinates\n\n            // Get search/init grid dims\n            int search_block_size   = INIT_KERNEL_THREADS;\n            int search_grid_size    = (num_merge_tiles + 1 + search_block_size - 1) / search_block_size;\n\n#if (CUB_PTX_ARCH == 0)\n            // Init textures\n            if (CubDebug(error = spmv_params.t_vector_x.BindTexture(spmv_params.d_vector_x))) break;\n#endif\n\n            if (search_grid_size < sm_count)\n//            if (num_merge_tiles < spmv_sm_occupancy * sm_count)\n            {\n                // Not enough spmv tiles to saturate the device: have spmv blocks search their own staring coords\n                d_tile_coordinates = NULL;\n            }\n            else\n            {\n                // Use separate search kernel if we have enough spmv tiles to saturate the device\n\n                // Log spmv_search_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking spmv_search_kernel<<<%d, %d, 0, %lld>>>()\\n\",\n                    search_grid_size, search_block_size, (long long) stream);\n\n                // Invoke spmv_search_kernel\n                spmv_search_kernel<<<search_grid_size, search_block_size, 0, stream>>>(\n                    num_merge_tiles,\n                    d_tile_coordinates,\n                    spmv_params);\n\n                // Check for failure to launch\n                if (CubDebug(error = cudaPeekAtLastError())) break;\n\n                // Sync the stream if specified to flush runtime errors\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n\n            // Log spmv_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking spmv_kernel<<<{%d,%d,%d}, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                spmv_grid_size.x, spmv_grid_size.y, spmv_grid_size.z, spmv_config.block_threads, (long long) stream, spmv_config.items_per_thread, spmv_sm_occupancy);\n\n            // Invoke spmv_kernel\n            spmv_kernel<<<spmv_grid_size, spmv_config.block_threads, 0, stream>>>(\n                spmv_params,\n                d_tile_coordinates,\n                d_tile_carry_pairs,\n                num_merge_tiles,\n                tile_state,\n                num_segment_fixup_tiles);\n\n            // Check for failure to launch\n            if (CubDebug(error = cudaPeekAtLastError())) break;\n\n            // Sync the stream if specified to flush runtime errors\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n\n            // Run reduce-by-key fixup if necessary\n            if (num_merge_tiles > 1)\n            {\n                // Log segment_fixup_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking segment_fixup_kernel<<<{%d,%d,%d}, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                    segment_fixup_grid_size.x, segment_fixup_grid_size.y, segment_fixup_grid_size.z, segment_fixup_config.block_threads, (long long) stream, segment_fixup_config.items_per_thread, segment_fixup_sm_occupancy);\n\n                // Invoke segment_fixup_kernel\n                segment_fixup_kernel<<<segment_fixup_grid_size, segment_fixup_config.block_threads, 0, stream>>>(\n                    d_tile_carry_pairs,\n                    spmv_params.d_vector_y,\n                    num_merge_tiles,\n                    num_segment_fixup_tiles,\n                    tile_state);\n\n                // Check for failure to launch\n                if (CubDebug(error = cudaPeekAtLastError())) break;\n\n                // Sync the stream if specified to flush runtime errors\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n\n#if (CUB_PTX_ARCH == 0)\n            // Free textures\n            if (CubDebug(error = spmv_params.t_vector_x.UnbindTexture())) break;\n#endif\n        }\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine for computing a device-wide reduction\n     */\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Dispatch(\n        void*                   d_temp_storage,                     ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n        size_t&                 temp_storage_bytes,                 ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation\n        SpmvParamsT&            spmv_params,                        ///< SpMV input parameter bundle\n        cudaStream_t            stream                  = 0,        ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous       = false)    ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  May cause significant slowdown.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel kernel dispatch configurations\n            KernelConfig spmv_config, segment_fixup_config;\n            InitConfigs(ptx_version, spmv_config, segment_fixup_config);\n\n            if (CubDebug(error = Dispatch(\n                d_temp_storage, temp_storage_bytes, spmv_params, stream, debug_synchronous,\n                DeviceSpmv1ColKernel<PtxSpmvPolicyT, ValueT, OffsetT>,\n                DeviceSpmvSearchKernel<PtxSpmvPolicyT, OffsetT, CoordinateT, SpmvParamsT>,\n                DeviceSpmvKernel<PtxSpmvPolicyT, ScanTileStateT, ValueT, OffsetT, CoordinateT, false, false>,\n                DeviceSegmentFixupKernel<PtxSegmentFixupPolicy, KeyValuePairT*, ValueT*, OffsetT, ScanTileStateT>,\n                spmv_config, segment_fixup_config))) break;\n\n/*\n            // Dispatch\n            if (spmv_params.beta == 0.0)\n            {\n                if (spmv_params.alpha == 1.0)\n                {\n                    // Dispatch y = A*x\n                    if (CubDebug(error = Dispatch(\n                        d_temp_storage, temp_storage_bytes, spmv_params, stream, debug_synchronous,\n                        DeviceSpmv1ColKernel<PtxSpmvPolicyT, ValueT, OffsetT>,\n                        DeviceSpmvSearchKernel<PtxSpmvPolicyT, OffsetT, CoordinateT, SpmvParamsT>,\n                        DeviceSpmvKernel<PtxSpmvPolicyT, ScanTileStateT, ValueT, OffsetT, CoordinateT, false, false>,\n                        DeviceSegmentFixupKernel<PtxSegmentFixupPolicy, KeyValuePairT*, ValueT*, OffsetT, ScanTileStateT>,\n                        spmv_config, segment_fixup_config))) break;\n                }\n                else\n                {\n                    // Dispatch y = alpha*A*x\n                    if (CubDebug(error = Dispatch(\n                        d_temp_storage, temp_storage_bytes, spmv_params, stream, debug_synchronous,\n                        DeviceSpmvSearchKernel<PtxSpmvPolicyT, ScanTileStateT, OffsetT, CoordinateT, SpmvParamsT>,\n                        DeviceSpmvKernel<PtxSpmvPolicyT, ValueT, OffsetT, CoordinateT, true, false>,\n                        DeviceSegmentFixupKernel<PtxSegmentFixupPolicy, KeyValuePairT*, ValueT*, OffsetT, ScanTileStateT>,\n                        spmv_config, segment_fixup_config))) break;\n                }\n            }\n            else\n            {\n                if (spmv_params.alpha == 1.0)\n                {\n                    // Dispatch y = A*x + beta*y\n                    if (CubDebug(error = Dispatch(\n                        d_temp_storage, temp_storage_bytes, spmv_params, stream, debug_synchronous,\n                        DeviceSpmvSearchKernel<PtxSpmvPolicyT, ScanTileStateT, OffsetT, CoordinateT, SpmvParamsT>,\n                        DeviceSpmvKernel<PtxSpmvPolicyT, ValueT, OffsetT, CoordinateT, false, true>,\n                        DeviceSegmentFixupKernel<PtxSegmentFixupPolicy, KeyValuePairT*, ValueT*, OffsetT, ScanTileStateT>,\n                        spmv_config, segment_fixup_config))) break;\n                }\n                else\n                {\n                    // Dispatch y = alpha*A*x + beta*y\n                    if (CubDebug(error = Dispatch(\n                        d_temp_storage, temp_storage_bytes, spmv_params, stream, debug_synchronous,\n                        DeviceSpmvSearchKernel<PtxSpmvPolicyT, ScanTileStateT, OffsetT, CoordinateT, SpmvParamsT>,\n                        DeviceSpmvKernel<PtxSpmvPolicyT, ValueT, OffsetT, CoordinateT, true, true>,\n                        DeviceSegmentFixupKernel<PtxSegmentFixupPolicy, KeyValuePairT*, ValueT*, OffsetT, ScanTileStateT>,\n                        spmv_config, segment_fixup_config))) break;\n                }\n            }\n*/\n        }\n        while (0);\n\n        return error;\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/grid/grid_barrier.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::GridBarrier implements a software global barrier among thread blocks within a CUDA grid\n */\n\n#pragma once\n\n#include \"../util_debug.cuh\"\n#include \"../util_namespace.cuh\"\n#include \"../thread/thread_load.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup GridModule\n * @{\n */\n\n\n/**\n * \\brief GridBarrier implements a software global barrier among thread blocks within a CUDA grid\n */\nclass GridBarrier\n{\nprotected :\n\n    typedef unsigned int SyncFlag;\n\n    // Counters in global device memory\n    SyncFlag* d_sync;\n\npublic:\n\n    /**\n     * Constructor\n     */\n    GridBarrier() : d_sync(NULL) {}\n\n\n    /**\n     * Synchronize\n     */\n    __device__ __forceinline__ void Sync() const\n    {\n        volatile SyncFlag *d_vol_sync = d_sync;\n\n        // Threadfence and syncthreads to make sure global writes are visible before\n        // thread-0 reports in with its sync counter\n        __threadfence();\n        CTA_SYNC();\n\n        if (blockIdx.x == 0)\n        {\n            // Report in ourselves\n            if (threadIdx.x == 0)\n            {\n                d_vol_sync[blockIdx.x] = 1;\n            }\n\n            CTA_SYNC();\n\n            // Wait for everyone else to report in\n            for (int peer_block = threadIdx.x; peer_block < gridDim.x; peer_block += blockDim.x)\n            {\n                while (ThreadLoad<LOAD_CG>(d_sync + peer_block) == 0)\n                {\n                    __threadfence_block();\n                }\n            }\n\n            CTA_SYNC();\n\n            // Let everyone know it's safe to proceed\n            for (int peer_block = threadIdx.x; peer_block < gridDim.x; peer_block += blockDim.x)\n            {\n                d_vol_sync[peer_block] = 0;\n            }\n        }\n        else\n        {\n            if (threadIdx.x == 0)\n            {\n                // Report in\n                d_vol_sync[blockIdx.x] = 1;\n\n                // Wait for acknowledgment\n                while (ThreadLoad<LOAD_CG>(d_sync + blockIdx.x) == 1)\n                {\n                    __threadfence_block();\n                }\n            }\n\n            CTA_SYNC();\n        }\n    }\n};\n\n\n/**\n * \\brief GridBarrierLifetime extends GridBarrier to provide lifetime management of the temporary device storage needed for cooperation.\n *\n * Uses RAII for lifetime, i.e., device resources are reclaimed when\n * the destructor is called.\n */\nclass GridBarrierLifetime : public GridBarrier\n{\nprotected:\n\n    // Number of bytes backed by d_sync\n    size_t sync_bytes;\n\npublic:\n\n    /**\n     * Constructor\n     */\n    GridBarrierLifetime() : GridBarrier(), sync_bytes(0) {}\n\n\n    /**\n     * DeviceFrees and resets the progress counters\n     */\n    cudaError_t HostReset()\n    {\n        cudaError_t retval = cudaSuccess;\n        if (d_sync)\n        {\n            CubDebug(retval = cudaFree(d_sync));\n            d_sync = NULL;\n        }\n        sync_bytes = 0;\n        return retval;\n    }\n\n\n    /**\n     * Destructor\n     */\n    virtual ~GridBarrierLifetime()\n    {\n        HostReset();\n    }\n\n\n    /**\n     * Sets up the progress counters for the next kernel launch (lazily\n     * allocating and initializing them if necessary)\n     */\n    cudaError_t Setup(int sweep_grid_size)\n    {\n        cudaError_t retval = cudaSuccess;\n        do {\n            size_t new_sync_bytes = sweep_grid_size * sizeof(SyncFlag);\n            if (new_sync_bytes > sync_bytes)\n            {\n                if (d_sync)\n                {\n                    if (CubDebug(retval = cudaFree(d_sync))) break;\n                }\n\n                sync_bytes = new_sync_bytes;\n\n                // Allocate and initialize to zero\n                if (CubDebug(retval = cudaMalloc((void**) &d_sync, sync_bytes))) break;\n                if (CubDebug(retval = cudaMemset(d_sync, 0, new_sync_bytes))) break;\n            }\n        } while (0);\n\n        return retval;\n    }\n};\n\n\n/** @} */       // end group GridModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/grid/grid_even_share.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::GridEvenShare is a descriptor utility for distributing input among CUDA thread blocks in an \"even-share\" fashion.  Each thread block gets roughly the same number of fixed-size work units (grains).\n */\n\n\n#pragma once\n\n#include \"../util_namespace.cuh\"\n#include \"../util_macro.cuh\"\n#include \"grid_mapping.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup GridModule\n * @{\n */\n\n\n/**\n * \\brief GridEvenShare is a descriptor utility for distributing input among\n * CUDA thread blocks in an \"even-share\" fashion.  Each thread block gets roughly\n * the same number of input tiles.\n *\n * \\par Overview\n * Each thread block is assigned a consecutive sequence of input tiles.  To help\n * preserve alignment and eliminate the overhead of guarded loads for all but the\n * last thread block, to GridEvenShare assigns one of three different amounts of\n * work to a given thread block: \"big\", \"normal\", or \"last\".  The \"big\" workloads\n * are one scheduling grain larger than \"normal\".  The \"last\" work unit for the\n * last thread block may be partially-full if the input is not an even multiple of\n * the scheduling grain size.\n *\n * \\par\n * Before invoking a child grid, a parent thread will typically construct an\n * instance of GridEvenShare.  The instance can be passed to child thread blocks\n * which can initialize their per-thread block offsets using \\p BlockInit().\n */\ntemplate <typename OffsetT>\nstruct GridEvenShare\n{\nprivate:\n\n    OffsetT     total_tiles;\n    int         big_shares;\n    OffsetT     big_share_items;\n    OffsetT     normal_share_items;\n    OffsetT     normal_base_offset;\n\npublic:\n\n    /// Total number of input items\n    OffsetT     num_items;\n\n    /// Grid size in thread blocks\n    int         grid_size;\n\n    /// OffsetT into input marking the beginning of the owning thread block's segment of input tiles\n    OffsetT     block_offset;\n\n    /// OffsetT into input of marking the end (one-past) of the owning thread block's segment of input tiles\n    OffsetT     block_end;\n\n    /// Stride between input tiles\n    OffsetT     block_stride;\n\n\n    /**\n     * \\brief Constructor.\n     */\n    __host__ __device__ __forceinline__ GridEvenShare() :\n        total_tiles(0),\n        big_shares(0),\n        big_share_items(0),\n        normal_share_items(0),\n        normal_base_offset(0),\n        num_items(0),\n        grid_size(0),\n        block_offset(0),\n        block_end(0),\n        block_stride(0)\n    {}\n\n\n    /**\n     * \\brief Dispatch initializer. To be called prior prior to kernel launch.\n     */\n    __host__ __device__ __forceinline__ void DispatchInit(\n        OffsetT num_items,          ///< Total number of input items\n        int     max_grid_size,      ///< Maximum grid size allowable (actual grid size may be less if not warranted by the the number of input items)\n        int     tile_items)         ///< Number of data items per input tile\n    {\n        this->block_offset          = num_items;    // Initialize past-the-end\n        this->block_end             = num_items;    // Initialize past-the-end\n        this->num_items             = num_items;\n        this->total_tiles           = (num_items + tile_items - 1) / tile_items;\n        this->grid_size             = CUB_MIN(total_tiles, max_grid_size);\n        OffsetT avg_tiles_per_block = total_tiles / grid_size;\n        this->big_shares            = total_tiles - (avg_tiles_per_block * grid_size);        // leftover grains go to big blocks\n        this->normal_share_items    = avg_tiles_per_block * tile_items;\n        this->normal_base_offset    = big_shares * tile_items;\n        this->big_share_items       = normal_share_items + tile_items;\n    }\n\n\n    /**\n     * \\brief Initializes ranges for the specified thread block index.  Specialized\n     * for a \"raking\" access pattern in which each thread block is assigned a\n     * consecutive sequence of input tiles.\n     */\n    template <int TILE_ITEMS>\n    __device__ __forceinline__ void BlockInit(\n        int block_id,\n        Int2Type<GRID_MAPPING_RAKE> /*strategy_tag*/)\n    {\n        block_stride = TILE_ITEMS;\n        if (block_id < big_shares)\n        {\n            // This thread block gets a big share of grains (avg_tiles_per_block + 1)\n            block_offset = (block_id * big_share_items);\n            block_end = block_offset + big_share_items;\n        }\n        else if (block_id < total_tiles)\n        {\n            // This thread block gets a normal share of grains (avg_tiles_per_block)\n            block_offset = normal_base_offset + (block_id * normal_share_items);\n            block_end = CUB_MIN(num_items, block_offset + normal_share_items);\n        }\n        // Else default past-the-end\n    }\n\n\n    /**\n     * \\brief Block-initialization, specialized for a \"raking\" access\n     * pattern in which each thread block is assigned a consecutive sequence\n     * of input tiles.\n     */\n    template <int TILE_ITEMS>\n    __device__ __forceinline__ void BlockInit(\n        int block_id,\n        Int2Type<GRID_MAPPING_STRIP_MINE> /*strategy_tag*/)\n    {\n        block_stride = grid_size * TILE_ITEMS;\n        block_offset = (block_id * TILE_ITEMS);\n        block_end = num_items;\n    }\n\n\n    /**\n     * \\brief Block-initialization, specialized for \"strip mining\" access\n     * pattern in which the input tiles assigned to each thread block are\n     * separated by a stride equal to the the extent of the grid.\n     */\n    template <\n        int TILE_ITEMS,\n        GridMappingStrategy STRATEGY>\n    __device__ __forceinline__ void BlockInit()\n    {\n        BlockInit<TILE_ITEMS>(blockIdx.x, Int2Type<STRATEGY>());\n    }\n\n\n    /**\n     * \\brief Block-initialization, specialized for a \"raking\" access\n     * pattern in which each thread block is assigned a consecutive sequence\n     * of input tiles.\n     */\n    template <int TILE_ITEMS>\n    __device__ __forceinline__ void BlockInit(\n        OffsetT block_offset,                       ///< [in] Threadblock begin offset (inclusive)\n        OffsetT block_end)                          ///< [in] Threadblock end offset (exclusive)\n    {\n        this->block_offset = block_offset;\n        this->block_end = block_end;\n        this->block_stride = TILE_ITEMS;\n    }\n\n\n};\n\n\n\n\n\n/** @} */       // end group GridModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/grid/grid_mapping.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::GridMappingStrategy enumerates alternative strategies for mapping constant-sized tiles of device-wide data onto a grid of CUDA thread blocks.\n */\n\n#pragma once\n\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup GridModule\n * @{\n */\n\n\n/******************************************************************************\n * Mapping policies\n *****************************************************************************/\n\n\n/**\n * \\brief cub::GridMappingStrategy enumerates alternative strategies for mapping constant-sized tiles of device-wide data onto a grid of CUDA thread blocks.\n */\nenum GridMappingStrategy\n{\n    /**\n     * \\brief An a \"raking\" access pattern in which each thread block is\n     * assigned a consecutive sequence of input tiles\n     *\n     * \\par Overview\n     * The input is evenly partitioned into \\p p segments, where \\p p is\n     * constant and corresponds loosely to the number of thread blocks that may\n     * actively reside on the target device. Each segment is comprised of\n     * consecutive tiles, where a tile is a small, constant-sized unit of input\n     * to be processed to completion before the thread block terminates or\n     * obtains more work.  The kernel invokes \\p p thread blocks, each\n     * of which iteratively consumes a segment of <em>n</em>/<em>p</em> elements\n     * in tile-size increments.\n     */\n    GRID_MAPPING_RAKE,\n\n    /**\n     * \\brief An a \"strip mining\" access pattern in which the input tiles assigned\n     * to each thread block are separated by a stride equal to the the extent of\n     * the grid.\n     *\n     * \\par Overview\n     * The input is evenly partitioned into \\p p sets, where \\p p is\n     * constant and corresponds loosely to the number of thread blocks that may\n     * actively reside on the target device. Each set is comprised of\n     * data tiles separated by stride \\p tiles, where a tile is a small,\n     * constant-sized unit of input to be processed to completion before the\n     * thread block terminates or obtains more work.  The kernel invokes \\p p\n     * thread blocks, each of which iteratively consumes a segment of\n     * <em>n</em>/<em>p</em> elements in tile-size increments.\n     */\n    GRID_MAPPING_STRIP_MINE,\n\n    /**\n     * \\brief A dynamic \"queue-based\" strategy for assigning input tiles to thread blocks.\n     *\n     * \\par Overview\n     * The input is treated as a queue to be dynamically consumed by a grid of\n     * thread blocks.  Work is atomically dequeued in tiles, where a tile is a\n     * unit of input to be processed to completion before the thread block\n     * terminates or obtains more work.  The grid size \\p p is constant,\n     * loosely corresponding to the number of thread blocks that may actively\n     * reside on the target device.\n     */\n    GRID_MAPPING_DYNAMIC,\n};\n\n\n/** @} */       // end group GridModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/grid/grid_queue.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::GridQueue is a descriptor utility for dynamic queue management.\n */\n\n#pragma once\n\n#include \"../util_namespace.cuh\"\n#include \"../util_debug.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup GridModule\n * @{\n */\n\n\n/**\n * \\brief GridQueue is a descriptor utility for dynamic queue management.\n *\n * \\par Overview\n * GridQueue descriptors provides abstractions for \"filling\" or\n * \"draining\" globally-shared vectors.\n *\n * \\par\n * A \"filling\" GridQueue works by atomically-adding to a zero-initialized counter,\n * returning a unique offset for the calling thread to write its items.\n * The GridQueue maintains the total \"fill-size\".  The fill counter must be reset\n * using GridQueue::ResetFill by the host or kernel instance prior to the kernel instance that\n * will be filling.\n *\n * \\par\n * Similarly, a \"draining\" GridQueue works by works by atomically-incrementing a\n * zero-initialized counter, returning a unique offset for the calling thread to\n * read its items. Threads can safely drain until the array's logical fill-size is\n * exceeded.  The drain counter must be reset using GridQueue::ResetDrain or\n * GridQueue::FillAndResetDrain by the host or kernel instance prior to the kernel instance that\n * will be filling.  (For dynamic work distribution of existing data, the corresponding fill-size\n * is simply the number of elements in the array.)\n *\n * \\par\n * Iterative work management can be implemented simply with a pair of flip-flopping\n * work buffers, each with an associated set of fill and drain GridQueue descriptors.\n *\n * \\tparam OffsetT Signed integer type for global offsets\n */\ntemplate <typename OffsetT>\nclass GridQueue\n{\nprivate:\n\n    /// Counter indices\n    enum\n    {\n        FILL    = 0,\n        DRAIN   = 1,\n    };\n\n    /// Pair of counters\n    OffsetT *d_counters;\n\npublic:\n\n    /// Returns the device allocation size in bytes needed to construct a GridQueue instance\n    __host__ __device__ __forceinline__\n    static size_t AllocationSize()\n    {\n        return sizeof(OffsetT) * 2;\n    }\n\n\n    /// Constructs an invalid GridQueue descriptor\n    __host__ __device__ __forceinline__ GridQueue()\n    :\n        d_counters(NULL)\n    {}\n\n\n    /// Constructs a GridQueue descriptor around the device storage allocation\n    __host__ __device__ __forceinline__ GridQueue(\n        void *d_storage)                    ///< Device allocation to back the GridQueue.  Must be at least as big as <tt>AllocationSize()</tt>.\n    :\n        d_counters((OffsetT*) d_storage)\n    {}\n\n\n    /// This operation sets the fill-size and resets the drain counter, preparing the GridQueue for draining in the next kernel instance.  To be called by the host or by a kernel prior to that which will be draining.\n    __host__ __device__ __forceinline__ cudaError_t FillAndResetDrain(\n        OffsetT fill_size,\n        cudaStream_t stream = 0)\n    {\n#if (CUB_PTX_ARCH > 0)\n        (void)stream;\n        d_counters[FILL] = fill_size;\n        d_counters[DRAIN] = 0;\n        return cudaSuccess;\n#else\n        OffsetT counters[2];\n        counters[FILL] = fill_size;\n        counters[DRAIN] = 0;\n        return CubDebug(cudaMemcpyAsync(d_counters, counters, sizeof(OffsetT) * 2, cudaMemcpyHostToDevice, stream));\n#endif\n    }\n\n\n    /// This operation resets the drain so that it may advance to meet the existing fill-size.  To be called by the host or by a kernel prior to that which will be draining.\n    __host__ __device__ __forceinline__ cudaError_t ResetDrain(cudaStream_t stream = 0)\n    {\n#if (CUB_PTX_ARCH > 0)\n        (void)stream;\n        d_counters[DRAIN] = 0;\n        return cudaSuccess;\n#else\n        return CubDebug(cudaMemsetAsync(d_counters + DRAIN, 0, sizeof(OffsetT), stream));\n#endif\n    }\n\n\n    /// This operation resets the fill counter.  To be called by the host or by a kernel prior to that which will be filling.\n    __host__ __device__ __forceinline__ cudaError_t ResetFill(cudaStream_t stream = 0)\n    {\n#if (CUB_PTX_ARCH > 0)\n        (void)stream;\n        d_counters[FILL] = 0;\n        return cudaSuccess;\n#else\n        return CubDebug(cudaMemsetAsync(d_counters + FILL, 0, sizeof(OffsetT), stream));\n#endif\n    }\n\n\n    /// Returns the fill-size established by the parent or by the previous kernel.\n    __host__ __device__ __forceinline__ cudaError_t FillSize(\n        OffsetT &fill_size,\n        cudaStream_t stream = 0)\n    {\n#if (CUB_PTX_ARCH > 0)\n        (void)stream;\n        fill_size = d_counters[FILL];\n        return cudaSuccess;\n#else\n        return CubDebug(cudaMemcpyAsync(&fill_size, d_counters + FILL, sizeof(OffsetT), cudaMemcpyDeviceToHost, stream));\n#endif\n    }\n\n\n    /// Drain \\p num_items from the queue.  Returns offset from which to read items.  To be called from CUDA kernel.\n    __device__ __forceinline__ OffsetT Drain(OffsetT num_items)\n    {\n        return atomicAdd(d_counters + DRAIN, num_items);\n    }\n\n\n    /// Fill \\p num_items into the queue.  Returns offset from which to write items.    To be called from CUDA kernel.\n    __device__ __forceinline__ OffsetT Fill(OffsetT num_items)\n    {\n        return atomicAdd(d_counters + FILL, num_items);\n    }\n};\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/**\n * Reset grid queue (call with 1 block of 1 thread)\n */\ntemplate <typename OffsetT>\n__global__ void FillAndResetDrainKernel(\n    GridQueue<OffsetT>   grid_queue,\n    OffsetT              num_items)\n{\n    grid_queue.FillAndResetDrain(num_items);\n}\n\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/** @} */       // end group GridModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n\n"
  },
  {
    "path": "external/cub/cub/host/mutex.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Simple portable mutex\n */\n\n\n#pragma once\n\n#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)\n    #include <mutex>\n#else\n    #if defined(_WIN32) || defined(_WIN64)\n        #include <intrin.h>\n\n        #define WIN32_LEAN_AND_MEAN\n        #define NOMINMAX\n        #include <windows.h>\n        #undef WIN32_LEAN_AND_MEAN\n        #undef NOMINMAX\n\n        /**\n         * Compiler read/write barrier\n         */\n        #pragma intrinsic(_ReadWriteBarrier)\n\n    #endif\n#endif\n\n#include \"../util_namespace.cuh\"\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * Simple portable mutex\n *   - Wraps std::mutex when compiled with C++11 or newer (supported on all platforms)\n *   - Uses GNU/Windows spinlock mechanisms for pre C++11 (supported on x86/x64 when compiled with cl.exe or g++)\n */\nstruct Mutex\n{\n#if (__cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1800)\n\n    std::mutex mtx;\n\n    void Lock()\n    {\n        mtx.lock();\n    }\n\n    void Unlock()\n    {\n        mtx.unlock();\n    }\n\n    void TryLock()\n    {\n        mtx.try_lock();\n    }\n\n#else       //__cplusplus > 199711L\n\n    #if defined(_MSC_VER)\n\n        // Microsoft VC++\n        typedef long Spinlock;\n\n    #else\n\n        // GNU g++\n        typedef int Spinlock;\n\n        /**\n         * Compiler read/write barrier\n         */\n        __forceinline__ void _ReadWriteBarrier()\n        {\n            __sync_synchronize();\n        }\n\n        /**\n         * Atomic exchange\n         */\n        __forceinline__ long _InterlockedExchange(volatile int * const Target, const int Value)\n        {\n            // NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier\n            _ReadWriteBarrier();\n            return __sync_lock_test_and_set(Target, Value);\n        }\n\n        /**\n         * Pause instruction to prevent excess processor bus usage\n         */\n        __forceinline__ void YieldProcessor()\n        {\n        }\n\n    #endif  // defined(_MSC_VER)\n\n        /// Lock member\n        volatile Spinlock lock;\n\n        /**\n         * Constructor\n         */\n        Mutex() : lock(0) {}\n\n        /**\n         * Return when the specified spinlock has been acquired\n         */\n        __forceinline__ void Lock()\n        {\n            while (1)\n            {\n                if (!_InterlockedExchange(&lock, 1)) return;\n                while (lock) YieldProcessor();\n            }\n        }\n\n\n        /**\n         * Release the specified spinlock\n         */\n        __forceinline__ void Unlock()\n        {\n            _ReadWriteBarrier();\n            lock = 0;\n        }\n\n#endif      // __cplusplus > 199711L\n\n};\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n"
  },
  {
    "path": "external/cub/cub/iterator/arg_index_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n#include <thrust/version.h>\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A random-access input wrapper for pairing dereferenced values with their corresponding indices (forming \\p KeyValuePair tuples).\n *\n * \\par Overview\n * - ArgIndexInputIteratorTwraps a random access input iterator \\p itr of type \\p InputIteratorT.\n *   Dereferencing an ArgIndexInputIteratorTat offset \\p i produces a \\p KeyValuePair value whose\n *   \\p key field is \\p i and whose \\p value field is <tt>itr[i]</tt>.\n * - Can be used with any data type.\n * - Can be constructed, manipulated, and exchanged within and between host and device\n *   functions.  Wrapped host memory can only be dereferenced on the host, and wrapped\n *   device memory can only be dereferenced on the device.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p ArgIndexInputIteratorTto\n * dereference an array of doubles\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/arg_index_input_iterator.cuh>\n *\n * // Declare, allocate, and initialize a device array\n * double *d_in;         // e.g., [8.0, 6.0, 7.0, 5.0, 3.0, 0.0, 9.0]\n *\n * // Create an iterator wrapper\n * cub::ArgIndexInputIterator<double*> itr(d_in);\n *\n * // Within device code:\n * typedef typename cub::ArgIndexInputIterator<double*>::value_type Tuple;\n * Tuple item_offset_pair.key = *itr;\n * printf(\"%f @ %d\\n\",\n *   item_offset_pair.value,\n *   item_offset_pair.key);   // 8.0 @ 0\n *\n * itr = itr + 6;\n * item_offset_pair.key = *itr;\n * printf(\"%f @ %d\\n\",\n *   item_offset_pair.value,\n *   item_offset_pair.key);   // 9.0 @ 6\n *\n * \\endcode\n *\n * \\tparam InputIteratorT       The value type of the wrapped input iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n * \\tparam OutputValueT         The paired value type of the <offset,value> tuple (Default: value type of input iterator)\n */\ntemplate <\n    typename    InputIteratorT,\n    typename    OffsetT             = ptrdiff_t,\n    typename    OutputValueT        = typename std::iterator_traits<InputIteratorT>::value_type>\nclass ArgIndexInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef ArgIndexInputIterator                       self_type;              ///< My own type\n    typedef OffsetT                                     difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef KeyValuePair<difference_type, OutputValueT> value_type;             ///< The type of the element the iterator can point to\n    typedef value_type*                                 pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef value_type                                  reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::any_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    InputIteratorT  itr;\n    difference_type offset;\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ArgIndexInputIterator(\n        InputIteratorT  itr,            ///< Input iterator to wrap\n        difference_type offset = 0)     ///< OffsetT (in items) from \\p itr denoting the position of the iterator\n    :\n        itr(itr),\n        offset(offset)\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        offset++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        offset++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n        value_type retval;\n        retval.value = itr[offset];\n        retval.key = offset;\n        return retval;\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(itr, offset + n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        offset += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(itr, offset - n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        offset -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return offset - other.offset;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        self_type offset = (*this) + n;\n        return *offset;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &(*(*this));\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return ((itr == rhs.itr) && (offset == rhs.offset));\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return ((itr != rhs.itr) || (offset != rhs.offset));\n    }\n\n    /// Normalize\n    __host__ __device__ __forceinline__ void normalize()\n    {\n        itr += offset;\n        offset = 0;\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& /*itr*/)\n    {\n        return os;\n    }\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/cache_modified_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A random-access input wrapper for dereferencing array values using a PTX cache load modifier.\n *\n * \\par Overview\n * - CacheModifiedInputIteratorTis a random-access input iterator that wraps a native\n *   device pointer of type <tt>ValueType*</tt>. \\p ValueType references are\n *   made by reading \\p ValueType values through loads modified by \\p MODIFIER.\n * - Can be used to load any data type from memory using PTX cache load modifiers (e.g., \"LOAD_LDG\",\n *   \"LOAD_CG\", \"LOAD_CA\", \"LOAD_CS\", \"LOAD_CV\", etc.).\n * - Can be constructed, manipulated, and exchanged within and between host and device\n *   functions, but can only be dereferenced within device functions.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p CacheModifiedInputIteratorTto\n * dereference a device array of double using the \"ldg\" PTX load modifier\n * (i.e., load values through texture cache).\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/cache_modified_input_iterator.cuh>\n *\n * // Declare, allocate, and initialize a device array\n * double *d_in;            // e.g., [8.0, 6.0, 7.0, 5.0, 3.0, 0.0, 9.0]\n *\n * // Create an iterator wrapper\n * cub::CacheModifiedInputIterator<cub::LOAD_LDG, double> itr(d_in);\n *\n * // Within device code:\n * printf(\"%f\\n\", itr[0]);  // 8.0\n * printf(\"%f\\n\", itr[1]);  // 6.0\n * printf(\"%f\\n\", itr[6]);  // 9.0\n *\n * \\endcode\n *\n * \\tparam CacheLoadModifier    The cub::CacheLoadModifier to use when accessing data\n * \\tparam ValueType            The value type of this iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    CacheLoadModifier   MODIFIER,\n    typename            ValueType,\n    typename            OffsetT = ptrdiff_t>\nclass CacheModifiedInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef CacheModifiedInputIterator          self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef ValueType                           value_type;             ///< The type of the element the iterator can point to\n    typedef ValueType*                          pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef ValueType                           reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::device_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\n\npublic:\n\n    /// Wrapped native pointer\n    ValueType* ptr;\n\n    /// Constructor\n    template <typename QualifiedValueType>\n    __host__ __device__ __forceinline__ CacheModifiedInputIterator(\n        QualifiedValueType* ptr)     ///< Native pointer to wrap\n    :\n        ptr(const_cast<typename RemoveQualifiers<QualifiedValueType>::Type *>(ptr))\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        ptr++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        ptr++;\n        return *this;\n    }\n\n    /// Indirection\n    __device__ __forceinline__ reference operator*() const\n    {\n        return ThreadLoad<MODIFIER>(ptr);\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(ptr + n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        ptr += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(ptr - n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        ptr -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return ptr - other.ptr;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        return ThreadLoad<MODIFIER>(ptr + n);\n    }\n\n    /// Structure dereference\n    __device__ __forceinline__ pointer operator->()\n    {\n        return &ThreadLoad<MODIFIER>(ptr);\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (ptr == rhs.ptr);\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (ptr != rhs.ptr);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& /*itr*/)\n    {\n        return os;\n    }\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/cache_modified_output_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A random-access output wrapper for storing array values using a PTX cache-modifier.\n *\n * \\par Overview\n * - CacheModifiedOutputIterator is a random-access output iterator that wraps a native\n *   device pointer of type <tt>ValueType*</tt>. \\p ValueType references are\n *   made by writing \\p ValueType values through stores modified by \\p MODIFIER.\n * - Can be used to store any data type to memory using PTX cache store modifiers (e.g., \"STORE_WB\",\n *   \"STORE_CG\", \"STORE_CS\", \"STORE_WT\", etc.).\n * - Can be constructed, manipulated, and exchanged within and between host and device\n *   functions, but can only be dereferenced within device functions.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p CacheModifiedOutputIterator to\n * dereference a device array of doubles using the \"wt\" PTX load modifier\n * (i.e., write-through to system memory).\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/cache_modified_output_iterator.cuh>\n *\n * // Declare, allocate, and initialize a device array\n * double *d_out;              // e.g., [, , , , , , ]\n *\n * // Create an iterator wrapper\n * cub::CacheModifiedOutputIterator<cub::STORE_WT, double> itr(d_out);\n *\n * // Within device code:\n * itr[0]  = 8.0;\n * itr[1]  = 66.0;\n * itr[55] = 24.0;\n *\n * \\endcode\n *\n * \\par Usage Considerations\n * - Can only be dereferenced within device code\n *\n * \\tparam CacheStoreModifier     The cub::CacheStoreModifier to use when accessing data\n * \\tparam ValueType            The value type of this iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    CacheStoreModifier  MODIFIER,\n    typename            ValueType,\n    typename            OffsetT = ptrdiff_t>\nclass CacheModifiedOutputIterator\n{\nprivate:\n\n    // Proxy object\n    struct Reference\n    {\n        ValueType* ptr;\n\n        /// Constructor\n        __host__ __device__ __forceinline__ Reference(ValueType* ptr) : ptr(ptr) {}\n\n        /// Assignment\n        __device__ __forceinline__ ValueType operator =(ValueType val)\n        {\n            ThreadStore<MODIFIER>(ptr, val);\n            return val;\n        }\n    };\n\npublic:\n\n    // Required iterator traits\n    typedef CacheModifiedOutputIterator         self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef void                                value_type;             ///< The type of the element the iterator can point to\n    typedef void                                pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef Reference                           reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::device_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    ValueType* ptr;\n\npublic:\n\n    /// Constructor\n    template <typename QualifiedValueType>\n    __host__ __device__ __forceinline__ CacheModifiedOutputIterator(\n        QualifiedValueType* ptr)     ///< Native pointer to wrap\n    :\n        ptr(const_cast<typename RemoveQualifiers<QualifiedValueType>::Type *>(ptr))\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        ptr++;\n        return retval;\n    }\n\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        ptr++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n        return Reference(ptr);\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(ptr + n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        ptr += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(ptr - n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        ptr -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return ptr - other.ptr;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        return Reference(ptr + n);\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (ptr == rhs.ptr);\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (ptr != rhs.ptr);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        return os;\n    }\n};\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/constant_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A random-access input generator for dereferencing a sequence of homogeneous values\n *\n * \\par Overview\n * - Read references to a ConstantInputIteratorTiterator always return the supplied constant\n *   of type \\p ValueType.\n * - Can be used with any data type.\n * - Can be constructed, manipulated, dereferenced, and exchanged within and between host and device\n *   functions.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p ConstantInputIteratorTto\n * dereference a sequence of homogeneous doubles.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/constant_input_iterator.cuh>\n *\n * cub::ConstantInputIterator<double> itr(5.0);\n *\n * printf(\"%f\\n\", itr[0]);      // 5.0\n * printf(\"%f\\n\", itr[1]);      // 5.0\n * printf(\"%f\\n\", itr[2]);      // 5.0\n * printf(\"%f\\n\", itr[50]);     // 5.0\n *\n * \\endcode\n *\n * \\tparam ValueType            The value type of this iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    typename ValueType,\n    typename OffsetT = ptrdiff_t>\nclass ConstantInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef ConstantInputIterator               self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef ValueType                           value_type;             ///< The type of the element the iterator can point to\n    typedef ValueType*                          pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef ValueType                           reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::any_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    ValueType   val;\n    OffsetT     offset;\n#ifdef _WIN32\n    OffsetT     pad[CUB_MAX(1, (16 / sizeof(OffsetT) - 1))];        // Workaround for win32 parameter-passing bug (ulonglong2 argmin DeviceReduce)\n#endif\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ConstantInputIterator(\n        ValueType   val,            ///< Starting value for the iterator instance to report\n        OffsetT     offset = 0)     ///< Base offset\n    :\n        val(val),\n        offset(offset)\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        offset++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        offset++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n        return val;\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(val, offset + n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        offset += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(val, offset - n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        offset -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return offset - other.offset;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance /*n*/) const\n    {\n        return val;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &val;\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (offset == rhs.offset) && ((val == rhs.val));\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (offset != rhs.offset) || (val!= rhs.val);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        os << \"[\" << itr.val << \",\" << itr.offset << \"]\";\n        return os;\n    }\n\n};\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/counting_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n/**\n * \\brief A random-access input generator for dereferencing a sequence of incrementing integer values.\n *\n * \\par Overview\n * - After initializing a CountingInputIteratorTto a certain integer \\p base, read references\n *   at \\p offset will return the value \\p base + \\p offset.\n * - Can be constructed, manipulated, dereferenced, and exchanged within and between host and device\n *   functions.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p CountingInputIteratorTto\n * dereference a sequence of incrementing integers.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/counting_input_iterator.cuh>\n *\n * cub::CountingInputIterator<int> itr(5);\n *\n * printf(\"%d\\n\", itr[0]);      // 5\n * printf(\"%d\\n\", itr[1]);      // 6\n * printf(\"%d\\n\", itr[2]);      // 7\n * printf(\"%d\\n\", itr[50]);     // 55\n *\n * \\endcode\n *\n * \\tparam ValueType            The value type of this iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    typename ValueType,\n    typename OffsetT = ptrdiff_t>\nclass CountingInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef CountingInputIterator               self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef ValueType                           value_type;             ///< The type of the element the iterator can point to\n    typedef ValueType*                          pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef ValueType                           reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::any_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    ValueType val;\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ CountingInputIterator(\n        const ValueType &val)          ///< Starting value for the iterator instance to report\n    :\n        val(val)\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        val++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        val++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n        return val;\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(val + (ValueType) n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        val += (ValueType) n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(val - (ValueType) n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        val -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return (difference_type) (val - other.val);\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        return val + (ValueType) n;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &val;\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (val == rhs.val);\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (val != rhs.val);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        os << \"[\" << itr.val << \"]\";\n        return os;\n    }\n\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/discard_output_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../util_namespace.cuh\"\n#include \"../util_macro.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A discard iterator\n */\ntemplate <typename OffsetT = ptrdiff_t>\nclass DiscardOutputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef DiscardOutputIterator   self_type;              ///< My own type\n    typedef OffsetT                 difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef void                    value_type;             ///< The type of the element the iterator can point to\n    typedef void                    pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef void                    reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::any_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    OffsetT offset;\n\n#if defined(_WIN32) || !defined(_WIN64)\n    // Workaround for win32 parameter-passing bug (ulonglong2 argmin DeviceReduce)\n    OffsetT pad[CUB_MAX(1, (16 / sizeof(OffsetT) - 1))];\n#endif\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ DiscardOutputIterator(\n        OffsetT offset = 0)     ///< Base offset\n    :\n        offset(offset)\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        offset++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        offset++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ self_type& operator*()\n    {\n        // return self reference, which can be assigned to anything\n        return *this;\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(offset + n);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        offset += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(offset - n);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        offset -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return offset - other.offset;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator[](Distance n)\n    {\n        // return self reference, which can be assigned to anything\n        return *this;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return;\n    }\n\n    /// Assignment to self (no-op)\n    __host__ __device__ __forceinline__ void operator=(self_type const& other)\n    {\n        offset = other.offset;\n    }\n\n    /// Assignment to anything else (no-op)\n    template<typename T>\n    __host__ __device__ __forceinline__ void operator=(T const&)\n    {}\n\n    /// Cast to void* operator\n    __host__ __device__ __forceinline__ operator void*() const { return NULL; }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (offset == rhs.offset);\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (offset != rhs.offset);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        os << \"[\" << itr.offset << \"]\";\n        return os;\n    }\n\n};\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/tex_obj_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_debug.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n\n/**\n * \\brief A random-access input wrapper for dereferencing array values through texture cache.  Uses newer Kepler-style texture objects.\n *\n * \\par Overview\n * - TexObjInputIteratorTwraps a native device pointer of type <tt>ValueType*</tt>. References\n *   to elements are to be loaded through texture cache.\n * - Can be used to load any data type from memory through texture cache.\n * - Can be manipulated and exchanged within and between host and device\n *   functions, can only be constructed within host functions, and can only be\n *   dereferenced within device functions.\n * - With regard to nested/dynamic parallelism, TexObjInputIteratorTiterators may only be\n *   created by the host thread, but can be used by any descendant kernel.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p TexRefInputIteratorTto\n * dereference a device array of doubles through texture cache.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/tex_obj_input_iterator.cuh>\n *\n * // Declare, allocate, and initialize a device array\n * int num_items;   // e.g., 7\n * double *d_in;    // e.g., [8.0, 6.0, 7.0, 5.0, 3.0, 0.0, 9.0]\n *\n * // Create an iterator wrapper\n * cub::TexObjInputIterator<double> itr;\n * itr.BindTexture(d_in, sizeof(double) * num_items);\n * ...\n *\n * // Within device code:\n * printf(\"%f\\n\", itr[0]);      // 8.0\n * printf(\"%f\\n\", itr[1]);      // 6.0\n * printf(\"%f\\n\", itr[6]);      // 9.0\n *\n * ...\n * itr.UnbindTexture();\n *\n * \\endcode\n *\n * \\tparam T                    The value type of this iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    typename    T,\n    typename    OffsetT = ptrdiff_t>\nclass TexObjInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef TexObjInputIterator                 self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef T                                   value_type;             ///< The type of the element the iterator can point to\n    typedef T*                                  pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef T                                   reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::device_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    // Largest texture word we can use in device\n    typedef typename UnitWord<T>::TextureWord TextureWord;\n\n    // Number of texture words per T\n    enum {\n        TEXTURE_MULTIPLE = sizeof(T) / sizeof(TextureWord)\n    };\n\nprivate:\n\n    T*                  ptr;\n    difference_type     tex_offset;\n    cudaTextureObject_t tex_obj;\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ TexObjInputIterator()\n    :\n        ptr(NULL),\n        tex_offset(0),\n        tex_obj(0)\n    {}\n\n    /// Use this iterator to bind \\p ptr with a texture reference\n    template <typename QualifiedT>\n    cudaError_t BindTexture(\n        QualifiedT      *ptr,               ///< Native pointer to wrap that is aligned to cudaDeviceProp::textureAlignment\n        size_t          bytes = size_t(-1),         ///< Number of bytes in the range\n        size_t          tex_offset = 0)     ///< OffsetT (in items) from \\p ptr denoting the position of the iterator\n    {\n        this->ptr = const_cast<typename RemoveQualifiers<QualifiedT>::Type *>(ptr);\n        this->tex_offset = tex_offset;\n\n        cudaChannelFormatDesc   channel_desc = cudaCreateChannelDesc<TextureWord>();\n        cudaResourceDesc        res_desc;\n        cudaTextureDesc         tex_desc;\n        memset(&res_desc, 0, sizeof(cudaResourceDesc));\n        memset(&tex_desc, 0, sizeof(cudaTextureDesc));\n        res_desc.resType                = cudaResourceTypeLinear;\n        res_desc.res.linear.devPtr      = this->ptr;\n        res_desc.res.linear.desc        = channel_desc;\n        res_desc.res.linear.sizeInBytes = bytes;\n        tex_desc.readMode               = cudaReadModeElementType;\n        return cudaCreateTextureObject(&tex_obj, &res_desc, &tex_desc, NULL);\n    }\n\n    /// Unbind this iterator from its texture reference\n    cudaError_t UnbindTexture()\n    {\n        return cudaDestroyTextureObject(tex_obj);\n    }\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        tex_offset++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        tex_offset++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n#if (CUB_PTX_ARCH == 0)\n        // Simply dereference the pointer on the host\n        return ptr[tex_offset];\n#else\n        // Move array of uninitialized words, then alias and assign to return value\n        TextureWord words[TEXTURE_MULTIPLE];\n\n        #pragma unroll\n        for (int i = 0; i < TEXTURE_MULTIPLE; ++i)\n        {\n            words[i] = tex1Dfetch<TextureWord>(\n                tex_obj,\n                (tex_offset * TEXTURE_MULTIPLE) + i);\n        }\n\n        // Load from words\n        return *reinterpret_cast<T*>(words);\n#endif\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval;\n        retval.ptr          = ptr;\n        retval.tex_obj      = tex_obj;\n        retval.tex_offset   = tex_offset + n;\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        tex_offset += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval;\n        retval.ptr          = ptr;\n        retval.tex_obj      = tex_obj;\n        retval.tex_offset   = tex_offset - n;\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        tex_offset -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return tex_offset - other.tex_offset;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        self_type offset = (*this) + n;\n        return *offset;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &(*(*this));\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return ((ptr == rhs.ptr) && (tex_offset == rhs.tex_offset) && (tex_obj == rhs.tex_obj));\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return ((ptr != rhs.ptr) || (tex_offset != rhs.tex_offset) || (tex_obj != rhs.tex_obj));\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        return os;\n    }\n\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/iterator/tex_ref_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_debug.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (CUDA_VERSION >= 5050) || defined(DOXYGEN_ACTIVE)  // This iterator is compatible with CUDA 5.5 and newer\n\n#if (THRUST_VERSION >= 100700)    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/******************************************************************************\n * Static file-scope Tesla/Fermi-style texture references\n *****************************************************************************/\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n// Anonymous namespace\nnamespace {\n\n/// Global texture reference specialized by type\ntemplate <typename T>\nstruct IteratorTexRef\n{\n    /// And by unique ID\n    template <int UNIQUE_ID>\n    struct TexId\n    {\n        // Largest texture word we can use in device\n        typedef typename UnitWord<T>::DeviceWord DeviceWord;\n        typedef typename UnitWord<T>::TextureWord TextureWord;\n\n        // Number of texture words per T\n        enum {\n            DEVICE_MULTIPLE = sizeof(T) / sizeof(DeviceWord),\n            TEXTURE_MULTIPLE = sizeof(T) / sizeof(TextureWord)\n        };\n\n        // Texture reference type\n        typedef texture<TextureWord> TexRef;\n\n        // Texture reference\n        static TexRef ref;\n\n        /// Bind texture\n        static cudaError_t BindTexture(void *d_in, size_t &offset)\n        {\n            if (d_in)\n            {\n                cudaChannelFormatDesc tex_desc = cudaCreateChannelDesc<TextureWord>();\n                ref.channelDesc = tex_desc;\n                return (CubDebug(cudaBindTexture(&offset, ref, d_in)));\n            }\n\n            return cudaSuccess;\n        }\n\n        /// Unbind texture\n        static cudaError_t UnbindTexture()\n        {\n            return CubDebug(cudaUnbindTexture(ref));\n        }\n\n        /// Fetch element\n        template <typename Distance>\n        static __device__ __forceinline__ T Fetch(Distance tex_offset)\n        {\n            DeviceWord temp[DEVICE_MULTIPLE];\n            TextureWord *words = reinterpret_cast<TextureWord*>(temp);\n\n            #pragma unroll\n            for (int i = 0; i < TEXTURE_MULTIPLE; ++i)\n            {\n                words[i] = tex1Dfetch(ref, (tex_offset * TEXTURE_MULTIPLE) + i);\n            }\n\n            return reinterpret_cast<T&>(temp);\n        }\n    };\n};\n\n// Texture reference definitions\ntemplate <typename  T>\ntemplate <int       UNIQUE_ID>\ntypename IteratorTexRef<T>::template TexId<UNIQUE_ID>::TexRef IteratorTexRef<T>::template TexId<UNIQUE_ID>::ref = 0;\n\n\n} // Anonymous namespace\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n\n/**\n * \\brief A random-access input wrapper for dereferencing array values through texture cache.  Uses older Tesla/Fermi-style texture references.\n *\n * \\par Overview\n * - TexRefInputIteratorTwraps a native device pointer of type <tt>ValueType*</tt>. References\n *   to elements are to be loaded through texture cache.\n * - Can be used to load any data type from memory through texture cache.\n * - Can be manipulated and exchanged within and between host and device\n *   functions, can only be constructed within host functions, and can only be\n *   dereferenced within device functions.\n * - The \\p UNIQUE_ID template parameter is used to statically name the underlying texture\n *   reference.  Only one TexRefInputIteratorTinstance can be bound at any given time for a\n *   specific combination of (1) data type \\p T, (2) \\p UNIQUE_ID, (3) host\n *   thread, and (4) compilation .o unit.\n * - With regard to nested/dynamic parallelism, TexRefInputIteratorTiterators may only be\n *   created by the host thread and used by a top-level kernel (i.e. the one which is launched\n *   from the host).\n * - Compatible with Thrust API v1.7 or newer.\n * - Compatible with CUDA toolkit v5.5 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p TexRefInputIteratorTto\n * dereference a device array of doubles through texture cache.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/tex_ref_input_iterator.cuh>\n *\n * // Declare, allocate, and initialize a device array\n * int num_items;   // e.g., 7\n * double *d_in;    // e.g., [8.0, 6.0, 7.0, 5.0, 3.0, 0.0, 9.0]\n *\n * // Create an iterator wrapper\n * cub::TexRefInputIterator<double, __LINE__> itr;\n * itr.BindTexture(d_in, sizeof(double) * num_items);\n * ...\n *\n * // Within device code:\n * printf(\"%f\\n\", itr[0]);      // 8.0\n * printf(\"%f\\n\", itr[1]);      // 6.0\n * printf(\"%f\\n\", itr[6]);      // 9.0\n *\n * ...\n * itr.UnbindTexture();\n *\n * \\endcode\n *\n * \\tparam T                    The value type of this iterator\n * \\tparam UNIQUE_ID            A globally-unique identifier (within the compilation unit) to name the underlying texture reference\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n */\ntemplate <\n    typename    T,\n    int         UNIQUE_ID,\n    typename    OffsetT = ptrdiff_t>\nclass TexRefInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef TexRefInputIterator                 self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef T                                   value_type;             ///< The type of the element the iterator can point to\n    typedef T*                                  pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef T                                   reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::device_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    T*              ptr;\n    difference_type tex_offset;\n\n    // Texture reference wrapper (old Tesla/Fermi-style textures)\n    typedef typename IteratorTexRef<T>::template TexId<UNIQUE_ID> TexId;\n\npublic:\n/*\n    /// Constructor\n    __host__ __device__ __forceinline__ TexRefInputIterator()\n    :\n        ptr(NULL),\n        tex_offset(0)\n    {}\n*/\n    /// Use this iterator to bind \\p ptr with a texture reference\n    template <typename QualifiedT>\n    cudaError_t BindTexture(\n        QualifiedT      *ptr,                   ///< Native pointer to wrap that is aligned to cudaDeviceProp::textureAlignment\n        size_t          bytes = size_t(-1),     ///< Number of bytes in the range\n        size_t          tex_offset = 0)         ///< OffsetT (in items) from \\p ptr denoting the position of the iterator\n    {\n        this->ptr = const_cast<typename RemoveQualifiers<QualifiedT>::Type *>(ptr);\n        size_t offset;\n        cudaError_t retval = TexId::BindTexture(this->ptr + tex_offset, offset);\n        this->tex_offset = (difference_type) (offset / sizeof(QualifiedT));\n        return retval;\n    }\n\n    /// Unbind this iterator from its texture reference\n    cudaError_t UnbindTexture()\n    {\n        return TexId::UnbindTexture();\n    }\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        tex_offset++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        tex_offset++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n#if (CUB_PTX_ARCH == 0)\n        // Simply dereference the pointer on the host\n        return ptr[tex_offset];\n#else\n        // Use the texture reference\n        return TexId::Fetch(tex_offset);\n#endif\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval;\n        retval.ptr = ptr;\n        retval.tex_offset = tex_offset + n;\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        tex_offset += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval;\n        retval.ptr = ptr;\n        retval.tex_offset = tex_offset - n;\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        tex_offset -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return tex_offset - other.tex_offset;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        self_type offset = (*this) + n;\n        return *offset;\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &(*(*this));\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return ((ptr == rhs.ptr) && (tex_offset == rhs.tex_offset));\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return ((ptr != rhs.ptr) || (tex_offset != rhs.tex_offset));\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        return os;\n    }\n\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n\n#endif // CUDA_VERSION\n"
  },
  {
    "path": "external/cub/cub/iterator/transform_input_iterator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Random-access iterator types\n */\n\n#pragma once\n\n#include <iterator>\n#include <iostream>\n\n#include \"../thread/thread_load.cuh\"\n#include \"../thread/thread_store.cuh\"\n#include \"../util_device.cuh\"\n#include \"../util_namespace.cuh\"\n\n#if (THRUST_VERSION >= 100700)\n    // This iterator is compatible with Thrust API 1.7 and newer\n    #include <thrust/iterator/iterator_facade.h>\n    #include <thrust/iterator/iterator_traits.h>\n#endif // THRUST_VERSION\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIterator\n * @{\n */\n\n\n/**\n * \\brief A random-access input wrapper for transforming dereferenced values.\n *\n * \\par Overview\n * - TransformInputIteratorTwraps a unary conversion functor of type \\p\n *   ConversionOp and a random-access input iterator of type <tt>InputIteratorT</tt>,\n *   using the former to produce references of type \\p ValueType from the latter.\n * - Can be used with any data type.\n * - Can be constructed, manipulated, and exchanged within and between host and device\n *   functions.  Wrapped host memory can only be dereferenced on the host, and wrapped\n *   device memory can only be dereferenced on the device.\n * - Compatible with Thrust API v1.7 or newer.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of \\p TransformInputIteratorTto\n * dereference an array of integers, tripling the values and converting them to doubles.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/iterator/transform_input_iterator.cuh>\n *\n * // Functor for tripling integer values and converting to doubles\n * struct TripleDoubler\n * {\n *     __host__ __device__ __forceinline__\n *     double operator()(const int &a) const {\n *         return double(a * 3);\n *     }\n * };\n *\n * // Declare, allocate, and initialize a device array\n * int *d_in;                   // e.g., [8, 6, 7, 5, 3, 0, 9]\n * TripleDoubler conversion_op;\n *\n * // Create an iterator wrapper\n * cub::TransformInputIterator<double, TripleDoubler, int*> itr(d_in, conversion_op);\n *\n * // Within device code:\n * printf(\"%f\\n\", itr[0]);  // 24.0\n * printf(\"%f\\n\", itr[1]);  // 18.0\n * printf(\"%f\\n\", itr[6]);  // 27.0\n *\n * \\endcode\n *\n * \\tparam ValueType            The value type of this iterator\n * \\tparam ConversionOp         Unary functor type for mapping objects of type \\p InputType to type \\p ValueType.  Must have member <tt>ValueType operator()(const InputType &datum)</tt>.\n * \\tparam InputIteratorT       The type of the wrapped input iterator\n * \\tparam OffsetT              The difference type of this iterator (Default: \\p ptrdiff_t)\n *\n */\ntemplate <\n    typename ValueType,\n    typename ConversionOp,\n    typename InputIteratorT,\n    typename OffsetT = ptrdiff_t>\nclass TransformInputIterator\n{\npublic:\n\n    // Required iterator traits\n    typedef TransformInputIterator              self_type;              ///< My own type\n    typedef OffsetT                             difference_type;        ///< Type to express the result of subtracting one iterator from another\n    typedef ValueType                           value_type;             ///< The type of the element the iterator can point to\n    typedef ValueType*                          pointer;                ///< The type of a pointer to an element the iterator can point to\n    typedef ValueType                           reference;              ///< The type of a reference to an element the iterator can point to\n\n#if (THRUST_VERSION >= 100700)\n    // Use Thrust's iterator categories so we can use these iterators in Thrust 1.7 (or newer) methods\n    typedef typename thrust::detail::iterator_facade_category<\n        thrust::any_system_tag,\n        thrust::random_access_traversal_tag,\n        value_type,\n        reference\n      >::type iterator_category;                                        ///< The iterator category\n#else\n    typedef std::random_access_iterator_tag     iterator_category;      ///< The iterator category\n#endif  // THRUST_VERSION\n\nprivate:\n\n    ConversionOp    conversion_op;\n    InputIteratorT  input_itr;\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__ TransformInputIterator(\n        InputIteratorT      input_itr,          ///< Input iterator to wrap\n        ConversionOp        conversion_op)      ///< Conversion functor to wrap\n    :\n        conversion_op(conversion_op),\n        input_itr(input_itr)\n    {}\n\n    /// Postfix increment\n    __host__ __device__ __forceinline__ self_type operator++(int)\n    {\n        self_type retval = *this;\n        input_itr++;\n        return retval;\n    }\n\n    /// Prefix increment\n    __host__ __device__ __forceinline__ self_type operator++()\n    {\n        input_itr++;\n        return *this;\n    }\n\n    /// Indirection\n    __host__ __device__ __forceinline__ reference operator*() const\n    {\n        return conversion_op(*input_itr);\n    }\n\n    /// Addition\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator+(Distance n) const\n    {\n        self_type retval(input_itr + n, conversion_op);\n        return retval;\n    }\n\n    /// Addition assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator+=(Distance n)\n    {\n        input_itr += n;\n        return *this;\n    }\n\n    /// Subtraction\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type operator-(Distance n) const\n    {\n        self_type retval(input_itr - n, conversion_op);\n        return retval;\n    }\n\n    /// Subtraction assignment\n    template <typename Distance>\n    __host__ __device__ __forceinline__ self_type& operator-=(Distance n)\n    {\n        input_itr -= n;\n        return *this;\n    }\n\n    /// Distance\n    __host__ __device__ __forceinline__ difference_type operator-(self_type other) const\n    {\n        return input_itr - other.input_itr;\n    }\n\n    /// Array subscript\n    template <typename Distance>\n    __host__ __device__ __forceinline__ reference operator[](Distance n) const\n    {\n        return conversion_op(input_itr[n]);\n    }\n\n    /// Structure dereference\n    __host__ __device__ __forceinline__ pointer operator->()\n    {\n        return &conversion_op(*input_itr);\n    }\n\n    /// Equal to\n    __host__ __device__ __forceinline__ bool operator==(const self_type& rhs)\n    {\n        return (input_itr == rhs.input_itr);\n    }\n\n    /// Not equal to\n    __host__ __device__ __forceinline__ bool operator!=(const self_type& rhs)\n    {\n        return (input_itr != rhs.input_itr);\n    }\n\n    /// ostream operator\n    friend std::ostream& operator<<(std::ostream& os, const self_type& itr)\n    {\n        return os;\n    }\n};\n\n\n\n/** @} */       // end group UtilIterator\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_load.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Thread utilities for reading memory using PTX cache modifiers.\n */\n\n#pragma once\n\n#include <cuda.h>\n\n#include <iterator>\n\n#include \"../util_ptx.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIo\n * @{\n */\n\n//-----------------------------------------------------------------------------\n// Tags and constants\n//-----------------------------------------------------------------------------\n\n/**\n * \\brief Enumeration of cache modifiers for memory load operations.\n */\nenum CacheLoadModifier\n{\n    LOAD_DEFAULT,       ///< Default (no modifier)\n    LOAD_CA,            ///< Cache at all levels\n    LOAD_CG,            ///< Cache at global level\n    LOAD_CS,            ///< Cache streaming (likely to be accessed once)\n    LOAD_CV,            ///< Cache as volatile (including cached system lines)\n    LOAD_LDG,           ///< Cache as texture\n    LOAD_VOLATILE,      ///< Volatile (any memory space)\n};\n\n\n/**\n * \\name Thread I/O (cache modified)\n * @{\n */\n\n/**\n * \\brief Thread utility for reading memory using cub::CacheLoadModifier cache modifiers.  Can be used to load any data type.\n *\n * \\par Example\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/thread/thread_load.cuh>\n *\n * // 32-bit load using cache-global modifier:\n * int *d_in;\n * int val = cub::ThreadLoad<cub::LOAD_CA>(d_in + threadIdx.x);\n *\n * // 16-bit load using default modifier\n * short *d_in;\n * short val = cub::ThreadLoad<cub::LOAD_DEFAULT>(d_in + threadIdx.x);\n *\n * // 256-bit load using cache-volatile modifier\n * double4 *d_in;\n * double4 val = cub::ThreadLoad<cub::LOAD_CV>(d_in + threadIdx.x);\n *\n * // 96-bit load using cache-streaming modifier\n * struct TestFoo { bool a; short b; };\n * TestFoo *d_struct;\n * TestFoo val = cub::ThreadLoad<cub::LOAD_CS>(d_in + threadIdx.x);\n * \\endcode\n *\n * \\tparam MODIFIER             <b>[inferred]</b> CacheLoadModifier enumeration\n * \\tparam InputIteratorT       <b>[inferred]</b> Input iterator type \\iterator\n */\ntemplate <\n    CacheLoadModifier MODIFIER,\n    typename InputIteratorT>\n__device__ __forceinline__ typename std::iterator_traits<InputIteratorT>::value_type ThreadLoad(InputIteratorT itr);\n\n\n//@}  end member group\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/// Helper structure for templated load iteration (inductive case)\ntemplate <int COUNT, int MAX>\nstruct IterateThreadLoad\n{\n    template <CacheLoadModifier MODIFIER, typename T>\n    static __device__ __forceinline__ void Load(T const *ptr, T *vals)\n    {\n        vals[COUNT] = ThreadLoad<MODIFIER>(ptr + COUNT);\n        IterateThreadLoad<COUNT + 1, MAX>::template Load<MODIFIER>(ptr, vals);\n    }\n\n    template <typename InputIteratorT, typename T>\n    static __device__ __forceinline__ void Dereference(InputIteratorT itr, T *vals)\n    {\n        vals[COUNT] = itr[COUNT];\n        IterateThreadLoad<COUNT + 1, MAX>::Dereference(itr, vals);\n    }\n};\n\n\n/// Helper structure for templated load iteration (termination case)\ntemplate <int MAX>\nstruct IterateThreadLoad<MAX, MAX>\n{\n    template <CacheLoadModifier MODIFIER, typename T>\n    static __device__ __forceinline__ void Load(T const * /*ptr*/, T * /*vals*/) {}\n\n    template <typename InputIteratorT, typename T>\n    static __device__ __forceinline__ void Dereference(InputIteratorT /*itr*/, T * /*vals*/) {}\n};\n\n\n/**\n * Define a uint4 (16B) ThreadLoad specialization for the given Cache load modifier\n */\n#define _CUB_LOAD_16(cub_modifier, ptx_modifier)                                             \\\n    template<>                                                                              \\\n    __device__ __forceinline__ uint4 ThreadLoad<cub_modifier, uint4 const *>(uint4 const *ptr)                   \\\n    {                                                                                       \\\n        uint4 retval;                                                                       \\\n        asm volatile (\"ld.\"#ptx_modifier\".v4.u32 {%0, %1, %2, %3}, [%4];\" :                 \\\n            \"=r\"(retval.x),                                                                 \\\n            \"=r\"(retval.y),                                                                 \\\n            \"=r\"(retval.z),                                                                 \\\n            \"=r\"(retval.w) :                                                                \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ ulonglong2 ThreadLoad<cub_modifier, ulonglong2 const *>(ulonglong2 const *ptr)    \\\n    {                                                                                       \\\n        ulonglong2 retval;                                                                  \\\n        asm volatile (\"ld.\"#ptx_modifier\".v2.u64 {%0, %1}, [%2];\" :                         \\\n            \"=l\"(retval.x),                                                                 \\\n            \"=l\"(retval.y) :                                                                \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }\n\n/**\n * Define a uint2 (8B) ThreadLoad specialization for the given Cache load modifier\n */\n#define _CUB_LOAD_8(cub_modifier, ptx_modifier)                                              \\\n    template<>                                                                              \\\n    __device__ __forceinline__ ushort4 ThreadLoad<cub_modifier, ushort4 const *>(ushort4 const *ptr)             \\\n    {                                                                                       \\\n        ushort4 retval;                                                                     \\\n        asm volatile (\"ld.\"#ptx_modifier\".v4.u16 {%0, %1, %2, %3}, [%4];\" :                 \\\n            \"=h\"(retval.x),                                                                 \\\n            \"=h\"(retval.y),                                                                 \\\n            \"=h\"(retval.z),                                                                 \\\n            \"=h\"(retval.w) :                                                                \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ uint2 ThreadLoad<cub_modifier, uint2 const *>(uint2 const *ptr)                   \\\n    {                                                                                       \\\n        uint2 retval;                                                                       \\\n        asm volatile (\"ld.\"#ptx_modifier\".v2.u32 {%0, %1}, [%2];\" :                         \\\n            \"=r\"(retval.x),                                                                 \\\n            \"=r\"(retval.y) :                                                                \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ unsigned long long ThreadLoad<cub_modifier, unsigned long long const *>(unsigned long long const *ptr)    \\\n    {                                                                                       \\\n        unsigned long long retval;                                                          \\\n        asm volatile (\"ld.\"#ptx_modifier\".u64 %0, [%1];\" :                                  \\\n            \"=l\"(retval) :                                                                  \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }\n\n/**\n * Define a uint (4B) ThreadLoad specialization for the given Cache load modifier\n */\n#define _CUB_LOAD_4(cub_modifier, ptx_modifier)                                              \\\n    template<>                                                                              \\\n    __device__ __forceinline__ unsigned int ThreadLoad<cub_modifier, unsigned int const *>(unsigned int const *ptr)                      \\\n    {                                                                                       \\\n        unsigned int retval;                                                                \\\n        asm volatile (\"ld.\"#ptx_modifier\".u32 %0, [%1];\" :                                  \\\n            \"=r\"(retval) :                                                                  \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }\n\n\n/**\n * Define a unsigned short (2B) ThreadLoad specialization for the given Cache load modifier\n */\n#define _CUB_LOAD_2(cub_modifier, ptx_modifier)                                              \\\n    template<>                                                                              \\\n    __device__ __forceinline__ unsigned short ThreadLoad<cub_modifier, unsigned short const *>(unsigned short const *ptr)                \\\n    {                                                                                       \\\n        unsigned short retval;                                                              \\\n        asm volatile (\"ld.\"#ptx_modifier\".u16 %0, [%1];\" :                                  \\\n            \"=h\"(retval) :                                                                  \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return retval;                                                                      \\\n    }\n\n\n/**\n * Define an unsigned char (1B) ThreadLoad specialization for the given Cache load modifier\n */\n#define _CUB_LOAD_1(cub_modifier, ptx_modifier)                                              \\\n    template<>                                                                              \\\n    __device__ __forceinline__ unsigned char ThreadLoad<cub_modifier, unsigned char const *>(unsigned char const *ptr)                   \\\n    {                                                                                       \\\n        unsigned short retval;                                                              \\\n        asm volatile (                                                                      \\\n        \"{\"                                                                                 \\\n        \"   .reg .u8 datum;\"                                                                \\\n        \"    ld.\"#ptx_modifier\".u8 datum, [%1];\"                                            \\\n        \"    cvt.u16.u8 %0, datum;\"                                                         \\\n        \"}\" :                                                                               \\\n            \"=h\"(retval) :                                                                  \\\n            _CUB_ASM_PTR_(ptr));                                                            \\\n        return (unsigned char) retval;                                                      \\\n    }\n\n\n/**\n * Define powers-of-two ThreadLoad specializations for the given Cache load modifier\n */\n#define _CUB_LOAD_ALL(cub_modifier, ptx_modifier)                                            \\\n    _CUB_LOAD_16(cub_modifier, ptx_modifier)                                                 \\\n    _CUB_LOAD_8(cub_modifier, ptx_modifier)                                                  \\\n    _CUB_LOAD_4(cub_modifier, ptx_modifier)                                                  \\\n    _CUB_LOAD_2(cub_modifier, ptx_modifier)                                                  \\\n    _CUB_LOAD_1(cub_modifier, ptx_modifier)                                                  \\\n\n\n/**\n * Define powers-of-two ThreadLoad specializations for the various Cache load modifiers\n */\n#if CUB_PTX_ARCH >= 200\n    _CUB_LOAD_ALL(LOAD_CA, ca)\n    _CUB_LOAD_ALL(LOAD_CG, cg)\n    _CUB_LOAD_ALL(LOAD_CS, cs)\n    _CUB_LOAD_ALL(LOAD_CV, cv)\n#else\n    _CUB_LOAD_ALL(LOAD_CA, global)\n    // Use volatile to ensure coherent reads when this PTX is JIT'd to run on newer architectures with L1\n    _CUB_LOAD_ALL(LOAD_CG, volatile.global)\n    _CUB_LOAD_ALL(LOAD_CS, global)\n    _CUB_LOAD_ALL(LOAD_CV, volatile.global)\n#endif\n\n#if CUB_PTX_ARCH >= 350\n    _CUB_LOAD_ALL(LOAD_LDG, global.nc)\n#else\n    _CUB_LOAD_ALL(LOAD_LDG, global)\n#endif\n\n\n// Macro cleanup\n#undef _CUB_LOAD_ALL\n#undef _CUB_LOAD_1\n#undef _CUB_LOAD_2\n#undef _CUB_LOAD_4\n#undef _CUB_LOAD_8\n#undef _CUB_LOAD_16\n\n\n\n/**\n * ThreadLoad definition for LOAD_DEFAULT modifier on iterator types\n */\ntemplate <typename InputIteratorT>\n__device__ __forceinline__ typename std::iterator_traits<InputIteratorT>::value_type ThreadLoad(\n    InputIteratorT          itr,\n    Int2Type<LOAD_DEFAULT>  /*modifier*/,\n    Int2Type<false>         /*is_pointer*/)\n{\n    return *itr;\n}\n\n\n/**\n * ThreadLoad definition for LOAD_DEFAULT modifier on pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ T ThreadLoad(\n    T                       *ptr,\n    Int2Type<LOAD_DEFAULT>  /*modifier*/,\n    Int2Type<true>          /*is_pointer*/)\n{\n    return *ptr;\n}\n\n\n/**\n * ThreadLoad definition for LOAD_VOLATILE modifier on primitive pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ T ThreadLoadVolatilePointer(\n    T                       *ptr,\n    Int2Type<true>          /*is_primitive*/)\n{\n    T retval = *reinterpret_cast<volatile T*>(ptr);\n    return retval;\n}\n\n\n/**\n * ThreadLoad definition for LOAD_VOLATILE modifier on non-primitive pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ T ThreadLoadVolatilePointer(\n    T                       *ptr,\n    Int2Type<false>         /*is_primitive*/)\n{\n    typedef typename UnitWord<T>::VolatileWord VolatileWord;   // Word type for memcopying\n\n    const int VOLATILE_MULTIPLE = sizeof(T) / sizeof(VolatileWord);\n/*\n    VolatileWord words[VOLATILE_MULTIPLE];\n\n    IterateThreadLoad<0, VOLATILE_MULTIPLE>::Dereference(\n        reinterpret_cast<volatile VolatileWord*>(ptr),\n        words);\n\n    return *reinterpret_cast<T*>(words);\n*/\n\n    T retval;\n    VolatileWord *words = reinterpret_cast<VolatileWord*>(&retval);\n    IterateThreadLoad<0, VOLATILE_MULTIPLE>::Dereference(\n        reinterpret_cast<volatile VolatileWord*>(ptr),\n        words);\n    return retval;\n}\n\n\n/**\n * ThreadLoad definition for LOAD_VOLATILE modifier on pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ T ThreadLoad(\n    T                       *ptr,\n    Int2Type<LOAD_VOLATILE> /*modifier*/,\n    Int2Type<true>          /*is_pointer*/)\n{\n    // Apply tags for partial-specialization\n    return ThreadLoadVolatilePointer(ptr, Int2Type<Traits<T>::PRIMITIVE>());\n}\n\n\n/**\n * ThreadLoad definition for generic modifiers on pointer types\n */\ntemplate <typename T, int MODIFIER>\n__device__ __forceinline__ T ThreadLoad(\n    T const                 *ptr,\n    Int2Type<MODIFIER>      /*modifier*/,\n    Int2Type<true>          /*is_pointer*/)\n{\n    typedef typename UnitWord<T>::DeviceWord DeviceWord;\n\n    const int DEVICE_MULTIPLE = sizeof(T) / sizeof(DeviceWord);\n\n    DeviceWord words[DEVICE_MULTIPLE];\n\n    IterateThreadLoad<0, DEVICE_MULTIPLE>::template Load<CacheLoadModifier(MODIFIER)>(\n        reinterpret_cast<DeviceWord*>(const_cast<T*>(ptr)),\n        words);\n\n    return *reinterpret_cast<T*>(words);\n}\n\n\n/**\n * ThreadLoad definition for generic modifiers\n */\ntemplate <\n    CacheLoadModifier MODIFIER,\n    typename InputIteratorT>\n__device__ __forceinline__ typename std::iterator_traits<InputIteratorT>::value_type ThreadLoad(InputIteratorT itr)\n{\n    // Apply tags for partial-specialization\n    return ThreadLoad(\n        itr,\n        Int2Type<MODIFIER>(),\n        Int2Type<IsPointer<InputIteratorT>::VALUE>());\n}\n\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/** @} */       // end group UtilIo\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_operators.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Simple binary operator functor types\n */\n\n/******************************************************************************\n * Simple functor operators\n ******************************************************************************/\n\n#pragma once\n\n#include \"../util_macro.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilModule\n * @{\n */\n\n/**\n * \\brief Default equality functor\n */\nstruct Equality\n{\n    /// Boolean equality operator, returns <tt>(a == b)</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ bool operator()(const T &a, const T &b) const\n    {\n        return a == b;\n    }\n};\n\n\n/**\n * \\brief Default inequality functor\n */\nstruct Inequality\n{\n    /// Boolean inequality operator, returns <tt>(a != b)</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ bool operator()(const T &a, const T &b) const\n    {\n        return a != b;\n    }\n};\n\n\n/**\n * \\brief Inequality functor (wraps equality functor)\n */\ntemplate <typename EqualityOp>\nstruct InequalityWrapper\n{\n    /// Wrapped equality operator\n    EqualityOp op;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    InequalityWrapper(EqualityOp op) : op(op) {}\n\n    /// Boolean inequality operator, returns <tt>(a != b)</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ bool operator()(const T &a, const T &b)\n    {\n        return !op(a, b);\n    }\n};\n\n\n/**\n * \\brief Default sum functor\n */\nstruct Sum\n{\n    /// Boolean sum operator, returns <tt>a + b</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return a + b;\n    }\n};\n\n\n/**\n * \\brief Default max functor\n */\nstruct Max\n{\n    /// Boolean max operator, returns <tt>(a > b) ? a : b</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return CUB_MAX(a, b);\n    }\n};\n\n\n/**\n * \\brief Arg max functor (keeps the value and offset of the first occurrence of the larger item)\n */\nstruct ArgMax\n{\n    /// Boolean max operator, preferring the item having the smaller offset in case of ties\n    template <typename T, typename OffsetT>\n    __host__ __device__ __forceinline__ KeyValuePair<OffsetT, T> operator()(\n        const KeyValuePair<OffsetT, T> &a,\n        const KeyValuePair<OffsetT, T> &b) const\n    {\n// Mooch BUG (device reduce argmax gk110 3.2 million random fp32)\n//        return ((b.value > a.value) || ((a.value == b.value) && (b.key < a.key))) ? b : a;\n\n        if ((b.value > a.value) || ((a.value == b.value) && (b.key < a.key)))\n            return b;\n        return a;\n    }\n};\n\n\n/**\n * \\brief Default min functor\n */\nstruct Min\n{\n    /// Boolean min operator, returns <tt>(a < b) ? a : b</tt>\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return CUB_MIN(a, b);\n    }\n};\n\n\n/**\n * \\brief Arg min functor (keeps the value and offset of the first occurrence of the smallest item)\n */\nstruct ArgMin\n{\n    /// Boolean min operator, preferring the item having the smaller offset in case of ties\n    template <typename T, typename OffsetT>\n    __host__ __device__ __forceinline__ KeyValuePair<OffsetT, T> operator()(\n        const KeyValuePair<OffsetT, T> &a,\n        const KeyValuePair<OffsetT, T> &b) const\n    {\n// Mooch BUG (device reduce argmax gk110 3.2 million random fp32)\n//        return ((b.value < a.value) || ((a.value == b.value) && (b.key < a.key))) ? b : a;\n\n        if ((b.value < a.value) || ((a.value == b.value) && (b.key < a.key)))\n            return b;\n        return a;\n    }\n};\n\n\n/**\n * \\brief Default cast functor\n */\ntemplate <typename B>\nstruct CastOp\n{\n    /// Cast operator, returns <tt>(B) a</tt>\n    template <typename A>\n    __host__ __device__ __forceinline__ B operator()(const A &a) const\n    {\n        return (B) a;\n    }\n};\n\n\n/**\n * \\brief Binary operator wrapper for switching non-commutative scan arguments\n */\ntemplate <typename ScanOp>\nclass SwizzleScanOp\n{\nprivate:\n\n    /// Wrapped scan operator\n    ScanOp scan_op;\n\npublic:\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    SwizzleScanOp(ScanOp scan_op) : scan_op(scan_op) {}\n\n    /// Switch the scan arguments\n    template <typename T>\n    __host__ __device__ __forceinline__\n    T operator()(const T &a, const T &b)\n    {\n      T _a(a);\n      T _b(b);\n\n      return scan_op(_b, _a);\n    }\n};\n\n\n/**\n * \\brief Reduce-by-segment functor.\n *\n * Given two cub::KeyValuePair inputs \\p a and \\p b and a\n * binary associative combining operator \\p <tt>f(const T &x, const T &y)</tt>,\n * an instance of this functor returns a cub::KeyValuePair whose \\p key\n * field is <tt>a.key</tt> + <tt>b.key</tt>, and whose \\p value field\n * is either b.value if b.key is non-zero, or f(a.value, b.value) otherwise.\n *\n * ReduceBySegmentOp is an associative, non-commutative binary combining operator\n * for input sequences of cub::KeyValuePair pairings.  Such\n * sequences are typically used to represent a segmented set of values to be reduced\n * and a corresponding set of {0,1}-valued integer \"head flags\" demarcating the\n * first value of each segment.\n *\n */\ntemplate <typename ReductionOpT>    ///< Binary reduction operator to apply to values\nstruct ReduceBySegmentOp\n{\n    /// Wrapped reduction operator\n    ReductionOpT op;\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ReduceBySegmentOp() {}\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ReduceBySegmentOp(ReductionOpT op) : op(op) {}\n\n    /// Scan operator\n    template <typename KeyValuePairT>       ///< KeyValuePair pairing of T (value) and OffsetT (head flag)\n    __host__ __device__ __forceinline__ KeyValuePairT operator()(\n        const KeyValuePairT &first,         ///< First partial reduction\n        const KeyValuePairT &second)        ///< Second partial reduction\n    {\n        KeyValuePairT retval;\n        retval.key = first.key + second.key;\n        retval.value = (second.key) ?\n                second.value :                          // The second partial reduction spans a segment reset, so it's value aggregate becomes the running aggregate\n                op(first.value, second.value);          // The second partial reduction does not span a reset, so accumulate both into the running aggregate\n        return retval;\n    }\n};\n\n\n\ntemplate <typename ReductionOpT>    ///< Binary reduction operator to apply to values\nstruct ReduceByKeyOp\n{\n    /// Wrapped reduction operator\n    ReductionOpT op;\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ReduceByKeyOp() {}\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ReduceByKeyOp(ReductionOpT op) : op(op) {}\n\n    /// Scan operator\n    template <typename KeyValuePairT>\n    __host__ __device__ __forceinline__ KeyValuePairT operator()(\n        const KeyValuePairT &first,       ///< First partial reduction\n        const KeyValuePairT &second)      ///< Second partial reduction\n    {\n        KeyValuePairT retval = second;\n\n        if (first.key == second.key)\n            retval.value = op(first.value, retval.value);\n\n        return retval;\n    }\n};\n\n\n\n\n\n\n\n/** @} */       // end group UtilModule\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_reduce.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Thread utilities for sequential reduction over statically-sized array types\n */\n\n#pragma once\n\n#include \"../thread/thread_operators.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/// Internal namespace (to prevent ADL mishaps between static functions when mixing different CUB installations)\nnamespace internal {\n\n/**\n * Sequential reduction over statically-sized array types\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ReductionOp>\n__device__ __forceinline__ T ThreadReduce(\n    T*                  input,                  ///< [in] Input array\n    ReductionOp         reduction_op,           ///< [in] Binary reduction operator\n    T                   prefix,                 ///< [in] Prefix to seed reduction with\n    Int2Type<LENGTH>    /*length*/)\n{\n    T retval = prefix;\n\n    #pragma unroll\n    for (int i = 0; i < LENGTH; ++i)\n        retval = reduction_op(retval, input[i]);\n\n    return retval;\n}\n\n\n/**\n * \\brief Perform a sequential reduction over \\p LENGTH elements of the \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     LengthT of input array\n * \\tparam T          <b>[inferred]</b> The data type to be reduced.\n * \\tparam ScanOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ReductionOp>\n__device__ __forceinline__ T ThreadReduce(\n    T*          input,                  ///< [in] Input array\n    ReductionOp reduction_op,           ///< [in] Binary reduction operator\n    T           prefix)                 ///< [in] Prefix to seed reduction with\n{\n    return ThreadReduce(input, reduction_op, prefix, Int2Type<LENGTH>());\n}\n\n\n/**\n * \\brief Perform a sequential reduction over \\p LENGTH elements of the \\p input array.  The aggregate is returned.\n *\n * \\tparam LENGTH     LengthT of input array\n * \\tparam T          <b>[inferred]</b> The data type to be reduced.\n * \\tparam ScanOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ReductionOp>\n__device__ __forceinline__ T ThreadReduce(\n    T*          input,                  ///< [in] Input array\n    ReductionOp reduction_op)           ///< [in] Binary reduction operator\n{\n    T prefix = input[0];\n    return ThreadReduce<LENGTH - 1>(input + 1, reduction_op, prefix);\n}\n\n\n/**\n * \\brief Perform a sequential reduction over the statically-sized \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     <b>[inferred]</b> LengthT of \\p input array\n * \\tparam T          <b>[inferred]</b> The data type to be reduced.\n * \\tparam ScanOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ReductionOp>\n__device__ __forceinline__ T ThreadReduce(\n    T           (&input)[LENGTH],       ///< [in] Input array\n    ReductionOp reduction_op,           ///< [in] Binary reduction operator\n    T           prefix)                 ///< [in] Prefix to seed reduction with\n{\n    return ThreadReduce(input, reduction_op, prefix, Int2Type<LENGTH>());\n}\n\n\n/**\n * \\brief Serial reduction with the specified operator\n *\n * \\tparam LENGTH     <b>[inferred]</b> LengthT of \\p input array\n * \\tparam T          <b>[inferred]</b> The data type to be reduced.\n * \\tparam ScanOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ReductionOp>\n__device__ __forceinline__ T ThreadReduce(\n    T           (&input)[LENGTH],       ///< [in] Input array\n    ReductionOp reduction_op)           ///< [in] Binary reduction operator\n{\n    return ThreadReduce<LENGTH>((T*) input, reduction_op);\n}\n\n\n}               // internal namespace\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_scan.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Thread utilities for sequential prefix scan over statically-sized array types\n */\n\n#pragma once\n\n#include \"../thread/thread_operators.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/// Internal namespace (to prevent ADL mishaps between static functions when mixing different CUB installations)\nnamespace internal {\n\n\n/**\n * \\addtogroup UtilModule\n * @{\n */\n\n/**\n * \\name Sequential prefix scan over statically-sized array types\n * @{\n */\n\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanExclusive(\n    T                   inclusive,\n    T                   exclusive,\n    T                   *input,                 ///< [in] Input array\n    T                   *output,                ///< [out] Output array (may be aliased to \\p input)\n    ScanOp              scan_op,                ///< [in] Binary scan operator\n    Int2Type<LENGTH>    /*length*/)\n{\n    #pragma unroll\n    for (int i = 0; i < LENGTH; ++i)\n    {\n        inclusive = scan_op(exclusive, input[i]);\n        output[i] = exclusive;\n        exclusive = inclusive;\n    }\n\n    return inclusive;\n}\n\n\n\n/**\n * \\brief Perform a sequential exclusive prefix scan over \\p LENGTH elements of the \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanExclusive(\n    T           *input,                 ///< [in] Input array\n    T           *output,                ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op,                ///< [in] Binary scan operator\n    T           prefix,                 ///< [in] Prefix to seed scan with\n    bool        apply_prefix = true)    ///< [in] Whether or not the calling thread should apply its prefix.  If not, the first output element is undefined.  (Handy for preventing thread-0 from applying a prefix.)\n{\n    T inclusive = input[0];\n    if (apply_prefix)\n    {\n        inclusive = scan_op(prefix, inclusive);\n    }\n    output[0] = prefix;\n    T exclusive = inclusive;\n\n    return ThreadScanExclusive(inclusive, exclusive, input + 1, output + 1, scan_op, Int2Type<LENGTH - 1>());\n}\n\n\n/**\n * \\brief Perform a sequential exclusive prefix scan over the statically-sized \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     <b>[inferred]</b> LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanExclusive(\n    T           (&input)[LENGTH],       ///< [in] Input array\n    T           (&output)[LENGTH],      ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op,                ///< [in] Binary scan operator\n    T           prefix,                 ///< [in] Prefix to seed scan with\n    bool        apply_prefix = true)    ///< [in] Whether or not the calling thread should apply its prefix.  (Handy for preventing thread-0 from applying a prefix.)\n{\n    return ThreadScanExclusive<LENGTH>((T*) input, (T*) output, scan_op, prefix, apply_prefix);\n}\n\n\n\n\n\n\n\n\n\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanInclusive(\n    T                   inclusive,\n    T                   *input,                 ///< [in] Input array\n    T                   *output,                ///< [out] Output array (may be aliased to \\p input)\n    ScanOp              scan_op,                ///< [in] Binary scan operator\n    Int2Type<LENGTH>    /*length*/)\n{\n    #pragma unroll\n    for (int i = 0; i < LENGTH; ++i)\n    {\n        inclusive = scan_op(inclusive, input[i]);\n        output[i] = inclusive;\n    }\n\n    return inclusive;\n}\n\n\n/**\n * \\brief Perform a sequential inclusive prefix scan over \\p LENGTH elements of the \\p input array.  The aggregate is returned.\n *\n * \\tparam LENGTH     LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanInclusive(\n    T           *input,                 ///< [in] Input array\n    T           *output,                ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op)                ///< [in] Binary scan operator\n{\n    T inclusive = input[0];\n    output[0] = inclusive;\n\n    // Continue scan\n    return ThreadScanInclusive(inclusive, input + 1, output + 1, scan_op, Int2Type<LENGTH - 1>());\n}\n\n\n/**\n * \\brief Perform a sequential inclusive prefix scan over the statically-sized \\p input array.  The aggregate is returned.\n *\n * \\tparam LENGTH     <b>[inferred]</b> LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanInclusive(\n    T           (&input)[LENGTH],       ///< [in] Input array\n    T           (&output)[LENGTH],      ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op)                ///< [in] Binary scan operator\n{\n    return ThreadScanInclusive<LENGTH>((T*) input, (T*) output, scan_op);\n}\n\n\n/**\n * \\brief Perform a sequential inclusive prefix scan over \\p LENGTH elements of the \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanInclusive(\n    T           *input,                 ///< [in] Input array\n    T           *output,                ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op,                ///< [in] Binary scan operator\n    T           prefix,                 ///< [in] Prefix to seed scan with\n    bool        apply_prefix = true)    ///< [in] Whether or not the calling thread should apply its prefix.  (Handy for preventing thread-0 from applying a prefix.)\n{\n    T inclusive = input[0];\n    if (apply_prefix)\n    {\n        inclusive = scan_op(prefix, inclusive);\n    }\n    output[0] = inclusive;\n\n    // Continue scan\n    return ThreadScanInclusive(inclusive, input + 1, output + 1, scan_op, Int2Type<LENGTH - 1>());\n}\n\n\n/**\n * \\brief Perform a sequential inclusive prefix scan over the statically-sized \\p input array, seeded with the specified \\p prefix.  The aggregate is returned.\n *\n * \\tparam LENGTH     <b>[inferred]</b> LengthT of \\p input and \\p output arrays\n * \\tparam T          <b>[inferred]</b> The data type to be scanned.\n * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n */\ntemplate <\n    int         LENGTH,\n    typename    T,\n    typename    ScanOp>\n__device__ __forceinline__ T ThreadScanInclusive(\n    T           (&input)[LENGTH],       ///< [in] Input array\n    T           (&output)[LENGTH],      ///< [out] Output array (may be aliased to \\p input)\n    ScanOp      scan_op,                ///< [in] Binary scan operator\n    T           prefix,                 ///< [in] Prefix to seed scan with\n    bool        apply_prefix = true)    ///< [in] Whether or not the calling thread should apply its prefix.  (Handy for preventing thread-0 from applying a prefix.)\n{\n    return ThreadScanInclusive<LENGTH>((T*) input, (T*) output, scan_op, prefix, apply_prefix);\n}\n\n\n//@}  end member group\n\n/** @} */       // end group UtilModule\n\n\n}               // internal namespace\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_search.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Thread utilities for sequential search\n */\n\n#pragma once\n\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * Computes the begin offsets into A and B for the specific diagonal\n */\ntemplate <\n    typename AIteratorT,\n    typename BIteratorT,\n    typename OffsetT,\n    typename CoordinateT>\n__host__ __device__ __forceinline__ void MergePathSearch(\n    OffsetT         diagonal,\n    AIteratorT      a,\n    BIteratorT      b,\n    OffsetT         a_len,\n    OffsetT         b_len,\n    CoordinateT&    path_coordinate)\n{\n    /// The value type of the input iterator\n    typedef typename std::iterator_traits<AIteratorT>::value_type T;\n\n    OffsetT split_min = CUB_MAX(diagonal - b_len, 0);\n    OffsetT split_max = CUB_MIN(diagonal, a_len);\n\n    while (split_min < split_max)\n    {\n        OffsetT split_pivot = (split_min + split_max) >> 1;\n        if (a[split_pivot] <= b[diagonal - split_pivot - 1])\n        {\n            // Move candidate split range up A, down B\n            split_min = split_pivot + 1;\n        }\n        else\n        {\n            // Move candidate split range up B, down A\n            split_max = split_pivot;\n        }\n    }\n\n    path_coordinate.x = CUB_MIN(split_min, a_len);\n    path_coordinate.y = diagonal - split_min;\n}\n\n\n\n/**\n * \\brief Returns the offset of the first value within \\p input which does not compare less than \\p val\n */\ntemplate <\n    typename InputIteratorT,\n    typename OffsetT,\n    typename T>\n__device__ __forceinline__ OffsetT LowerBound(\n    InputIteratorT      input,              ///< [in] Input sequence\n    OffsetT             num_items,          ///< [in] Input sequence length\n    T                   val)                ///< [in] Search key\n{\n    OffsetT retval = 0;\n    while (num_items > 0)\n    {\n        OffsetT half = num_items >> 1;\n        if (input[retval + half] < val)\n        {\n            retval = retval + (half + 1);\n            num_items = num_items - (half + 1);\n        }\n        else\n        {\n            num_items = half;\n        }\n    }\n\n    return retval;\n}\n\n\n/**\n * \\brief Returns the offset of the first value within \\p input which compares greater than \\p val\n */\ntemplate <\n    typename InputIteratorT,\n    typename OffsetT,\n    typename T>\n__device__ __forceinline__ OffsetT UpperBound(\n    InputIteratorT      input,              ///< [in] Input sequence\n    OffsetT             num_items,          ///< [in] Input sequence length\n    T                   val)                ///< [in] Search key\n{\n    OffsetT retval = 0;\n    while (num_items > 0)\n    {\n        OffsetT half = num_items >> 1;\n        if (val < input[retval + half])\n        {\n            num_items = half;\n        }\n        else\n        {\n            retval = retval + (half + 1);\n            num_items = num_items - (half + 1);\n        }\n    }\n\n    return retval;\n}\n\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/thread/thread_store.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Thread utilities for writing memory using PTX cache modifiers.\n */\n\n#pragma once\n\n#include <cuda.h>\n\n#include \"../util_ptx.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup UtilIo\n * @{\n */\n\n\n//-----------------------------------------------------------------------------\n// Tags and constants\n//-----------------------------------------------------------------------------\n\n/**\n * \\brief Enumeration of cache modifiers for memory store operations.\n */\nenum CacheStoreModifier\n{\n    STORE_DEFAULT,              ///< Default (no modifier)\n    STORE_WB,                   ///< Cache write-back all coherent levels\n    STORE_CG,                   ///< Cache at global level\n    STORE_CS,                   ///< Cache streaming (likely to be accessed once)\n    STORE_WT,                   ///< Cache write-through (to system memory)\n    STORE_VOLATILE,             ///< Volatile shared (any memory space)\n};\n\n\n/**\n * \\name Thread I/O (cache modified)\n * @{\n */\n\n/**\n * \\brief Thread utility for writing memory using cub::CacheStoreModifier cache modifiers.  Can be used to store any data type.\n *\n * \\par Example\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/thread/thread_store.cuh>\n *\n * // 32-bit store using cache-global modifier:\n * int *d_out;\n * int val;\n * cub::ThreadStore<cub::STORE_CG>(d_out + threadIdx.x, val);\n *\n * // 16-bit store using default modifier\n * short *d_out;\n * short val;\n * cub::ThreadStore<cub::STORE_DEFAULT>(d_out + threadIdx.x, val);\n *\n * // 256-bit store using write-through modifier\n * double4 *d_out;\n * double4 val;\n * cub::ThreadStore<cub::STORE_WT>(d_out + threadIdx.x, val);\n *\n * // 96-bit store using cache-streaming cache modifier\n * struct TestFoo { bool a; short b; };\n * TestFoo *d_struct;\n * TestFoo val;\n * cub::ThreadStore<cub::STORE_CS>(d_out + threadIdx.x, val);\n * \\endcode\n *\n * \\tparam MODIFIER             <b>[inferred]</b> CacheStoreModifier enumeration\n * \\tparam InputIteratorT       <b>[inferred]</b> Output iterator type \\iterator\n * \\tparam T                    <b>[inferred]</b> Data type of output value\n */\ntemplate <\n    CacheStoreModifier  MODIFIER,\n    typename            OutputIteratorT,\n    typename            T>\n__device__ __forceinline__ void ThreadStore(OutputIteratorT itr, T val);\n\n\n//@}  end member group\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/// Helper structure for templated store iteration (inductive case)\ntemplate <int COUNT, int MAX>\nstruct IterateThreadStore\n{\n    template <CacheStoreModifier MODIFIER, typename T>\n    static __device__ __forceinline__ void Store(T *ptr, T *vals)\n    {\n        ThreadStore<MODIFIER>(ptr + COUNT, vals[COUNT]);\n        IterateThreadStore<COUNT + 1, MAX>::template Store<MODIFIER>(ptr, vals);\n    }\n\n    template <typename OutputIteratorT, typename T>\n    static __device__ __forceinline__ void Dereference(OutputIteratorT ptr, T *vals)\n    {\n        ptr[COUNT] = vals[COUNT];\n        IterateThreadStore<COUNT + 1, MAX>::Dereference(ptr, vals);\n    }\n\n};\n\n/// Helper structure for templated store iteration (termination case)\ntemplate <int MAX>\nstruct IterateThreadStore<MAX, MAX>\n{\n    template <CacheStoreModifier MODIFIER, typename T>\n    static __device__ __forceinline__ void Store(T * /*ptr*/, T * /*vals*/) {}\n\n    template <typename OutputIteratorT, typename T>\n    static __device__ __forceinline__ void Dereference(OutputIteratorT /*ptr*/, T * /*vals*/) {}\n};\n\n\n/**\n * Define a uint4 (16B) ThreadStore specialization for the given Cache load modifier\n */\n#define _CUB_STORE_16(cub_modifier, ptx_modifier)                                            \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, uint4*, uint4>(uint4* ptr, uint4 val)                         \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".v4.u32 [%0], {%1, %2, %3, %4};\" : :               \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"r\"(val.x),                                                                     \\\n            \"r\"(val.y),                                                                     \\\n            \"r\"(val.z),                                                                     \\\n            \"r\"(val.w));                                                                    \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, ulonglong2*, ulonglong2>(ulonglong2* ptr, ulonglong2 val)     \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".v2.u64 [%0], {%1, %2};\" : :                       \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"l\"(val.x),                                                                     \\\n            \"l\"(val.y));                                                                    \\\n    }\n\n\n/**\n * Define a uint2 (8B) ThreadStore specialization for the given Cache load modifier\n */\n#define _CUB_STORE_8(cub_modifier, ptx_modifier)                                             \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, ushort4*, ushort4>(ushort4* ptr, ushort4 val)                 \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".v4.u16 [%0], {%1, %2, %3, %4};\" : :               \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"h\"(val.x),                                                                     \\\n            \"h\"(val.y),                                                                     \\\n            \"h\"(val.z),                                                                     \\\n            \"h\"(val.w));                                                                    \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, uint2*, uint2>(uint2* ptr, uint2 val)                         \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".v2.u32 [%0], {%1, %2};\" : :                       \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"r\"(val.x),                                                                     \\\n            \"r\"(val.y));                                                                    \\\n    }                                                                                       \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, unsigned long long*, unsigned long long>(unsigned long long* ptr, unsigned long long val)     \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".u64 [%0], %1;\" : :                                \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"l\"(val));                                                                      \\\n    }\n\n/**\n * Define a unsigned int (4B) ThreadStore specialization for the given Cache load modifier\n */\n#define _CUB_STORE_4(cub_modifier, ptx_modifier)                                             \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, unsigned int*, unsigned int>(unsigned int* ptr, unsigned int val)                             \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".u32 [%0], %1;\" : :                                \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"r\"(val));                                                                      \\\n    }\n\n\n/**\n * Define a unsigned short (2B) ThreadStore specialization for the given Cache load modifier\n */\n#define _CUB_STORE_2(cub_modifier, ptx_modifier)                                             \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, unsigned short*, unsigned short>(unsigned short* ptr, unsigned short val)                     \\\n    {                                                                                       \\\n        asm volatile (\"st.\"#ptx_modifier\".u16 [%0], %1;\" : :                                \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"h\"(val));                                                                      \\\n    }\n\n\n/**\n * Define a unsigned char (1B) ThreadStore specialization for the given Cache load modifier\n */\n#define _CUB_STORE_1(cub_modifier, ptx_modifier)                                             \\\n    template<>                                                                              \\\n    __device__ __forceinline__ void ThreadStore<cub_modifier, unsigned char*, unsigned char>(unsigned char* ptr, unsigned char val)                         \\\n    {                                                                                       \\\n        asm volatile (                                                                      \\\n        \"{\"                                                                                 \\\n        \"   .reg .u8 datum;\"                                                                \\\n        \"   cvt.u8.u16 datum, %1;\"                                                          \\\n        \"   st.\"#ptx_modifier\".u8 [%0], datum;\"                                             \\\n        \"}\" : :                                                                             \\\n            _CUB_ASM_PTR_(ptr),                                                             \\\n            \"h\"((unsigned short) val));                                                               \\\n    }\n\n/**\n * Define powers-of-two ThreadStore specializations for the given Cache load modifier\n */\n#define _CUB_STORE_ALL(cub_modifier, ptx_modifier)                                           \\\n    _CUB_STORE_16(cub_modifier, ptx_modifier)                                                \\\n    _CUB_STORE_8(cub_modifier, ptx_modifier)                                                 \\\n    _CUB_STORE_4(cub_modifier, ptx_modifier)                                                 \\\n    _CUB_STORE_2(cub_modifier, ptx_modifier)                                                 \\\n    _CUB_STORE_1(cub_modifier, ptx_modifier)                                                 \\\n\n\n/**\n * Define ThreadStore specializations for the various Cache load modifiers\n */\n#if CUB_PTX_ARCH >= 200\n    _CUB_STORE_ALL(STORE_WB, wb)\n    _CUB_STORE_ALL(STORE_CG, cg)\n    _CUB_STORE_ALL(STORE_CS, cs)\n    _CUB_STORE_ALL(STORE_WT, wt)\n#else\n    _CUB_STORE_ALL(STORE_WB, global)\n    _CUB_STORE_ALL(STORE_CG, global)\n    _CUB_STORE_ALL(STORE_CS, global)\n    _CUB_STORE_ALL(STORE_WT, volatile.global)\n#endif\n\n\n// Macro cleanup\n#undef _CUB_STORE_ALL\n#undef _CUB_STORE_1\n#undef _CUB_STORE_2\n#undef _CUB_STORE_4\n#undef _CUB_STORE_8\n#undef _CUB_STORE_16\n\n\n/**\n * ThreadStore definition for STORE_DEFAULT modifier on iterator types\n */\ntemplate <typename OutputIteratorT, typename T>\n__device__ __forceinline__ void ThreadStore(\n    OutputIteratorT             itr,\n    T                           val,\n    Int2Type<STORE_DEFAULT>     /*modifier*/,\n    Int2Type<false>             /*is_pointer*/)\n{\n    *itr = val;\n}\n\n\n/**\n * ThreadStore definition for STORE_DEFAULT modifier on pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ void ThreadStore(\n    T                           *ptr,\n    T                           val,\n    Int2Type<STORE_DEFAULT>     /*modifier*/,\n    Int2Type<true>              /*is_pointer*/)\n{\n    *ptr = val;\n}\n\n\n/**\n * ThreadStore definition for STORE_VOLATILE modifier on primitive pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ void ThreadStoreVolatilePtr(\n    T                           *ptr,\n    T                           val,\n    Int2Type<true>              /*is_primitive*/)\n{\n    *reinterpret_cast<volatile T*>(ptr) = val;\n}\n\n\n/**\n * ThreadStore definition for STORE_VOLATILE modifier on non-primitive pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ void ThreadStoreVolatilePtr(\n    T                           *ptr,\n    T                           val,\n    Int2Type<false>             /*is_primitive*/)\n{\n    // Create a temporary using shuffle-words, then store using volatile-words\n    typedef typename UnitWord<T>::VolatileWord  VolatileWord;  \n    typedef typename UnitWord<T>::ShuffleWord   ShuffleWord;\n\n    const int VOLATILE_MULTIPLE = sizeof(T) / sizeof(VolatileWord);\n    const int SHUFFLE_MULTIPLE  = sizeof(T) / sizeof(ShuffleWord);\n    \n    VolatileWord words[VOLATILE_MULTIPLE];\n\n    #pragma unroll\n    for (int i = 0; i < SHUFFLE_MULTIPLE; ++i)\n        reinterpret_cast<ShuffleWord*>(words)[i] = reinterpret_cast<ShuffleWord*>(&val)[i];\n\n    IterateThreadStore<0, VOLATILE_MULTIPLE>::template Dereference(\n        reinterpret_cast<volatile VolatileWord*>(ptr),\n        words);\n}\n\n\n/**\n * ThreadStore definition for STORE_VOLATILE modifier on pointer types\n */\ntemplate <typename T>\n__device__ __forceinline__ void ThreadStore(\n    T                           *ptr,\n    T                           val,\n    Int2Type<STORE_VOLATILE>    /*modifier*/,\n    Int2Type<true>              /*is_pointer*/)\n{\n    ThreadStoreVolatilePtr(ptr, val, Int2Type<Traits<T>::PRIMITIVE>());\n}\n\n\n/**\n * ThreadStore definition for generic modifiers on pointer types\n */\ntemplate <typename T, int MODIFIER>\n__device__ __forceinline__ void ThreadStore(\n    T                           *ptr,\n    T                           val,\n    Int2Type<MODIFIER>          /*modifier*/,\n    Int2Type<true>              /*is_pointer*/)\n{\n    // Create a temporary using shuffle-words, then store using device-words\n    typedef typename UnitWord<T>::DeviceWord    DeviceWord;  \n    typedef typename UnitWord<T>::ShuffleWord   ShuffleWord;\n\n    const int DEVICE_MULTIPLE   = sizeof(T) / sizeof(DeviceWord);\n    const int SHUFFLE_MULTIPLE  = sizeof(T) / sizeof(ShuffleWord);\n    \n    DeviceWord words[DEVICE_MULTIPLE];\n\n    #pragma unroll\n    for (int i = 0; i < SHUFFLE_MULTIPLE; ++i)\n        reinterpret_cast<ShuffleWord*>(words)[i] = reinterpret_cast<ShuffleWord*>(&val)[i];\n\n    IterateThreadStore<0, DEVICE_MULTIPLE>::template Store<CacheStoreModifier(MODIFIER)>(\n        reinterpret_cast<DeviceWord*>(ptr),\n        words);\n}\n\n\n/**\n * ThreadStore definition for generic modifiers\n */\ntemplate <CacheStoreModifier MODIFIER, typename OutputIteratorT, typename T>\n__device__ __forceinline__ void ThreadStore(OutputIteratorT itr, T val)\n{\n    ThreadStore(\n        itr,\n        val,\n        Int2Type<MODIFIER>(),\n        Int2Type<IsPointer<OutputIteratorT>::VALUE>());\n}\n\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/** @} */       // end group UtilIo\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_allocator.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple caching allocator for device memory allocations. The allocator is\n * thread-safe and capable of managing device allocations on multiple devices.\n ******************************************************************************/\n\n#pragma once\n\n#include \"util_namespace.cuh\"\n#include \"util_debug.cuh\"\n\n#include <set>\n#include <map>\n\n#include \"host/mutex.cuh\"\n#include <math.h>\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilMgmt\n * @{\n */\n\n\n/******************************************************************************\n * CachingDeviceAllocator (host use)\n ******************************************************************************/\n\n/**\n * \\brief A simple caching allocator for device memory allocations.\n *\n * \\par Overview\n * The allocator is thread-safe and stream-safe and is capable of managing cached\n * device allocations on multiple devices.  It behaves as follows:\n *\n * \\par\n * - Allocations from the allocator are associated with an \\p active_stream.  Once freed,\n *   the allocation becomes available immediately for reuse within the \\p active_stream\n *   with which it was associated with during allocation, and it becomes available for\n *   reuse within other streams when all prior work submitted to \\p active_stream has completed.\n * - Allocations are categorized and cached by bin size.  A new allocation request of\n *   a given size will only consider cached allocations within the corresponding bin.\n * - Bin limits progress geometrically in accordance with the growth factor\n *   \\p bin_growth provided during construction.  Unused device allocations within\n *   a larger bin cache are not reused for allocation requests that categorize to\n *   smaller bin sizes.\n * - Allocation requests below (\\p bin_growth ^ \\p min_bin) are rounded up to\n *   (\\p bin_growth ^ \\p min_bin).\n * - Allocations above (\\p bin_growth ^ \\p max_bin) are not rounded up to the nearest\n *   bin and are simply freed when they are deallocated instead of being returned\n *   to a bin-cache.\n * - %If the total storage of cached allocations on a given device will exceed\n *   \\p max_cached_bytes, allocations for that device are simply freed when they are\n *   deallocated instead of being returned to their bin-cache.\n *\n * \\par\n * For example, the default-constructed CachingDeviceAllocator is configured with:\n * - \\p bin_growth          = 8\n * - \\p min_bin             = 3\n * - \\p max_bin             = 7\n * - \\p max_cached_bytes    = 6MB - 1B\n *\n * \\par\n * which delineates five bin-sizes: 512B, 4KB, 32KB, 256KB, and 2MB\n * and sets a maximum of 6,291,455 cached bytes per device\n *\n */\nstruct CachingDeviceAllocator\n{\n\n    //---------------------------------------------------------------------\n    // Constants\n    //---------------------------------------------------------------------\n\n    /// Out-of-bounds bin\n    static const unsigned int INVALID_BIN = (unsigned int) -1;\n\n    /// Invalid size\n    static const size_t INVALID_SIZE = (size_t) -1;\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    /// Invalid device ordinal\n    static const int INVALID_DEVICE_ORDINAL = -1;\n\n    //---------------------------------------------------------------------\n    // Type definitions and helper types\n    //---------------------------------------------------------------------\n\n    /**\n     * Descriptor for device memory allocations\n     */\n    struct BlockDescriptor\n    {\n        void*           d_ptr;              // Device pointer\n        size_t          bytes;              // Size of allocation in bytes\n        unsigned int    bin;                // Bin enumeration\n        int             device;             // device ordinal\n        cudaStream_t    associated_stream;  // Associated associated_stream\n        cudaEvent_t     ready_event;        // Signal when associated stream has run to the point at which this block was freed\n\n        // Constructor (suitable for searching maps for a specific block, given its pointer and device)\n        BlockDescriptor(void *d_ptr, int device) :\n            d_ptr(d_ptr),\n            bytes(0),\n            bin(INVALID_BIN),\n            device(device),\n            associated_stream(0),\n            ready_event(0)\n        {}\n\n        // Constructor (suitable for searching maps for a range of suitable blocks, given a device)\n        BlockDescriptor(int device) :\n            d_ptr(NULL),\n            bytes(0),\n            bin(INVALID_BIN),\n            device(device),\n            associated_stream(0),\n            ready_event(0)\n        {}\n\n        // Comparison functor for comparing device pointers\n        static bool PtrCompare(const BlockDescriptor &a, const BlockDescriptor &b)\n        {\n            if (a.device == b.device)\n                return (a.d_ptr < b.d_ptr);\n            else\n                return (a.device < b.device);\n        }\n\n        // Comparison functor for comparing allocation sizes\n        static bool SizeCompare(const BlockDescriptor &a, const BlockDescriptor &b)\n        {\n            if (a.device == b.device)\n                return (a.bytes < b.bytes);\n            else\n                return (a.device < b.device);\n        }\n    };\n\n    /// BlockDescriptor comparator function interface\n    typedef bool (*Compare)(const BlockDescriptor &, const BlockDescriptor &);\n\n    class TotalBytes {\n    public:\n        size_t free;\n        size_t live;\n        TotalBytes() { free = live = 0; }\n    };\n\n    /// Set type for cached blocks (ordered by size)\n    typedef std::multiset<BlockDescriptor, Compare> CachedBlocks;\n\n    /// Set type for live blocks (ordered by ptr)\n    typedef std::multiset<BlockDescriptor, Compare> BusyBlocks;\n\n    /// Map type of device ordinals to the number of cached bytes cached by each device\n    typedef std::map<int, TotalBytes> GpuCachedBytes;\n\n\n    //---------------------------------------------------------------------\n    // Utility functions\n    //---------------------------------------------------------------------\n\n    /**\n     * Integer pow function for unsigned base and exponent\n     */\n    static unsigned int IntPow(\n        unsigned int base,\n        unsigned int exp)\n    {\n        unsigned int retval = 1;\n        while (exp > 0)\n        {\n            if (exp & 1) {\n                retval = retval * base;        // multiply the result by the current base\n            }\n            base = base * base;                // square the base\n            exp = exp >> 1;                    // divide the exponent in half\n        }\n        return retval;\n    }\n\n\n    /**\n     * Round up to the nearest power-of\n     */\n    void NearestPowerOf(\n        unsigned int    &power,\n        size_t          &rounded_bytes,\n        unsigned int    base,\n        size_t          value)\n    {\n        power = 0;\n        rounded_bytes = 1;\n\n        if (value * base < value)\n        {\n            // Overflow\n            power = sizeof(size_t) * 8;\n            rounded_bytes = size_t(0) - 1;\n            return;\n        }\n\n        while (rounded_bytes < value)\n        {\n            rounded_bytes *= base;\n            power++;\n        }\n    }\n\n\n    //---------------------------------------------------------------------\n    // Fields\n    //---------------------------------------------------------------------\n\n    cub::Mutex      mutex;              /// Mutex for thread-safety\n\n    unsigned int    bin_growth;         /// Geometric growth factor for bin-sizes\n    unsigned int    min_bin;            /// Minimum bin enumeration\n    unsigned int    max_bin;            /// Maximum bin enumeration\n\n    size_t          min_bin_bytes;      /// Minimum bin size\n    size_t          max_bin_bytes;      /// Maximum bin size\n    size_t          max_cached_bytes;   /// Maximum aggregate cached bytes per device\n\n    const bool      skip_cleanup;       /// Whether or not to skip a call to FreeAllCached() when destructor is called.  (The CUDA runtime may have already shut down for statically declared allocators)\n    bool            debug;              /// Whether or not to print (de)allocation events to stdout\n\n    GpuCachedBytes  cached_bytes;       /// Map of device ordinal to aggregate cached bytes on that device\n    CachedBlocks    cached_blocks;      /// Set of cached device allocations available for reuse\n    BusyBlocks      live_blocks;        /// Set of live device allocations currently in use\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n    //---------------------------------------------------------------------\n    // Methods\n    //---------------------------------------------------------------------\n\n    /**\n     * \\brief Constructor.\n     */\n    CachingDeviceAllocator(\n        unsigned int    bin_growth,                             ///< Geometric growth factor for bin-sizes\n        unsigned int    min_bin             = 1,                ///< Minimum bin (default is bin_growth ^ 1)\n        unsigned int    max_bin             = INVALID_BIN,      ///< Maximum bin (default is no max bin)\n        size_t          max_cached_bytes    = INVALID_SIZE,     ///< Maximum aggregate cached bytes per device (default is no limit)\n        bool            skip_cleanup        = false,            ///< Whether or not to skip a call to \\p FreeAllCached() when the destructor is called (default is to deallocate)\n        bool            debug               = false)            ///< Whether or not to print (de)allocation events to stdout (default is no stderr output)\n    :\n        bin_growth(bin_growth),\n        min_bin(min_bin),\n        max_bin(max_bin),\n        min_bin_bytes(IntPow(bin_growth, min_bin)),\n        max_bin_bytes(IntPow(bin_growth, max_bin)),\n        max_cached_bytes(max_cached_bytes),\n        skip_cleanup(skip_cleanup),\n        debug(debug),\n        cached_blocks(BlockDescriptor::SizeCompare),\n        live_blocks(BlockDescriptor::PtrCompare)\n    {}\n\n\n    /**\n     * \\brief Default constructor.\n     *\n     * Configured with:\n     * \\par\n     * - \\p bin_growth          = 8\n     * - \\p min_bin             = 3\n     * - \\p max_bin             = 7\n     * - \\p max_cached_bytes    = (\\p bin_growth ^ \\p max_bin) * 3) - 1 = 6,291,455 bytes\n     *\n     * which delineates five bin-sizes: 512B, 4KB, 32KB, 256KB, and 2MB and\n     * sets a maximum of 6,291,455 cached bytes per device\n     */\n    CachingDeviceAllocator(\n        bool skip_cleanup = false,\n        bool debug = false)\n    :\n        bin_growth(8),\n        min_bin(3),\n        max_bin(7),\n        min_bin_bytes(IntPow(bin_growth, min_bin)),\n        max_bin_bytes(IntPow(bin_growth, max_bin)),\n        max_cached_bytes((max_bin_bytes * 3) - 1),\n        skip_cleanup(skip_cleanup),\n        debug(debug),\n        cached_blocks(BlockDescriptor::SizeCompare),\n        live_blocks(BlockDescriptor::PtrCompare)\n    {}\n\n\n    /**\n     * \\brief Sets the limit on the number bytes this allocator is allowed to cache per device.\n     *\n     * Changing the ceiling of cached bytes does not cause any allocations (in-use or\n     * cached-in-reserve) to be freed.  See \\p FreeAllCached().\n     */\n    cudaError_t SetMaxCachedBytes(\n        size_t max_cached_bytes)\n    {\n        // Lock\n        mutex.Lock();\n\n        if (debug) _CubLog(\"Changing max_cached_bytes (%lld -> %lld)\\n\", (long long) this->max_cached_bytes, (long long) max_cached_bytes);\n\n        this->max_cached_bytes = max_cached_bytes;\n\n        // Unlock\n        mutex.Unlock();\n\n        return cudaSuccess;\n    }\n\n\n    /**\n     * \\brief Provides a suitable allocation of device memory for the given size on the specified device.\n     *\n     * Once freed, the allocation becomes available immediately for reuse within the \\p active_stream\n     * with which it was associated with during allocation, and it becomes available for reuse within other\n     * streams when all prior work submitted to \\p active_stream has completed.\n     */\n    cudaError_t DeviceAllocate(\n        int             device,             ///< [in] Device on which to place the allocation\n        void            **d_ptr,            ///< [out] Reference to pointer to the allocation\n        size_t          bytes,              ///< [in] Minimum number of bytes for the allocation\n        cudaStream_t    active_stream = 0)  ///< [in] The stream to be associated with this allocation\n    {\n        *d_ptr                          = NULL;\n        int entrypoint_device           = INVALID_DEVICE_ORDINAL;\n        cudaError_t error               = cudaSuccess;\n\n        if (device == INVALID_DEVICE_ORDINAL)\n        {\n            if (CubDebug(error = cudaGetDevice(&entrypoint_device))) return error;\n            device = entrypoint_device;\n        }\n\n        // Create a block descriptor for the requested allocation\n        bool found = false;\n        BlockDescriptor search_key(device);\n        search_key.associated_stream = active_stream;\n        NearestPowerOf(search_key.bin, search_key.bytes, bin_growth, bytes);\n\n        if (search_key.bin > max_bin)\n        {\n            // Bin is greater than our maximum bin: allocate the request\n            // exactly and give out-of-bounds bin.  It will not be cached\n            // for reuse when returned.\n            search_key.bin      = INVALID_BIN;\n            search_key.bytes    = bytes;\n        }\n        else\n        {\n            // Search for a suitable cached allocation: lock\n            mutex.Lock();\n\n            if (search_key.bin < min_bin)\n            {\n                // Bin is less than minimum bin: round up\n                search_key.bin      = min_bin;\n                search_key.bytes    = min_bin_bytes;\n            }\n\n            // Iterate through the range of cached blocks on the same device in the same bin\n            CachedBlocks::iterator block_itr = cached_blocks.lower_bound(search_key);\n            while ((block_itr != cached_blocks.end())\n                    && (block_itr->device == device)\n                    && (block_itr->bin == search_key.bin))\n            {\n                // To prevent races with reusing blocks returned by the host but still\n                // in use by the device, only consider cached blocks that are\n                // either (from the active stream) or (from an idle stream)\n                if ((active_stream == block_itr->associated_stream) ||\n                    (cudaEventQuery(block_itr->ready_event) != cudaErrorNotReady))\n                {\n                    // Reuse existing cache block.  Insert into live blocks.\n                    found = true;\n                    search_key = *block_itr;\n                    search_key.associated_stream = active_stream;\n                    live_blocks.insert(search_key);\n\n                    // Remove from free blocks\n                    cached_bytes[device].free -= search_key.bytes;\n                    cached_bytes[device].live += search_key.bytes;\n\n                    if (debug) _CubLog(\"\\tDevice %d reused cached block at %p (%lld bytes) for stream %lld (previously associated with stream %lld).\\n\",\n                        device, search_key.d_ptr, (long long) search_key.bytes, (long long) search_key.associated_stream, (long long)  block_itr->associated_stream);\n\n                    cached_blocks.erase(block_itr);\n\n                    break;\n                }\n                block_itr++;\n            }\n\n            // Done searching: unlock\n            mutex.Unlock();\n        }\n\n        // Allocate the block if necessary\n        if (!found)\n        {\n            // Set runtime's current device to specified device (entrypoint may not be set)\n            if (device != entrypoint_device)\n            {\n                if (CubDebug(error = cudaGetDevice(&entrypoint_device))) return error;\n                if (CubDebug(error = cudaSetDevice(device))) return error;\n            }\n\n            // Attempt to allocate\n            if (CubDebug(error = cudaMalloc(&search_key.d_ptr, search_key.bytes)) == cudaErrorMemoryAllocation)\n            {\n                // The allocation attempt failed: free all cached blocks on device and retry\n                if (debug) _CubLog(\"\\tDevice %d failed to allocate %lld bytes for stream %lld, retrying after freeing cached allocations\",\n                      device, (long long) search_key.bytes, (long long) search_key.associated_stream);\n\n                error = cudaSuccess;    // Reset the error we will return\n                cudaGetLastError();     // Reset CUDART's error\n\n                // Lock\n                mutex.Lock();\n\n                // Iterate the range of free blocks on the same device\n                BlockDescriptor free_key(device);\n                CachedBlocks::iterator block_itr = cached_blocks.lower_bound(free_key);\n\n                while ((block_itr != cached_blocks.end()) && (block_itr->device == device))\n                {\n                    // No need to worry about synchronization with the device: cudaFree is\n                    // blocking and will synchronize across all kernels executing\n                    // on the current device\n\n                    // Free device memory and destroy stream event.\n                    if (CubDebug(error = cudaFree(block_itr->d_ptr))) break;\n                    if (CubDebug(error = cudaEventDestroy(block_itr->ready_event))) break;\n\n                    // Reduce balance and erase entry\n                    cached_bytes[device].free -= block_itr->bytes;\n\n                    if (debug) _CubLog(\"\\tDevice %d freed %lld bytes.\\n\\t\\t  %lld available blocks cached (%lld bytes), %lld live blocks (%lld bytes) outstanding.\\n\",\n                        device, (long long) block_itr->bytes, (long long) cached_blocks.size(), (long long) cached_bytes[device].free, (long long) live_blocks.size(), (long long) cached_bytes[device].live);\n\n                    cached_blocks.erase(block_itr);\n\n                    block_itr++;\n                }\n\n                // Unlock\n                mutex.Unlock();\n\n                // Return under error\n                if (error) return error;\n\n                // Try to allocate again\n                if (CubDebug(error = cudaMalloc(&search_key.d_ptr, search_key.bytes))) return error;\n            }\n\n            // Create ready event\n            if (CubDebug(error = cudaEventCreateWithFlags(&search_key.ready_event, cudaEventDisableTiming)))\n                return error;\n\n            // Insert into live blocks\n            mutex.Lock();\n            live_blocks.insert(search_key);\n            cached_bytes[device].live += search_key.bytes;\n            mutex.Unlock();\n\n            if (debug) _CubLog(\"\\tDevice %d allocated new device block at %p (%lld bytes associated with stream %lld).\\n\",\n                      device, search_key.d_ptr, (long long) search_key.bytes, (long long) search_key.associated_stream);\n\n            // Attempt to revert back to previous device if necessary\n            if ((entrypoint_device != INVALID_DEVICE_ORDINAL) && (entrypoint_device != device))\n            {\n                if (CubDebug(error = cudaSetDevice(entrypoint_device))) return error;\n            }\n        }\n\n        // Copy device pointer to output parameter\n        *d_ptr = search_key.d_ptr;\n\n        if (debug) _CubLog(\"\\t\\t%lld available blocks cached (%lld bytes), %lld live blocks outstanding(%lld bytes).\\n\",\n            (long long) cached_blocks.size(), (long long) cached_bytes[device].free, (long long) live_blocks.size(), (long long) cached_bytes[device].live);\n\n        return error;\n    }\n\n\n    /**\n     * \\brief Provides a suitable allocation of device memory for the given size on the current device.\n     *\n     * Once freed, the allocation becomes available immediately for reuse within the \\p active_stream\n     * with which it was associated with during allocation, and it becomes available for reuse within other\n     * streams when all prior work submitted to \\p active_stream has completed.\n     */\n    cudaError_t DeviceAllocate(\n        void            **d_ptr,            ///< [out] Reference to pointer to the allocation\n        size_t          bytes,              ///< [in] Minimum number of bytes for the allocation\n        cudaStream_t    active_stream = 0)  ///< [in] The stream to be associated with this allocation\n    {\n        return DeviceAllocate(INVALID_DEVICE_ORDINAL, d_ptr, bytes, active_stream);\n    }\n\n\n    /**\n     * \\brief Frees a live allocation of device memory on the specified device, returning it to the allocator.\n     *\n     * Once freed, the allocation becomes available immediately for reuse within the \\p active_stream\n     * with which it was associated with during allocation, and it becomes available for reuse within other\n     * streams when all prior work submitted to \\p active_stream has completed.\n     */\n    cudaError_t DeviceFree(\n        int             device,\n        void*           d_ptr)\n    {\n        int entrypoint_device           = INVALID_DEVICE_ORDINAL;\n        cudaError_t error               = cudaSuccess;\n\n        if (device == INVALID_DEVICE_ORDINAL)\n        {\n            if (CubDebug(error = cudaGetDevice(&entrypoint_device)))\n                return error;\n            device = entrypoint_device;\n        }\n\n        // Lock\n        mutex.Lock();\n\n        // Find corresponding block descriptor\n        bool recached = false;\n        BlockDescriptor search_key(d_ptr, device);\n        BusyBlocks::iterator block_itr = live_blocks.find(search_key);\n        if (block_itr != live_blocks.end())\n        {\n            // Remove from live blocks\n            search_key = *block_itr;\n            live_blocks.erase(block_itr);\n            cached_bytes[device].live -= search_key.bytes;\n\n            // Keep the returned allocation if bin is valid and we won't exceed the max cached threshold\n            if ((search_key.bin != INVALID_BIN) && (cached_bytes[device].free + search_key.bytes <= max_cached_bytes))\n            {\n                // Insert returned allocation into free blocks\n                recached = true;\n                cached_blocks.insert(search_key);\n                cached_bytes[device].free += search_key.bytes;\n\n                if (debug) _CubLog(\"\\tDevice %d returned %lld bytes from associated stream %lld.\\n\\t\\t %lld available blocks cached (%lld bytes), %lld live blocks outstanding. (%lld bytes)\\n\",\n                    device, (long long) search_key.bytes, (long long) search_key.associated_stream, (long long) cached_blocks.size(),\n                    (long long) cached_bytes[device].free, (long long) live_blocks.size(), (long long) cached_bytes[device].live);\n            }\n        }\n\n        // Unlock\n        mutex.Unlock();\n\n        // First set to specified device (entrypoint may not be set)\n        if (device != entrypoint_device)\n        {\n            if (CubDebug(error = cudaGetDevice(&entrypoint_device))) return error;\n            if (CubDebug(error = cudaSetDevice(device))) return error;\n        }\n\n        if (recached)\n        {\n            // Insert the ready event in the associated stream (must have current device set properly)\n            if (CubDebug(error = cudaEventRecord(search_key.ready_event, search_key.associated_stream))) return error;\n        }\n        else\n        {\n            // Free the allocation from the runtime and cleanup the event.\n            if (CubDebug(error = cudaFree(d_ptr))) return error;\n            if (CubDebug(error = cudaEventDestroy(search_key.ready_event))) return error;\n\n            if (debug) _CubLog(\"\\tDevice %d freed %lld bytes from associated stream %lld.\\n\\t\\t  %lld available blocks cached (%lld bytes), %lld live blocks (%lld bytes) outstanding.\\n\",\n                device, (long long) search_key.bytes, (long long) search_key.associated_stream, (long long) cached_blocks.size(), (long long) cached_bytes[device].free, (long long) live_blocks.size(), (long long) cached_bytes[device].live);\n        }\n\n        // Reset device\n        if ((entrypoint_device != INVALID_DEVICE_ORDINAL) && (entrypoint_device != device))\n        {\n            if (CubDebug(error = cudaSetDevice(entrypoint_device))) return error;\n        }\n\n        return error;\n    }\n\n\n    /**\n     * \\brief Frees a live allocation of device memory on the current device, returning it to the allocator.\n     *\n     * Once freed, the allocation becomes available immediately for reuse within the \\p active_stream\n     * with which it was associated with during allocation, and it becomes available for reuse within other\n     * streams when all prior work submitted to \\p active_stream has completed.\n     */\n    cudaError_t DeviceFree(\n        void*           d_ptr)\n    {\n        return DeviceFree(INVALID_DEVICE_ORDINAL, d_ptr);\n    }\n\n\n    /**\n     * \\brief Frees all cached device allocations on all devices\n     */\n    cudaError_t FreeAllCached()\n    {\n        cudaError_t error         = cudaSuccess;\n        int entrypoint_device     = INVALID_DEVICE_ORDINAL;\n        int current_device        = INVALID_DEVICE_ORDINAL;\n\n        mutex.Lock();\n\n        while (!cached_blocks.empty())\n        {\n            // Get first block\n            CachedBlocks::iterator begin = cached_blocks.begin();\n\n            // Get entry-point device ordinal if necessary\n            if (entrypoint_device == INVALID_DEVICE_ORDINAL)\n            {\n                if (CubDebug(error = cudaGetDevice(&entrypoint_device))) break;\n            }\n\n            // Set current device ordinal if necessary\n            if (begin->device != current_device)\n            {\n                if (CubDebug(error = cudaSetDevice(begin->device))) break;\n                current_device = begin->device;\n            }\n\n            // Free device memory\n            if (CubDebug(error = cudaFree(begin->d_ptr))) break;\n            if (CubDebug(error = cudaEventDestroy(begin->ready_event))) break;\n\n            // Reduce balance and erase entry\n            cached_bytes[current_device].free -= begin->bytes;\n\n            if (debug) _CubLog(\"\\tDevice %d freed %lld bytes.\\n\\t\\t  %lld available blocks cached (%lld bytes), %lld live blocks (%lld bytes) outstanding.\\n\",\n                current_device, (long long) begin->bytes, (long long) cached_blocks.size(), (long long) cached_bytes[current_device].free, (long long) live_blocks.size(), (long long) cached_bytes[current_device].live);\n\n            cached_blocks.erase(begin);\n        }\n\n        mutex.Unlock();\n\n        // Attempt to revert back to entry-point device if necessary\n        if (entrypoint_device != INVALID_DEVICE_ORDINAL)\n        {\n            if (CubDebug(error = cudaSetDevice(entrypoint_device))) return error;\n        }\n\n        return error;\n    }\n\n\n    /**\n     * \\brief Destructor\n     */\n    virtual ~CachingDeviceAllocator()\n    {\n        if (!skip_cleanup)\n            FreeAllCached();\n    }\n\n};\n\n\n\n\n/** @} */       // end group UtilMgmt\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_arch.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Static architectural properties by SM version.\n */\n\n#pragma once\n\n#include \"util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n#if (__CUDACC_VER_MAJOR__ >= 9) && !defined(CUB_USE_COOPERATIVE_GROUPS)\n    #define CUB_USE_COOPERATIVE_GROUPS\n#endif\n\n/// CUB_PTX_ARCH reflects the PTX version targeted by the active compiler pass (or zero during the host pass).\n#ifndef CUB_PTX_ARCH\n    #ifndef __CUDA_ARCH__\n        #define CUB_PTX_ARCH 0\n    #else\n        #define CUB_PTX_ARCH __CUDA_ARCH__\n    #endif\n#endif\n\n\n/// Whether or not the source targeted by the active compiler pass is allowed to  invoke device kernels or methods from the CUDA runtime API.\n#ifndef CUB_RUNTIME_FUNCTION\n    #if !defined(__CUDA_ARCH__) || (__CUDA_ARCH__>= 350 && defined(__CUDACC_RDC__))\n        #define CUB_RUNTIME_ENABLED\n        #define CUB_RUNTIME_FUNCTION __host__ __device__\n    #else\n        #define CUB_RUNTIME_FUNCTION __host__\n    #endif\n#endif\n\n\n/// Number of threads per warp\n#ifndef CUB_LOG_WARP_THREADS\n    #define CUB_LOG_WARP_THREADS(arch)                      \\\n        (5)\n    #define CUB_WARP_THREADS(arch)                          \\\n        (1 << CUB_LOG_WARP_THREADS(arch))\n\n    #define CUB_PTX_WARP_THREADS        CUB_WARP_THREADS(CUB_PTX_ARCH)\n    #define CUB_PTX_LOG_WARP_THREADS    CUB_LOG_WARP_THREADS(CUB_PTX_ARCH)\n#endif\n\n\n/// Number of smem banks\n#ifndef CUB_LOG_SMEM_BANKS\n    #define CUB_LOG_SMEM_BANKS(arch)                        \\\n        ((arch >= 200) ?                                    \\\n            (5) :                                           \\\n            (4))\n    #define CUB_SMEM_BANKS(arch)                            \\\n        (1 << CUB_LOG_SMEM_BANKS(arch))\n\n    #define CUB_PTX_LOG_SMEM_BANKS      CUB_LOG_SMEM_BANKS(CUB_PTX_ARCH)\n    #define CUB_PTX_SMEM_BANKS          CUB_SMEM_BANKS(CUB_PTX_ARCH)\n#endif\n\n\n/// Oversubscription factor\n#ifndef CUB_SUBSCRIPTION_FACTOR\n    #define CUB_SUBSCRIPTION_FACTOR(arch)                   \\\n        ((arch >= 300) ?                                    \\\n            (5) :                                           \\\n            ((arch >= 200) ?                                \\\n                (3) :                                       \\\n                (10)))\n    #define CUB_PTX_SUBSCRIPTION_FACTOR             CUB_SUBSCRIPTION_FACTOR(CUB_PTX_ARCH)\n#endif\n\n\n/// Prefer padding overhead vs X-way conflicts greater than this threshold\n#ifndef CUB_PREFER_CONFLICT_OVER_PADDING\n    #define CUB_PREFER_CONFLICT_OVER_PADDING(arch)          \\\n        ((arch >= 300) ?                                    \\\n            (1) :                                           \\\n            (4))\n    #define CUB_PTX_PREFER_CONFLICT_OVER_PADDING    CUB_PREFER_CONFLICT_OVER_PADDING(CUB_PTX_ARCH)\n#endif\n\n\n/// Scale down the number of warps to keep same amount of \"tile\" storage as the nominal configuration for 4B data.  Minimum of two warps.\n#ifndef CUB_BLOCK_THREADS\n    #define CUB_BLOCK_THREADS(NOMINAL_4B_BLOCK_THREADS, T, PTX_ARCH)                        \\\n        (CUB_MIN(                                                                           \\\n            NOMINAL_4B_BLOCK_THREADS * 2,                                                   \\\n            CUB_WARP_THREADS(PTX_ARCH) * CUB_MAX(                                           \\\n                (NOMINAL_4B_BLOCK_THREADS / CUB_WARP_THREADS(PTX_ARCH)) * 3 / 4,            \\\n                (NOMINAL_4B_BLOCK_THREADS / CUB_WARP_THREADS(PTX_ARCH)) * 4 / sizeof(T))))\n#endif\n\n/// Scale up/down number of items per thread to keep the same amount of \"tile\" storage as the nominal configuration for 4B data.  Minimum 1 item per thread\n#ifndef CUB_ITEMS_PER_THREAD\n    #define CUB_ITEMS_PER_THREAD(NOMINAL_4B_ITEMS_PER_THREAD, NOMINAL_4B_BLOCK_THREADS, T, PTX_ARCH)    \\\n\t    (CUB_MIN(                                                                                       \\\n\t        NOMINAL_4B_ITEMS_PER_THREAD * 2,                                                            \\\n\t        CUB_MAX(                                                                                    \\\n\t            1,                                                                                      \\\n\t            (NOMINAL_4B_ITEMS_PER_THREAD * NOMINAL_4B_BLOCK_THREADS * 4 / sizeof(T)) / CUB_BLOCK_THREADS(NOMINAL_4B_BLOCK_THREADS, T, PTX_ARCH))))\n#endif\n\n/// Define both nominal threads-per-block and items-per-thread\n#ifndef CUB_NOMINAL_CONFIG\n    #define CUB_NOMINAL_CONFIG(NOMINAL_4B_BLOCK_THREADS, NOMINAL_4B_ITEMS_PER_THREAD, T)    \\\n        CUB_BLOCK_THREADS(NOMINAL_4B_BLOCK_THREADS, T, 200),                                \\\n        CUB_ITEMS_PER_THREAD(NOMINAL_4B_ITEMS_PER_THREAD, NOMINAL_4B_BLOCK_THREADS, T, 200)\n#endif\n\n\n\n#endif  // Do not document\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_debug.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Error and event logging routines.\n *\n * The following macros definitions are supported:\n * - \\p CUB_LOG.  Simple event messages are printed to \\p stdout.\n */\n\n#pragma once\n\n#include <stdio.h>\n#include \"util_namespace.cuh\"\n#include \"util_arch.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilMgmt\n * @{\n */\n\n\n/// CUB error reporting macro (prints error messages to stderr)\n#if (defined(DEBUG) || defined(_DEBUG)) && !defined(CUB_STDERR)\n    #define CUB_STDERR\n#endif\n\n\n\n/**\n * \\brief %If \\p CUB_STDERR is defined and \\p error is not \\p cudaSuccess, the corresponding error message is printed to \\p stderr (or \\p stdout in device code) along with the supplied source context.\n *\n * \\return The CUDA error.\n */\n__host__ __device__ __forceinline__ cudaError_t Debug(\n    cudaError_t     error,\n    const char*     filename,\n    int             line)\n{\n    (void)filename;\n    (void)line;\n#ifdef CUB_STDERR\n    if (error)\n    {\n    #if (CUB_PTX_ARCH == 0)\n        fprintf(stderr, \"CUDA error %d [%s, %d]: %s\\n\", error, filename, line, cudaGetErrorString(error));\n        fflush(stderr);\n    #elif (CUB_PTX_ARCH >= 200)\n        printf(\"CUDA error %d [block (%d,%d,%d) thread (%d,%d,%d), %s, %d]\\n\", error, blockIdx.z, blockIdx.y, blockIdx.x, threadIdx.z, threadIdx.y, threadIdx.x, filename, line);\n    #endif\n    }\n#endif\n    return error;\n}\n\n\n/**\n * \\brief Debug macro\n */\n#ifndef CubDebug\n    #define CubDebug(e) cub::Debug((cudaError_t) (e), __FILE__, __LINE__)\n#endif\n\n\n/**\n * \\brief Debug macro with exit\n */\n#ifndef CubDebugExit\n    #define CubDebugExit(e) if (cub::Debug((cudaError_t) (e), __FILE__, __LINE__)) { exit(1); }\n#endif\n\n\n/**\n * \\brief Log macro for printf statements.\n */\n#if !defined(_CubLog)\n    #if !(defined(__clang__) && defined(__CUDA__))\n        #if (CUB_PTX_ARCH == 0)\n            #define _CubLog(format, ...) printf(format,__VA_ARGS__);\n        #elif (CUB_PTX_ARCH >= 200)\n            #define _CubLog(format, ...) printf(\"[block (%d,%d,%d), thread (%d,%d,%d)]: \" format, blockIdx.z, blockIdx.y, blockIdx.x, threadIdx.z, threadIdx.y, threadIdx.x, __VA_ARGS__);\n        #endif\n    #else\n        // XXX shameless hack for clang around variadic printf...\n        //     Compilies w/o supplying -std=c++11 but shows warning,\n        //     so we sielence them :)\n        #pragma clang diagnostic ignored \"-Wc++11-extensions\"\n        #pragma clang diagnostic ignored \"-Wunnamed-type-template-args\"\n            template <class... Args>\n            inline __host__ __device__ void va_printf(char const* format, Args const&... args)\n            {\n        #ifdef __CUDA_ARCH__\n              printf(format, blockIdx.z, blockIdx.y, blockIdx.x, threadIdx.z, threadIdx.y, threadIdx.x, args...);\n        #else\n              printf(format, args...);\n        #endif\n            }\n        #ifndef __CUDA_ARCH__\n            #define _CubLog(format, ...) va_printf(format,__VA_ARGS__);\n        #else\n            #define _CubLog(format, ...) va_printf(\"[block (%d,%d,%d), thread (%d,%d,%d)]: \" format, __VA_ARGS__);\n        #endif\n    #endif\n#endif\n\n\n\n\n/** @} */       // end group UtilMgmt\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_device.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Properties of a given CUDA device and the corresponding PTX bundle\n */\n\n#pragma once\n\n#include \"util_type.cuh\"\n#include \"util_arch.cuh\"\n#include \"util_debug.cuh\"\n#include \"util_namespace.cuh\"\n#include \"util_macro.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilMgmt\n * @{\n */\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/**\n * Alias temporaries to externally-allocated device storage (or simply return the amount of storage needed).\n */\ntemplate <int ALLOCATIONS>\n__host__ __device__ __forceinline__\ncudaError_t AliasTemporaries(\n    void    *d_temp_storage,                    ///< [in] %Device-accessible allocation of temporary storage.  When NULL, the required allocation size is written to \\p temp_storage_bytes and no work is done.\n    size_t  &temp_storage_bytes,                ///< [in,out] Size in bytes of \\t d_temp_storage allocation\n    void*   (&allocations)[ALLOCATIONS],        ///< [in,out] Pointers to device allocations needed\n    size_t  (&allocation_sizes)[ALLOCATIONS])   ///< [in] Sizes in bytes of device allocations needed\n{\n    const int ALIGN_BYTES   = 256;\n    const int ALIGN_MASK    = ~(ALIGN_BYTES - 1);\n\n    // Compute exclusive prefix sum over allocation requests\n    size_t allocation_offsets[ALLOCATIONS];\n    size_t bytes_needed = 0;\n    for (int i = 0; i < ALLOCATIONS; ++i)\n    {\n        size_t allocation_bytes = (allocation_sizes[i] + ALIGN_BYTES - 1) & ALIGN_MASK;\n        allocation_offsets[i] = bytes_needed;\n        bytes_needed += allocation_bytes;\n    }\n    bytes_needed += ALIGN_BYTES - 1;\n\n    // Check if the caller is simply requesting the size of the storage allocation\n    if (!d_temp_storage)\n    {\n        temp_storage_bytes = bytes_needed;\n        return cudaSuccess;\n    }\n\n    // Check if enough storage provided\n    if (temp_storage_bytes < bytes_needed)\n    {\n        return CubDebug(cudaErrorInvalidValue);\n    }\n\n    // Alias\n    d_temp_storage = (void *) ((size_t(d_temp_storage) + ALIGN_BYTES - 1) & ALIGN_MASK);\n    for (int i = 0; i < ALLOCATIONS; ++i)\n    {\n        allocations[i] = static_cast<char*>(d_temp_storage) + allocation_offsets[i];\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Empty kernel for querying PTX manifest metadata (e.g., version) for the current device\n */\ntemplate <typename T>\n__global__ void EmptyKernel(void) { }\n\n\n#endif  // DOXYGEN_SHOULD_SKIP_THIS\n\n/**\n * \\brief Retrieves the PTX version that will be used on the current device (major * 100 + minor * 10)\n */\nCUB_RUNTIME_FUNCTION __forceinline__ cudaError_t PtxVersion(int &ptx_version)\n{\n    struct Dummy\n    {\n        /// Type definition of the EmptyKernel kernel entry point\n        typedef void (*EmptyKernelPtr)();\n\n        /// Force EmptyKernel<void> to be generated if this class is used\n        CUB_RUNTIME_FUNCTION __forceinline__\n        EmptyKernelPtr Empty()\n        {\n            return EmptyKernel<void>;\n        }\n    };\n\n\n#ifndef CUB_RUNTIME_ENABLED\n    (void)ptx_version;\n\n    // CUDA API calls not supported from this device\n    return cudaErrorInvalidConfiguration;\n\n#elif (CUB_PTX_ARCH > 0)\n\n    ptx_version = CUB_PTX_ARCH;\n    return cudaSuccess;\n\n#else\n\n    cudaError_t error = cudaSuccess;\n    do\n    {\n        cudaFuncAttributes empty_kernel_attrs;\n        if (CubDebug(error = cudaFuncGetAttributes(&empty_kernel_attrs, EmptyKernel<void>))) break;\n        ptx_version = empty_kernel_attrs.ptxVersion * 10;\n    }\n    while (0);\n\n    return error;\n\n#endif\n}\n\n\n/**\n * \\brief Retrieves the SM version (major * 100 + minor * 10)\n */\nCUB_RUNTIME_FUNCTION __forceinline__ cudaError_t SmVersion(int &sm_version, int device_ordinal)\n{\n#ifndef CUB_RUNTIME_ENABLED\n    (void)sm_version;\n    (void)device_ordinal;\n\n    // CUDA API calls not supported from this device\n    return cudaErrorInvalidConfiguration;\n\n#else\n\n    cudaError_t error = cudaSuccess;\n    do\n    {\n        // Fill in SM version\n        int major, minor;\n        if (CubDebug(error = cudaDeviceGetAttribute(&major, cudaDevAttrComputeCapabilityMajor, device_ordinal))) break;\n        if (CubDebug(error = cudaDeviceGetAttribute(&minor, cudaDevAttrComputeCapabilityMinor, device_ordinal))) break;\n        sm_version = major * 100 + minor * 10;\n    }\n    while (0);\n\n    return error;\n\n#endif\n}\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n/**\n * Synchronize the stream if specified\n */\nCUB_RUNTIME_FUNCTION __forceinline__\nstatic cudaError_t SyncStream(cudaStream_t stream)\n{\n#if (CUB_PTX_ARCH == 0)\n    return cudaStreamSynchronize(stream);\n#else\n    (void)stream;\n    // Device can't yet sync on a specific stream\n    return cudaDeviceSynchronize();\n#endif\n}\n\n\n/**\n * \\brief Computes maximum SM occupancy in thread blocks for executing the given kernel function pointer \\p kernel_ptr on the current device with \\p block_threads per thread block.\n *\n * \\par Snippet\n * The code snippet below illustrates the use of the MaxSmOccupancy function.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/util_device.cuh>\n *\n * template <typename T>\n * __global__ void ExampleKernel()\n * {\n *     // Allocate shared memory for BlockScan\n *     __shared__ volatile T buffer[4096];\n *\n *        ...\n * }\n *\n *     ...\n *\n * // Determine SM occupancy for ExampleKernel specialized for unsigned char\n * int max_sm_occupancy;\n * MaxSmOccupancy(max_sm_occupancy, ExampleKernel<unsigned char>, 64);\n *\n * // max_sm_occupancy  <-- 4 on SM10\n * // max_sm_occupancy  <-- 8 on SM20\n * // max_sm_occupancy  <-- 12 on SM35\n *\n * \\endcode\n *\n */\ntemplate <typename KernelPtr>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t MaxSmOccupancy(\n    int                 &max_sm_occupancy,          ///< [out] maximum number of thread blocks that can reside on a single SM\n    KernelPtr           kernel_ptr,                 ///< [in] Kernel pointer for which to compute SM occupancy\n    int                 block_threads,              ///< [in] Number of threads per thread block\n    int                 dynamic_smem_bytes = 0)\n{\n#ifndef CUB_RUNTIME_ENABLED\n    (void)dynamic_smem_bytes;\n    (void)block_threads;\n    (void)kernel_ptr;\n    (void)max_sm_occupancy;\n\n    // CUDA API calls not supported from this device\n    return CubDebug(cudaErrorInvalidConfiguration);\n\n#else\n\n    return cudaOccupancyMaxActiveBlocksPerMultiprocessor (\n        &max_sm_occupancy,\n        kernel_ptr,\n        block_threads,\n        dynamic_smem_bytes);\n\n#endif  // CUB_RUNTIME_ENABLED\n}\n\n\n/******************************************************************************\n * Policy management\n ******************************************************************************/\n\n/**\n * Kernel dispatch configuration\n */\nstruct KernelConfig\n{\n    int block_threads;\n    int items_per_thread;\n    int tile_size;\n    int sm_occupancy;\n\n    CUB_RUNTIME_FUNCTION __forceinline__\n    KernelConfig() : block_threads(0), items_per_thread(0), tile_size(0), sm_occupancy(0) {}\n\n    template <typename AgentPolicyT, typename KernelPtrT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    cudaError_t Init(KernelPtrT kernel_ptr)\n    {\n        block_threads        = AgentPolicyT::BLOCK_THREADS;\n        items_per_thread     = AgentPolicyT::ITEMS_PER_THREAD;\n        tile_size            = block_threads * items_per_thread;\n        cudaError_t retval   = MaxSmOccupancy(sm_occupancy, kernel_ptr, block_threads);\n        return retval;\n    }\n};\n\n\n\n/// Helper for dispatching into a policy chain\ntemplate <int PTX_VERSION, typename PolicyT, typename PrevPolicyT>\nstruct ChainedPolicy\n{\n   /// The policy for the active compiler pass\n   typedef typename If<(CUB_PTX_ARCH < PTX_VERSION), typename PrevPolicyT::ActivePolicy, PolicyT>::Type ActivePolicy;\n\n   /// Specializes and dispatches op in accordance to the first policy in the chain of adequate PTX version\n   template <typename FunctorT>\n   CUB_RUNTIME_FUNCTION __forceinline__\n   static cudaError_t Invoke(int ptx_version, FunctorT &op)\n   {\n       if (ptx_version < PTX_VERSION) {\n           return PrevPolicyT::Invoke(ptx_version, op);\n       }\n       return op.template Invoke<PolicyT>();\n   }\n};\n\n/// Helper for dispatching into a policy chain (end-of-chain specialization)\ntemplate <int PTX_VERSION, typename PolicyT>\nstruct ChainedPolicy<PTX_VERSION, PolicyT, PolicyT>\n{\n    /// The policy for the active compiler pass\n    typedef PolicyT ActivePolicy;\n\n    /// Specializes and dispatches op in accordance to the first policy in the chain of adequate PTX version\n    template <typename FunctorT>\n    CUB_RUNTIME_FUNCTION __forceinline__\n    static cudaError_t Invoke(int /*ptx_version*/, FunctorT &op) {\n        return op.template Invoke<PolicyT>();\n    }\n};\n\n\n\n\n#endif  // Do not document\n\n\n\n\n/** @} */       // end group UtilMgmt\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_macro.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Common C/C++ macro utilities\n ******************************************************************************/\n\n#pragma once\n\n#include \"util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilModule\n * @{\n */\n\n#ifndef CUB_ALIGN\n    #if defined(_WIN32) || defined(_WIN64)\n        /// Align struct\n        #define CUB_ALIGN(bytes) __declspec(align(32))\n    #else\n        /// Align struct\n        #define CUB_ALIGN(bytes) __attribute__((aligned(bytes)))\n    #endif\n#endif\n\n#ifndef CUB_MAX\n    /// Select maximum(a, b)\n    #define CUB_MAX(a, b) (((b) > (a)) ? (b) : (a))\n#endif\n\n#ifndef CUB_MIN\n    /// Select minimum(a, b)\n    #define CUB_MIN(a, b) (((b) < (a)) ? (b) : (a))\n#endif\n\n#ifndef CUB_QUOTIENT_FLOOR\n    /// Quotient of x/y rounded down to nearest integer\n    #define CUB_QUOTIENT_FLOOR(x, y) ((x) / (y))\n#endif\n\n#ifndef CUB_QUOTIENT_CEILING\n    /// Quotient of x/y rounded up to nearest integer\n    #define CUB_QUOTIENT_CEILING(x, y) (((x) + (y) - 1) / (y))\n#endif\n\n#ifndef CUB_ROUND_UP_NEAREST\n    /// x rounded up to the nearest multiple of y\n    #define CUB_ROUND_UP_NEAREST(x, y) ((((x) + (y) - 1) / (y)) * y)\n#endif\n\n#ifndef CUB_ROUND_DOWN_NEAREST\n    /// x rounded down to the nearest multiple of y\n    #define CUB_ROUND_DOWN_NEAREST(x, y) (((x) / (y)) * y)\n#endif\n\n\n#ifndef CUB_STATIC_ASSERT\n    #ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n        #define CUB_CAT_(a, b) a ## b\n        #define CUB_CAT(a, b) CUB_CAT_(a, b)\n    #endif // DOXYGEN_SHOULD_SKIP_THIS\n\n    /// Static assert\n    #define CUB_STATIC_ASSERT(cond, msg) typedef int CUB_CAT(cub_static_assert, __LINE__)[(cond) ? 1 : -1]\n#endif\n\n/** @} */       // end group UtilModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_namespace.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Place-holder for prefixing the cub namespace\n */\n\n#pragma once\n\n// For example:\n//#define CUB_NS_PREFIX namespace thrust{ namespace detail {\n//#define CUB_NS_POSTFIX } }\n\n#ifndef CUB_NS_PREFIX\n#define CUB_NS_PREFIX\n#endif\n\n#ifndef CUB_NS_POSTFIX\n#define CUB_NS_POSTFIX\n#endif\n"
  },
  {
    "path": "external/cub/cub/util_ptx.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * PTX intrinsics\n */\n\n\n#pragma once\n\n#include \"util_type.cuh\"\n#include \"util_arch.cuh\"\n#include \"util_namespace.cuh\"\n#include \"util_debug.cuh\"\n\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilPtx\n * @{\n */\n\n\n/******************************************************************************\n * PTX helper macros\n ******************************************************************************/\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n/**\n * Register modifier for pointer-types (for inlining PTX assembly)\n */\n#if defined(_WIN64) || defined(__LP64__)\n    #define __CUB_LP64__ 1\n    // 64-bit register modifier for inlined asm\n    #define _CUB_ASM_PTR_ \"l\"\n    #define _CUB_ASM_PTR_SIZE_ \"u64\"\n#else\n    #define __CUB_LP64__ 0\n    // 32-bit register modifier for inlined asm\n    #define _CUB_ASM_PTR_ \"r\"\n    #define _CUB_ASM_PTR_SIZE_ \"u32\"\n#endif\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/******************************************************************************\n * Inlined PTX intrinsics\n ******************************************************************************/\n\n/**\n * \\brief Shift-right then add.  Returns (\\p x >> \\p shift) + \\p addend.\n */\n__device__ __forceinline__ unsigned int SHR_ADD(\n    unsigned int x,\n    unsigned int shift,\n    unsigned int addend)\n{\n    unsigned int ret;\n#if CUB_PTX_ARCH >= 200\n    asm (\"vshr.u32.u32.u32.clamp.add %0, %1, %2, %3;\" :\n        \"=r\"(ret) : \"r\"(x), \"r\"(shift), \"r\"(addend));\n#else\n    ret = (x >> shift) + addend;\n#endif\n    return ret;\n}\n\n\n/**\n * \\brief Shift-left then add.  Returns (\\p x << \\p shift) + \\p addend.\n */\n__device__ __forceinline__ unsigned int SHL_ADD(\n    unsigned int x,\n    unsigned int shift,\n    unsigned int addend)\n{\n    unsigned int ret;\n#if CUB_PTX_ARCH >= 200\n    asm (\"vshl.u32.u32.u32.clamp.add %0, %1, %2, %3;\" :\n        \"=r\"(ret) : \"r\"(x), \"r\"(shift), \"r\"(addend));\n#else\n    ret = (x << shift) + addend;\n#endif\n    return ret;\n}\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n/**\n * Bitfield-extract.\n */\ntemplate <typename UnsignedBits, int BYTE_LEN>\n__device__ __forceinline__ unsigned int BFE(\n    UnsignedBits            source,\n    unsigned int            bit_start,\n    unsigned int            num_bits,\n    Int2Type<BYTE_LEN>      /*byte_len*/)\n{\n    unsigned int bits;\n#if CUB_PTX_ARCH >= 200\n    asm (\"bfe.u32 %0, %1, %2, %3;\" : \"=r\"(bits) : \"r\"((unsigned int) source), \"r\"(bit_start), \"r\"(num_bits));\n#else\n    const unsigned int MASK = (1 << num_bits) - 1;\n    bits = (source >> bit_start) & MASK;\n#endif\n    return bits;\n}\n\n\n/**\n * Bitfield-extract for 64-bit types.\n */\ntemplate <typename UnsignedBits>\n__device__ __forceinline__ unsigned int BFE(\n    UnsignedBits            source,\n    unsigned int            bit_start,\n    unsigned int            num_bits,\n    Int2Type<8>             /*byte_len*/)\n{\n    const unsigned long long MASK = (1ull << num_bits) - 1;\n    return (source >> bit_start) & MASK;\n}\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n/**\n * \\brief Bitfield-extract.  Extracts \\p num_bits from \\p source starting at bit-offset \\p bit_start.  The input \\p source may be an 8b, 16b, 32b, or 64b unsigned integer type.\n */\ntemplate <typename UnsignedBits>\n__device__ __forceinline__ unsigned int BFE(\n    UnsignedBits source,\n    unsigned int bit_start,\n    unsigned int num_bits)\n{\n    return BFE(source, bit_start, num_bits, Int2Type<sizeof(UnsignedBits)>());\n}\n\n\n/**\n * \\brief Bitfield insert.  Inserts the \\p num_bits least significant bits of \\p y into \\p x at bit-offset \\p bit_start.\n */\n__device__ __forceinline__ void BFI(\n    unsigned int &ret,\n    unsigned int x,\n    unsigned int y,\n    unsigned int bit_start,\n    unsigned int num_bits)\n{\n#if CUB_PTX_ARCH >= 200\n    asm (\"bfi.b32 %0, %1, %2, %3, %4;\" :\n        \"=r\"(ret) : \"r\"(y), \"r\"(x), \"r\"(bit_start), \"r\"(num_bits));\n#else\n    x <<= bit_start;\n    unsigned int MASK_X = ((1 << num_bits) - 1) << bit_start;\n    unsigned int MASK_Y = ~MASK_X;\n    ret = (y & MASK_Y) | (x & MASK_X);\n#endif\n}\n\n\n/**\n * \\brief Three-operand add.  Returns \\p x + \\p y + \\p z.\n */\n__device__ __forceinline__ unsigned int IADD3(unsigned int x, unsigned int y, unsigned int z)\n{\n#if CUB_PTX_ARCH >= 200\n    asm (\"vadd.u32.u32.u32.add %0, %1, %2, %3;\" : \"=r\"(x) : \"r\"(x), \"r\"(y), \"r\"(z));\n#else\n    x = x + y + z;\n#endif\n    return x;\n}\n\n\n/**\n * \\brief Byte-permute. Pick four arbitrary bytes from two 32-bit registers, and reassemble them into a 32-bit destination register.  For SM2.0 or later.\n *\n * \\par\n * The bytes in the two source registers \\p a and \\p b are numbered from 0 to 7:\n * {\\p b, \\p a} = {{b7, b6, b5, b4}, {b3, b2, b1, b0}}. For each of the four bytes\n * {b3, b2, b1, b0} selected in the return value, a 4-bit selector is defined within\n * the four lower \"nibbles\" of \\p index: {\\p index } = {n7, n6, n5, n4, n3, n2, n1, n0}\n *\n * \\par Snippet\n * The code snippet below illustrates byte-permute.\n * \\par\n * \\code\n * #include <cub/cub.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     int a        = 0x03020100;\n *     int b        = 0x07060504;\n *     int index    = 0x00007531;\n *\n *     int selected = PRMT(a, b, index);    // 0x07050301\n *\n * \\endcode\n *\n */\n__device__ __forceinline__ int PRMT(unsigned int a, unsigned int b, unsigned int index)\n{\n    int ret;\n    asm (\"prmt.b32 %0, %1, %2, %3;\" : \"=r\"(ret) : \"r\"(a), \"r\"(b), \"r\"(index));\n    return ret;\n}\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n/**\n * Sync-threads barrier.\n */\n__device__ __forceinline__ void BAR(int count)\n{\n    asm volatile(\"bar.sync 1, %0;\" : : \"r\"(count));\n}\n\n/**\n * CTA barrier\n */\n__device__  __forceinline__ void CTA_SYNC()\n{\n    __syncthreads();\n}\n\n\n/**\n * CTA barrier with predicate\n */\n__device__  __forceinline__ int CTA_SYNC_AND(int p)\n{\n    return __syncthreads_and(p);\n}\n\n\n/**\n * Warp barrier\n */\n__device__  __forceinline__ void WARP_SYNC(unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    __syncwarp(member_mask);\n#endif\n}\n\n\n/**\n * Warp any\n */\n__device__  __forceinline__ int WARP_ANY(int predicate, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    return __any_sync(member_mask, predicate);\n#else\n    return ::__any(predicate);\n#endif\n}\n\n\n/**\n * Warp any\n */\n__device__  __forceinline__ int WARP_ALL(int predicate, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    return __all_sync(member_mask, predicate);\n#else\n    return ::__all(predicate);\n#endif\n}\n\n\n/**\n * Warp ballot\n */\n__device__  __forceinline__ int WARP_BALLOT(int predicate, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    return __ballot_sync(member_mask, predicate);\n#else\n    return __ballot(predicate);\n#endif\n}\n\n/**\n * Warp synchronous shfl_up\n */\n__device__ __forceinline__ \nunsigned int SHFL_UP_SYNC(unsigned int word, int src_offset, int first_lane, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    asm volatile(\"shfl.sync.up.b32 %0, %1, %2, %3, %4;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_offset), \"r\"(first_lane), \"r\"(member_mask));\n#else\n    asm volatile(\"shfl.up.b32 %0, %1, %2, %3;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_offset), \"r\"(first_lane));\n#endif\n    return word;\n}\n\n/**\n * Warp synchronous shfl_down\n */\n__device__ __forceinline__ \nunsigned int SHFL_DOWN_SYNC(unsigned int word, int src_offset, int last_lane, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    asm volatile(\"shfl.sync.down.b32 %0, %1, %2, %3, %4;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_offset), \"r\"(last_lane), \"r\"(member_mask));\n#else\n    asm volatile(\"shfl.down.b32 %0, %1, %2, %3;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_offset), \"r\"(last_lane));\n#endif\n    return word;\n}\n\n/**\n * Warp synchronous shfl_idx\n */\n__device__ __forceinline__ \nunsigned int SHFL_IDX_SYNC(unsigned int word, int src_lane, int last_lane, unsigned int member_mask)\n{\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n    asm volatile(\"shfl.sync.idx.b32 %0, %1, %2, %3, %4;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_lane), \"r\"(last_lane), \"r\"(member_mask));\n#else\n    asm volatile(\"shfl.idx.b32 %0, %1, %2, %3;\"\n        : \"=r\"(word) : \"r\"(word), \"r\"(src_lane), \"r\"(last_lane));\n#endif\n    return word;\n}\n\n/**\n * Floating point multiply. (Mantissa LSB rounds towards zero.)\n */\n__device__ __forceinline__ float FMUL_RZ(float a, float b)\n{\n    float d;\n    asm (\"mul.rz.f32 %0, %1, %2;\" : \"=f\"(d) : \"f\"(a), \"f\"(b));\n    return d;\n}\n\n\n/**\n * Floating point multiply-add. (Mantissa LSB rounds towards zero.)\n */\n__device__ __forceinline__ float FFMA_RZ(float a, float b, float c)\n{\n    float d;\n    asm (\"fma.rz.f32 %0, %1, %2, %3;\" : \"=f\"(d) : \"f\"(a), \"f\"(b), \"f\"(c));\n    return d;\n}\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n/**\n * \\brief Terminates the calling thread\n */\n__device__ __forceinline__ void ThreadExit() {\n    asm volatile(\"exit;\");\n}    \n\n\n/**\n * \\brief  Abort execution and generate an interrupt to the host CPU\n */\n__device__ __forceinline__ void ThreadTrap() {\n    asm volatile(\"trap;\");\n}\n\n\n/**\n * \\brief Returns the row-major linear thread identifier for a multidimensional thread block\n */\n__device__ __forceinline__ int RowMajorTid(int block_dim_x, int block_dim_y, int block_dim_z)\n{\n    return ((block_dim_z == 1) ? 0 : (threadIdx.z * block_dim_x * block_dim_y)) +\n            ((block_dim_y == 1) ? 0 : (threadIdx.y * block_dim_x)) +\n            threadIdx.x;\n}\n\n\n/**\n * \\brief Returns the warp lane ID of the calling thread\n */\n__device__ __forceinline__ unsigned int LaneId()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%laneid;\" : \"=r\"(ret) );\n    return ret;\n}\n\n\n/**\n * \\brief Returns the warp ID of the calling thread.  Warp ID is guaranteed to be unique among warps, but may not correspond to a zero-based ranking within the thread block.\n */\n__device__ __forceinline__ unsigned int WarpId()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%warpid;\" : \"=r\"(ret) );\n    return ret;\n}\n\n/**\n * \\brief Returns the warp lane mask of all lanes less than the calling thread\n */\n__device__ __forceinline__ unsigned int LaneMaskLt()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%lanemask_lt;\" : \"=r\"(ret) );\n    return ret;\n}\n\n/**\n * \\brief Returns the warp lane mask of all lanes less than or equal to the calling thread\n */\n__device__ __forceinline__ unsigned int LaneMaskLe()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%lanemask_le;\" : \"=r\"(ret) );\n    return ret;\n}\n\n/**\n * \\brief Returns the warp lane mask of all lanes greater than the calling thread\n */\n__device__ __forceinline__ unsigned int LaneMaskGt()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%lanemask_gt;\" : \"=r\"(ret) );\n    return ret;\n}\n\n/**\n * \\brief Returns the warp lane mask of all lanes greater than or equal to the calling thread\n */\n__device__ __forceinline__ unsigned int LaneMaskGe()\n{\n    unsigned int ret;\n    asm (\"mov.u32 %0, %%lanemask_ge;\" : \"=r\"(ret) );\n    return ret;\n}\n\n/** @} */       // end group UtilPtx\n\n\n\n\n/**\n * \\brief Shuffle-up for any data type.  Each <em>warp-lane<sub>i</sub></em> obtains the value \\p input contributed by <em>warp-lane</em><sub><em>i</em>-<tt>src_offset</tt></sub>.  For thread lanes \\e i < src_offset, the thread's own \\p input is returned to the thread. ![](shfl_up_logo.png)\n * \\ingroup WarpModule\n *\n * \\par\n * - Available only for SM3.0 or newer\n *\n * \\par Snippet\n * The code snippet below illustrates each thread obtaining a \\p double value from the\n * predecessor of its predecessor.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/util_ptx.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Obtain one input item per thread\n *     double thread_data = ...\n *\n *     // Obtain item from two ranks below\n *     double peer_data = ShuffleUp(thread_data, 2, 0, 0xffffffff);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the first warp of threads is <tt>{1.0, 2.0, 3.0, 4.0, 5.0, ..., 32.0}</tt>.\n * The corresponding output \\p peer_data will be <tt>{1.0, 2.0, 1.0, 2.0, 3.0, ..., 30.0}</tt>.\n *\n */\ntemplate <typename T>\n__device__ __forceinline__ T ShuffleUp(\n    T               input,              ///< [in] The value to broadcast\n    int             src_offset,         ///< [in] The relative down-offset of the peer to read from\n    int             first_lane,         ///< [in] Index of first lane in segment (typically 0)\n    unsigned int    member_mask)        ///< [in] 32-bit mask of participating warp lanes\n{\n    typedef typename UnitWord<T>::ShuffleWord ShuffleWord;\n\n    const int       WORDS           = (sizeof(T) + sizeof(ShuffleWord) - 1) / sizeof(ShuffleWord);\n \n    T               output;\n    ShuffleWord     *output_alias   = reinterpret_cast<ShuffleWord *>(&output);\n    ShuffleWord     *input_alias    = reinterpret_cast<ShuffleWord *>(&input);\n\n    unsigned int shuffle_word;\n    shuffle_word = SHFL_UP_SYNC((unsigned int)input_alias[0], src_offset, first_lane, member_mask);\n    output_alias[0] = shuffle_word;\n\n    #pragma unroll\n    for (int WORD = 1; WORD < WORDS; ++WORD)\n    {\n        shuffle_word       = SHFL_UP_SYNC((unsigned int)input_alias[WORD], src_offset, first_lane, member_mask);\n        output_alias[WORD] = shuffle_word;\n    }\n\n    return output;\n}\n\n\n/**\n * \\brief Shuffle-down for any data type.  Each <em>warp-lane<sub>i</sub></em> obtains the value \\p input contributed by <em>warp-lane</em><sub><em>i</em>+<tt>src_offset</tt></sub>.  For thread lanes \\e i >= WARP_THREADS, the thread's own \\p input is returned to the thread.  ![](shfl_down_logo.png)\n * \\ingroup WarpModule\n *\n * \\par\n * - Available only for SM3.0 or newer\n *\n * \\par Snippet\n * The code snippet below illustrates each thread obtaining a \\p double value from the\n * successor of its successor.\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/util_ptx.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Obtain one input item per thread\n *     double thread_data = ...\n *\n *     // Obtain item from two ranks below\n *     double peer_data = ShuffleDown(thread_data, 2, 31, 0xffffffff);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the first warp of threads is <tt>{1.0, 2.0, 3.0, 4.0, 5.0, ..., 32.0}</tt>.\n * The corresponding output \\p peer_data will be <tt>{3.0, 4.0, 5.0, 6.0, 7.0, ..., 32.0}</tt>.\n *\n */\ntemplate <typename T>\n__device__ __forceinline__ T ShuffleDown(\n    T               input,              ///< [in] The value to broadcast\n    int             src_offset,         ///< [in] The relative up-offset of the peer to read from\n    int             last_lane,          ///< [in] Index of first lane in segment (typically 31)\n    unsigned int    member_mask)        ///< [in] 32-bit mask of participating warp lanes\n{\n    typedef typename UnitWord<T>::ShuffleWord ShuffleWord;\n\n    const int       WORDS           = (sizeof(T) + sizeof(ShuffleWord) - 1) / sizeof(ShuffleWord);\n\n    T               output;\n    ShuffleWord     *output_alias   = reinterpret_cast<ShuffleWord *>(&output);\n    ShuffleWord     *input_alias    = reinterpret_cast<ShuffleWord *>(&input);\n\n    unsigned int shuffle_word;\n    shuffle_word    = SHFL_DOWN_SYNC((unsigned int)input_alias[0], src_offset, last_lane, member_mask);\n    output_alias[0] = shuffle_word;\n\n    #pragma unroll\n    for (int WORD = 1; WORD < WORDS; ++WORD)\n    {\n        shuffle_word       = SHFL_DOWN_SYNC((unsigned int)input_alias[WORD], src_offset, last_lane, member_mask);\n        output_alias[WORD] = shuffle_word;\n    }\n\n    return output;\n}\n\n\n/**\n * \\brief Shuffle-broadcast for any data type.  Each <em>warp-lane<sub>i</sub></em> obtains the value \\p input\n * contributed by <em>warp-lane</em><sub><tt>src_lane</tt></sub>.  For \\p src_lane < 0 or \\p src_lane >= WARP_THREADS,\n * then the thread's own \\p input is returned to the thread. ![](shfl_broadcast_logo.png)\n *\n * \\ingroup WarpModule\n *\n * \\par\n * - Available only for SM3.0 or newer\n *\n * \\par Snippet\n * The code snippet below illustrates each thread obtaining a \\p double value from <em>warp-lane</em><sub>0</sub>.\n *\n * \\par\n * \\code\n * #include <cub/cub.cuh>   // or equivalently <cub/util_ptx.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Obtain one input item per thread\n *     double thread_data = ...\n *\n *     // Obtain item from thread 0\n *     double peer_data = ShuffleIndex(thread_data, 0, 32, 0xffffffff);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the first warp of threads is <tt>{1.0, 2.0, 3.0, 4.0, 5.0, ..., 32.0}</tt>.\n * The corresponding output \\p peer_data will be <tt>{1.0, 1.0, 1.0, 1.0, 1.0, ..., 1.0}</tt>.\n *\n */\ntemplate <typename T>\n__device__ __forceinline__ T ShuffleIndex(\n    T               input,                  ///< [in] The value to broadcast\n    int             src_lane,               ///< [in] Which warp lane is to do the broadcasting\n    int             logical_warp_threads,   ///< [in] Number of threads per logical warp\n    unsigned int    member_mask)            ///< [in] 32-bit mask of participating warp lanes\n{\n    typedef typename UnitWord<T>::ShuffleWord ShuffleWord;\n\n    const int       WORDS           = (sizeof(T) + sizeof(ShuffleWord) - 1) / sizeof(ShuffleWord);\n\n    T               output;\n    ShuffleWord     *output_alias   = reinterpret_cast<ShuffleWord *>(&output);\n    ShuffleWord     *input_alias    = reinterpret_cast<ShuffleWord *>(&input);\n\n    unsigned int shuffle_word;\n    shuffle_word = SHFL_IDX_SYNC((unsigned int)input_alias[0],\n                                 src_lane,\n                                 logical_warp_threads - 1,\n                                 member_mask);\n\n    output_alias[0] = shuffle_word;\n\n    #pragma unroll\n    for (int WORD = 1; WORD < WORDS; ++WORD)\n    {\n        shuffle_word = SHFL_IDX_SYNC((unsigned int)input_alias[WORD],\n                                     src_lane,\n                                     logical_warp_threads - 1,\n                                     member_mask);\n\n        output_alias[WORD] = shuffle_word;\n    }\n\n    return output;\n}\n\n\n\n/**\n * Compute a 32b mask of threads having the same least-significant\n * LABEL_BITS of \\p label as the calling thread.\n */\ntemplate <int LABEL_BITS>\ninline __device__ unsigned int MatchAny(unsigned int label)\n{\n    unsigned int retval;\n\n    // Extract masks of common threads for each bit\n    #pragma unroll\n    for (int BIT = 0; BIT < LABEL_BITS; ++BIT)\n    {\n        unsigned int mask;\n        unsigned int current_bit = 1 << BIT;\n        asm (\"{\\n\"\n            \"    .reg .pred p;\\n\"\n            \"    and.b32 %0, %1, %2;\"\n            \"    setp.eq.u32 p, %0, %2;\\n\"\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n            \"    vote.ballot.sync.b32 %0, p, 0xffffffff;\\n\"\n#else\n            \"    vote.ballot.b32 %0, p;\\n\"\n#endif\n            \"    @!p not.b32 %0, %0;\\n\"\n            \"}\\n\" : \"=r\"(mask) : \"r\"(label), \"r\"(current_bit));\n\n        // Remove peers who differ\n        retval = (BIT == 0) ? mask : retval & mask;\n    }\n\n    return retval;\n\n//  // VOLTA match\n//    unsigned int retval;\n//    asm (\"{\\n\"\n//         \"    match.any.sync.b32 %0, %1, 0xffffffff;\\n\"\n//         \"}\\n\" : \"=r\"(retval) : \"r\"(label));\n//    return retval;\n\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/util_type.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * Common type manipulation (metaprogramming) utilities\n */\n\n#pragma once\n\n#include <iostream>\n#include <limits>\n#include <cfloat>\n\n#include \"util_macro.cuh\"\n#include \"util_arch.cuh\"\n#include \"util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup UtilModule\n * @{\n */\n\n\n\n/******************************************************************************\n * Type equality\n ******************************************************************************/\n\n/**\n * \\brief Type selection (<tt>IF ? ThenType : ElseType</tt>)\n */\ntemplate <bool IF, typename ThenType, typename ElseType>\nstruct If\n{\n    /// Conditional type result\n    typedef ThenType Type;      // true\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <typename ThenType, typename ElseType>\nstruct If<false, ThenType, ElseType>\n{\n    typedef ElseType Type;      // false\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n/******************************************************************************\n * Conditional types\n ******************************************************************************/\n\n/**\n * \\brief Type equality test\n */\ntemplate <typename A, typename B>\nstruct Equals\n{\n    enum {\n        VALUE = 0,\n        NEGATE = 1\n    };\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <typename A>\nstruct Equals <A, A>\n{\n    enum {\n        VALUE = 1,\n        NEGATE = 0\n    };\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/******************************************************************************\n * Static math\n ******************************************************************************/\n\n/**\n * \\brief Statically determine log2(N), rounded up.\n *\n * For example:\n *     Log2<8>::VALUE   // 3\n *     Log2<3>::VALUE   // 2\n */\ntemplate <int N, int CURRENT_VAL = N, int COUNT = 0>\nstruct Log2\n{\n    /// Static logarithm value\n    enum { VALUE = Log2<N, (CURRENT_VAL >> 1), COUNT + 1>::VALUE };         // Inductive case\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <int N, int COUNT>\nstruct Log2<N, 0, COUNT>\n{\n    enum {VALUE = (1 << (COUNT - 1) < N) ?                                  // Base case\n        COUNT :\n        COUNT - 1 };\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/**\n * \\brief Statically determine if N is a power-of-two\n */\ntemplate <int N>\nstruct PowerOfTwo\n{\n    enum { VALUE = ((N & (N - 1)) == 0) };\n};\n\n\n\n/******************************************************************************\n * Pointer vs. iterator detection\n ******************************************************************************/\n\n/**\n * \\brief Pointer vs. iterator\n */\ntemplate <typename Tp>\nstruct IsPointer\n{\n    enum { VALUE = 0 };\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <typename Tp>\nstruct IsPointer<Tp*>\n{\n    enum { VALUE = 1 };\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n/******************************************************************************\n * Qualifier detection\n ******************************************************************************/\n\n/**\n * \\brief Volatile modifier test\n */\ntemplate <typename Tp>\nstruct IsVolatile\n{\n    enum { VALUE = 0 };\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <typename Tp>\nstruct IsVolatile<Tp volatile>\n{\n    enum { VALUE = 1 };\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/******************************************************************************\n * Qualifier removal\n ******************************************************************************/\n\n/**\n * \\brief Removes \\p const and \\p volatile qualifiers from type \\p Tp.\n *\n * For example:\n *     <tt>typename RemoveQualifiers<volatile int>::Type         // int;</tt>\n */\ntemplate <typename Tp, typename Up = Tp>\nstruct RemoveQualifiers\n{\n    /// Type without \\p const and \\p volatile qualifiers\n    typedef Up Type;\n};\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\ntemplate <typename Tp, typename Up>\nstruct RemoveQualifiers<Tp, volatile Up>\n{\n    typedef Up Type;\n};\n\ntemplate <typename Tp, typename Up>\nstruct RemoveQualifiers<Tp, const Up>\n{\n    typedef Up Type;\n};\n\ntemplate <typename Tp, typename Up>\nstruct RemoveQualifiers<Tp, const volatile Up>\n{\n    typedef Up Type;\n};\n\n\n/******************************************************************************\n * Marker types\n ******************************************************************************/\n\n/**\n * \\brief A simple \"NULL\" marker type\n */\nstruct NullType\n{\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    template <typename T>\n    __host__ __device__ __forceinline__ NullType& operator =(const T&) { return *this; }\n\n    __host__ __device__ __forceinline__ bool operator ==(const NullType&) { return true; }\n\n    __host__ __device__ __forceinline__ bool operator !=(const NullType&) { return false; }\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n};\n\n\n/**\n * \\brief Allows for the treatment of an integral constant as a type at compile-time (e.g., to achieve static call dispatch based on constant integral values)\n */\ntemplate <int A>\nstruct Int2Type\n{\n   enum {VALUE = A};\n};\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/******************************************************************************\n * Size and alignment\n ******************************************************************************/\n\n/// Structure alignment\ntemplate <typename T>\nstruct AlignBytes\n{\n    struct Pad\n    {\n        T       val;\n        char    byte;\n    };\n\n    enum\n    {\n        /// The \"true CUDA\" alignment of T in bytes\n        ALIGN_BYTES = sizeof(Pad) - sizeof(T)\n    };\n\n    /// The \"truly aligned\" type\n    typedef T Type;\n};\n\n// Specializations where host C++ compilers (e.g., 32-bit Windows) may disagree\n// with device C++ compilers (EDG) on types passed as template parameters through\n// kernel functions\n\n#define __CUB_ALIGN_BYTES(t, b)         \\\n    template <> struct AlignBytes<t>    \\\n    { enum { ALIGN_BYTES = b }; typedef __align__(b) t Type; };\n\n__CUB_ALIGN_BYTES(short4, 8)\n__CUB_ALIGN_BYTES(ushort4, 8)\n__CUB_ALIGN_BYTES(int2, 8)\n__CUB_ALIGN_BYTES(uint2, 8)\n__CUB_ALIGN_BYTES(long long, 8)\n__CUB_ALIGN_BYTES(unsigned long long, 8)\n__CUB_ALIGN_BYTES(float2, 8)\n__CUB_ALIGN_BYTES(double, 8)\n#ifdef _WIN32\n    __CUB_ALIGN_BYTES(long2, 8)\n    __CUB_ALIGN_BYTES(ulong2, 8)\n#else\n    __CUB_ALIGN_BYTES(long2, 16)\n    __CUB_ALIGN_BYTES(ulong2, 16)\n#endif\n__CUB_ALIGN_BYTES(int4, 16)\n__CUB_ALIGN_BYTES(uint4, 16)\n__CUB_ALIGN_BYTES(float4, 16)\n__CUB_ALIGN_BYTES(long4, 16)\n__CUB_ALIGN_BYTES(ulong4, 16)\n__CUB_ALIGN_BYTES(longlong2, 16)\n__CUB_ALIGN_BYTES(ulonglong2, 16)\n__CUB_ALIGN_BYTES(double2, 16)\n__CUB_ALIGN_BYTES(longlong4, 16)\n__CUB_ALIGN_BYTES(ulonglong4, 16)\n__CUB_ALIGN_BYTES(double4, 16)\n\ntemplate <typename T> struct AlignBytes<volatile T> : AlignBytes<T> {};\ntemplate <typename T> struct AlignBytes<const T> : AlignBytes<T> {};\ntemplate <typename T> struct AlignBytes<const volatile T> : AlignBytes<T> {};\n\n\n/// Unit-words of data movement\ntemplate <typename T>\nstruct UnitWord\n{\n    enum {\n        ALIGN_BYTES = AlignBytes<T>::ALIGN_BYTES\n    };\n\n    template <typename Unit>\n    struct IsMultiple\n    {\n        enum {\n            UNIT_ALIGN_BYTES    = AlignBytes<Unit>::ALIGN_BYTES,\n            IS_MULTIPLE         = (sizeof(T) % sizeof(Unit) == 0) && (ALIGN_BYTES % UNIT_ALIGN_BYTES == 0)\n        };\n    };\n\n    /// Biggest shuffle word that T is a whole multiple of and is not larger than the alignment of T\n    typedef typename If<IsMultiple<int>::IS_MULTIPLE,\n        unsigned int,\n        typename If<IsMultiple<short>::IS_MULTIPLE,\n            unsigned short,\n            unsigned char>::Type>::Type         ShuffleWord;\n\n    /// Biggest volatile word that T is a whole multiple of and is not larger than the alignment of T\n    typedef typename If<IsMultiple<long long>::IS_MULTIPLE,\n        unsigned long long,\n        ShuffleWord>::Type                      VolatileWord;\n\n    /// Biggest memory-access word that T is a whole multiple of and is not larger than the alignment of T\n    typedef typename If<IsMultiple<longlong2>::IS_MULTIPLE,\n        ulonglong2,\n        VolatileWord>::Type                     DeviceWord;\n\n    /// Biggest texture reference word that T is a whole multiple of and is not larger than the alignment of T\n    typedef typename If<IsMultiple<int4>::IS_MULTIPLE,\n        uint4,\n        typename If<IsMultiple<int2>::IS_MULTIPLE,\n            uint2,\n            ShuffleWord>::Type>::Type           TextureWord;\n};\n\n\n// float2 specialization workaround (for SM10-SM13)\ntemplate <>\nstruct UnitWord <float2>\n{\n    typedef int         ShuffleWord;\n#if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)\n    typedef float       VolatileWord;\n    typedef uint2       DeviceWord;\n#else\n    typedef unsigned long long   VolatileWord;\n    typedef unsigned long long   DeviceWord;\n#endif\n    typedef float2      TextureWord;\n};\n\n// float4 specialization workaround (for SM10-SM13)\ntemplate <>\nstruct UnitWord <float4>\n{\n    typedef int         ShuffleWord;\n#if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)\n    typedef float               VolatileWord;\n    typedef uint4               DeviceWord;\n#else\n    typedef unsigned long long  VolatileWord;\n    typedef ulonglong2          DeviceWord;\n#endif\n    typedef float4              TextureWord;\n};\n\n\n// char2 specialization workaround (for SM10-SM13)\ntemplate <>\nstruct UnitWord <char2>\n{\n    typedef unsigned short      ShuffleWord;\n#if (CUB_PTX_ARCH > 0) && (CUB_PTX_ARCH <= 130)\n    typedef unsigned short      VolatileWord;\n    typedef short               DeviceWord;\n#else\n    typedef unsigned short      VolatileWord;\n    typedef unsigned short      DeviceWord;\n#endif\n    typedef unsigned short      TextureWord;\n};\n\n\ntemplate <typename T> struct UnitWord<volatile T> : UnitWord<T> {};\ntemplate <typename T> struct UnitWord<const T> : UnitWord<T> {};\ntemplate <typename T> struct UnitWord<const volatile T> : UnitWord<T> {};\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n/******************************************************************************\n * Vector type inference utilities.\n ******************************************************************************/\n\n/**\n * \\brief Exposes a member typedef \\p Type that names the corresponding CUDA vector type if one exists.  Otherwise \\p Type refers to the CubVector structure itself, which will wrap the corresponding \\p x, \\p y, etc. vector fields.\n */\ntemplate <typename T, int vec_elements> struct CubVector;\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\nenum\n{\n    /// The maximum number of elements in CUDA vector types\n    MAX_VEC_ELEMENTS = 4,\n};\n\n\n/**\n * Generic vector-1 type\n */\ntemplate <typename T>\nstruct CubVector<T, 1>\n{\n    T x;\n\n    typedef T BaseType;\n    typedef CubVector<T, 1> Type;\n};\n\n/**\n * Generic vector-2 type\n */\ntemplate <typename T>\nstruct CubVector<T, 2>\n{\n    T x;\n    T y;\n\n    typedef T BaseType;\n    typedef CubVector<T, 2> Type;\n};\n\n/**\n * Generic vector-3 type\n */\ntemplate <typename T>\nstruct CubVector<T, 3>\n{\n    T x;\n    T y;\n    T z;\n\n    typedef T BaseType;\n    typedef CubVector<T, 3> Type;\n};\n\n/**\n * Generic vector-4 type\n */\ntemplate <typename T>\nstruct CubVector<T, 4>\n{\n    T x;\n    T y;\n    T z;\n    T w;\n\n    typedef T BaseType;\n    typedef CubVector<T, 4> Type;\n};\n\n\n/**\n * Macro for expanding partially-specialized built-in vector types\n */\n#define CUB_DEFINE_VECTOR_TYPE(base_type,short_type)                                                    \\\n                                                                                                        \\\n    template<> struct CubVector<base_type, 1> : short_type##1                                           \\\n    {                                                                                                   \\\n      typedef base_type       BaseType;                                                                 \\\n      typedef short_type##1   Type;                                                                     \\\n      __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const {           \\\n          CubVector retval;                                                                             \\\n          retval.x = x + other.x;                                                                       \\\n          return retval;                                                                                \\\n      }                                                                                                 \\\n      __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const {           \\\n          CubVector retval;                                                                             \\\n          retval.x = x - other.x;                                                                       \\\n          return retval;                                                                                \\\n      }                                                                                                 \\\n    };                                                                                                  \\\n                                                                                                        \\\n    template<> struct CubVector<base_type, 2> : short_type##2                                           \\\n    {                                                                                                   \\\n        typedef base_type       BaseType;                                                               \\\n        typedef short_type##2   Type;                                                                   \\\n        __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x + other.x;                                                                     \\\n            retval.y = y + other.y;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n        __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x - other.x;                                                                     \\\n            retval.y = y - other.y;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n    };                                                                                                  \\\n                                                                                                        \\\n    template<> struct CubVector<base_type, 3> : short_type##3                                           \\\n    {                                                                                                   \\\n        typedef base_type       BaseType;                                                               \\\n        typedef short_type##3   Type;                                                                   \\\n        __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x + other.x;                                                                     \\\n            retval.y = y + other.y;                                                                     \\\n            retval.z = z + other.z;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n        __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x - other.x;                                                                     \\\n            retval.y = y - other.y;                                                                     \\\n            retval.z = z - other.z;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n    };                                                                                                  \\\n                                                                                                        \\\n    template<> struct CubVector<base_type, 4> : short_type##4                                           \\\n    {                                                                                                   \\\n        typedef base_type       BaseType;                                                               \\\n        typedef short_type##4   Type;                                                                   \\\n        __host__ __device__ __forceinline__ CubVector operator+(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x + other.x;                                                                     \\\n            retval.y = y + other.y;                                                                     \\\n            retval.z = z + other.z;                                                                     \\\n            retval.w = w + other.w;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n        __host__ __device__ __forceinline__ CubVector operator-(const CubVector &other) const {         \\\n            CubVector retval;                                                                           \\\n            retval.x = x - other.x;                                                                     \\\n            retval.y = y - other.y;                                                                     \\\n            retval.z = z - other.z;                                                                     \\\n            retval.w = w - other.w;                                                                     \\\n            return retval;                                                                              \\\n        }                                                                                               \\\n    };\n\n\n\n// Expand CUDA vector types for built-in primitives\nCUB_DEFINE_VECTOR_TYPE(char,               char)\nCUB_DEFINE_VECTOR_TYPE(signed char,        char)\nCUB_DEFINE_VECTOR_TYPE(short,              short)\nCUB_DEFINE_VECTOR_TYPE(int,                int)\nCUB_DEFINE_VECTOR_TYPE(long,               long)\nCUB_DEFINE_VECTOR_TYPE(long long,          longlong)\nCUB_DEFINE_VECTOR_TYPE(unsigned char,      uchar)\nCUB_DEFINE_VECTOR_TYPE(unsigned short,     ushort)\nCUB_DEFINE_VECTOR_TYPE(unsigned int,       uint)\nCUB_DEFINE_VECTOR_TYPE(unsigned long,      ulong)\nCUB_DEFINE_VECTOR_TYPE(unsigned long long, ulonglong)\nCUB_DEFINE_VECTOR_TYPE(float,              float)\nCUB_DEFINE_VECTOR_TYPE(double,             double)\nCUB_DEFINE_VECTOR_TYPE(bool,               uchar)\n\n// Undefine macros\n#undef CUB_DEFINE_VECTOR_TYPE\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n\n/******************************************************************************\n * Wrapper types\n ******************************************************************************/\n\n/**\n * \\brief A storage-backing wrapper that allows types with non-trivial constructors to be aliased in unions\n */\ntemplate <typename T>\nstruct Uninitialized\n{\n    /// Biggest memory-access word that T is a whole multiple of and is not larger than the alignment of T\n    typedef typename UnitWord<T>::DeviceWord DeviceWord;\n\n    enum\n    {\n        WORDS = sizeof(T) / sizeof(DeviceWord)\n    };\n\n    /// Backing storage\n    DeviceWord storage[WORDS];\n\n    /// Alias\n    __host__ __device__ __forceinline__ T& Alias()\n    {\n        return reinterpret_cast<T&>(*this);\n    }\n};\n\n\n/**\n * \\brief A key identifier paired with a corresponding value\n */\ntemplate <\n    typename    _Key,\n    typename    _Value\n#if defined(_WIN32) && !defined(_WIN64)\n    , bool KeyIsLT = (AlignBytes<_Key>::ALIGN_BYTES < AlignBytes<_Value>::ALIGN_BYTES)\n    , bool ValIsLT = (AlignBytes<_Value>::ALIGN_BYTES < AlignBytes<_Key>::ALIGN_BYTES)\n#endif // #if defined(_WIN32) && !defined(_WIN64)\n    >\nstruct KeyValuePair\n{\n    typedef _Key    Key;                ///< Key data type\n    typedef _Value  Value;              ///< Value data type\n\n    Key     key;                        ///< Item key\n    Value   value;                      ///< Item value\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair() {}\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair(Key const& key, Value const& value) : key(key), value(value) {}\n\n    /// Inequality operator\n    __host__ __device__ __forceinline__ bool operator !=(const KeyValuePair &b)\n    {\n        return (value != b.value) || (key != b.key);\n    }\n};\n\n#if defined(_WIN32) && !defined(_WIN64)\n\n/**\n * Win32 won't do 16B alignment.  This can present two problems for\n * should-be-16B-aligned (but actually 8B aligned) built-in and intrinsics members:\n * 1) If a smaller-aligned item were to be listed first, the host compiler places the\n *    should-be-16B item at too early an offset (and disagrees with device compiler)\n * 2) Or, if a smaller-aligned item lists second, the host compiler gets the size\n *    of the struct wrong (and disagrees with device compiler)\n *\n * So we put the larger-should-be-aligned item first, and explicitly pad the\n * end of the struct\n */\n\n/// Smaller key specialization\ntemplate <typename K, typename V>\nstruct KeyValuePair<K, V, true, false>\n{\n    typedef K Key;\n    typedef V Value;\n\n    typedef char Pad[AlignBytes<V>::ALIGN_BYTES - AlignBytes<K>::ALIGN_BYTES];\n\n    Value   value;  // Value has larger would-be alignment and goes first\n    Key     key;\n    Pad     pad;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair() {}\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair(Key const& key, Value const& value) : key(key), value(value) {}\n\n    /// Inequality operator\n    __host__ __device__ __forceinline__ bool operator !=(const KeyValuePair &b)\n    {\n        return (value != b.value) || (key != b.key);\n    }\n};\n\n\n/// Smaller value specialization\ntemplate <typename K, typename V>\nstruct KeyValuePair<K, V, false, true>\n{\n    typedef K Key;\n    typedef V Value;\n\n    typedef char Pad[AlignBytes<K>::ALIGN_BYTES - AlignBytes<V>::ALIGN_BYTES];\n\n    Key     key;    // Key has larger would-be alignment and goes first\n    Value   value;\n    Pad     pad;\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair() {}\n\n    /// Constructor\n    __host__ __device__ __forceinline__\n    KeyValuePair(Key const& key, Value const& value) : key(key), value(value) {}\n\n    /// Inequality operator\n    __host__ __device__ __forceinline__ bool operator !=(const KeyValuePair &b)\n    {\n        return (value != b.value) || (key != b.key);\n    }\n};\n\n#endif // #if defined(_WIN32) && !defined(_WIN64)\n\n\n#ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n\n/**\n * \\brief A wrapper for passing simple static arrays as kernel parameters\n */\ntemplate <typename T, int COUNT>\nstruct ArrayWrapper\n{\n\n    /// Statically-sized array of type \\p T\n    T array[COUNT];\n\n    /// Constructor\n    __host__ __device__ __forceinline__ ArrayWrapper() {}\n};\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n/**\n * \\brief Double-buffer storage wrapper for multi-pass stream transformations that require more than one storage array for streaming intermediate results back and forth.\n *\n * Many multi-pass computations require a pair of \"ping-pong\" storage\n * buffers (e.g., one for reading from and the other for writing to, and then\n * vice-versa for the subsequent pass).  This structure wraps a set of device\n * buffers and a \"selector\" member to track which is \"current\".\n */\ntemplate <typename T>\nstruct DoubleBuffer\n{\n    /// Pair of device buffer pointers\n    T *d_buffers[2];\n\n    ///  Selector into \\p d_buffers (i.e., the active/valid buffer)\n    int selector;\n\n    /// \\brief Constructor\n    __host__ __device__ __forceinline__ DoubleBuffer()\n    {\n        selector = 0;\n        d_buffers[0] = NULL;\n        d_buffers[1] = NULL;\n    }\n\n    /// \\brief Constructor\n    __host__ __device__ __forceinline__ DoubleBuffer(\n        T *d_current,         ///< The currently valid buffer\n        T *d_alternate)       ///< Alternate storage buffer of the same size as \\p d_current\n    {\n        selector = 0;\n        d_buffers[0] = d_current;\n        d_buffers[1] = d_alternate;\n    }\n\n    /// \\brief Return pointer to the currently valid buffer\n    __host__ __device__ __forceinline__ T* Current() { return d_buffers[selector]; }\n\n    /// \\brief Return pointer to the currently invalid buffer\n    __host__ __device__ __forceinline__ T* Alternate() { return d_buffers[selector ^ 1]; }\n\n};\n\n\n\n/******************************************************************************\n * Typedef-detection\n ******************************************************************************/\n\n\n/**\n * \\brief Defines a structure \\p detector_name that is templated on type \\p T.  The \\p detector_name struct exposes a constant member \\p VALUE indicating whether or not parameter \\p T exposes a nested type \\p nested_type_name\n */\n#define CUB_DEFINE_DETECT_NESTED_TYPE(detector_name, nested_type_name)  \\\n    template <typename T>                                               \\\n    struct detector_name                                                \\\n    {                                                                   \\\n        template <typename C>                                           \\\n        static char& test(typename C::nested_type_name*);               \\\n        template <typename>                                             \\\n        static int& test(...);                                          \\\n        enum                                                            \\\n        {                                                               \\\n            VALUE = sizeof(test<T>(0)) < sizeof(int)                    \\\n        };                                                              \\\n    };\n\n\n\n/******************************************************************************\n * Simple enable-if (similar to Boost)\n ******************************************************************************/\n\n/**\n * \\brief Simple enable-if (similar to Boost)\n */\ntemplate <bool Condition, class T = void>\nstruct EnableIf\n{\n    /// Enable-if type for SFINAE dummy variables\n    typedef T Type;\n};\n\n\ntemplate <class T>\nstruct EnableIf<false, T> {};\n\n\n\n/******************************************************************************\n * Typedef-detection\n ******************************************************************************/\n\n/**\n * \\brief Determine whether or not BinaryOp's functor is of the form <tt>bool operator()(const T& a, const T&b)</tt> or <tt>bool operator()(const T& a, const T&b, unsigned int idx)</tt>\n */\ntemplate <typename T, typename BinaryOp>\nstruct BinaryOpHasIdxParam\n{\nprivate:\n/*\n    template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, unsigned int idx) const>  struct SFINAE1 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, unsigned int idx)>        struct SFINAE2 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, unsigned int idx) const>                struct SFINAE3 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, unsigned int idx)>                      struct SFINAE4 {};\n*/\n    template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, int idx) const>           struct SFINAE5 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(const T &a, const T &b, int idx)>                 struct SFINAE6 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, int idx) const>                         struct SFINAE7 {};\n    template <typename BinaryOpT, bool (BinaryOpT::*)(T a, T b, int idx)>                               struct SFINAE8 {};\n/*\n    template <typename BinaryOpT> static char Test(SFINAE1<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE2<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE3<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE4<BinaryOpT, &BinaryOpT::operator()> *);\n*/\n    template <typename BinaryOpT> static char Test(SFINAE5<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE6<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE7<BinaryOpT, &BinaryOpT::operator()> *);\n    template <typename BinaryOpT> static char Test(SFINAE8<BinaryOpT, &BinaryOpT::operator()> *);\n\n    template <typename BinaryOpT> static int Test(...);\n\npublic:\n\n    /// Whether the functor BinaryOp has a third <tt>unsigned int</tt> index param\n    static const bool HAS_PARAM = sizeof(Test<BinaryOp>(NULL)) == sizeof(char);\n};\n\n\n\n\n/******************************************************************************\n * Simple type traits utilities.\n *\n * For example:\n *     Traits<int>::CATEGORY             // SIGNED_INTEGER\n *     Traits<NullType>::NULL_TYPE       // true\n *     Traits<uint4>::CATEGORY           // NOT_A_NUMBER\n *     Traits<uint4>::PRIMITIVE;         // false\n *\n ******************************************************************************/\n\n/**\n * \\brief Basic type traits categories\n */\nenum Category\n{\n    NOT_A_NUMBER,\n    SIGNED_INTEGER,\n    UNSIGNED_INTEGER,\n    FLOATING_POINT\n};\n\n\n/**\n * \\brief Basic type traits\n */\ntemplate <Category _CATEGORY, bool _PRIMITIVE, bool _NULL_TYPE, typename _UnsignedBits, typename T>\nstruct BaseTraits\n{\n    /// Category\n    static const Category CATEGORY      = _CATEGORY;\n    enum\n    {\n        PRIMITIVE       = _PRIMITIVE,\n        NULL_TYPE       = _NULL_TYPE,\n    };\n};\n\n\n/**\n * Basic type traits (unsigned primitive specialization)\n */\ntemplate <typename _UnsignedBits, typename T>\nstruct BaseTraits<UNSIGNED_INTEGER, true, false, _UnsignedBits, T>\n{\n    typedef _UnsignedBits       UnsignedBits;\n\n    static const Category       CATEGORY    = UNSIGNED_INTEGER;\n    static const UnsignedBits   LOWEST_KEY  = UnsignedBits(0);\n    static const UnsignedBits   MAX_KEY     = UnsignedBits(-1);\n\n    enum\n    {\n        PRIMITIVE       = true,\n        NULL_TYPE       = false,\n    };\n\n\n    static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)\n    {\n        return key;\n    }\n\n    static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)\n    {\n        return key;\n    }\n\n    static __host__ __device__ __forceinline__ T Max()\n    {\n        UnsignedBits retval = MAX_KEY;\n        return reinterpret_cast<T&>(retval);\n    }\n\n    static __host__ __device__ __forceinline__ T Lowest()\n    {\n        UnsignedBits retval = LOWEST_KEY;\n        return reinterpret_cast<T&>(retval);\n    }\n};\n\n\n/**\n * Basic type traits (signed primitive specialization)\n */\ntemplate <typename _UnsignedBits, typename T>\nstruct BaseTraits<SIGNED_INTEGER, true, false, _UnsignedBits, T>\n{\n    typedef _UnsignedBits       UnsignedBits;\n\n    static const Category       CATEGORY    = SIGNED_INTEGER;\n    static const UnsignedBits   HIGH_BIT    = UnsignedBits(1) << ((sizeof(UnsignedBits) * 8) - 1);\n    static const UnsignedBits   LOWEST_KEY  = HIGH_BIT;\n    static const UnsignedBits   MAX_KEY     = UnsignedBits(-1) ^ HIGH_BIT;\n\n    enum\n    {\n        PRIMITIVE       = true,\n        NULL_TYPE       = false,\n    };\n\n    static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)\n    {\n        return key ^ HIGH_BIT;\n    };\n\n    static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)\n    {\n        return key ^ HIGH_BIT;\n    };\n\n    static __host__ __device__ __forceinline__ T Max()\n    {\n        UnsignedBits retval = MAX_KEY;\n        return reinterpret_cast<T&>(retval);\n    }\n\n    static __host__ __device__ __forceinline__ T Lowest()\n    {\n        UnsignedBits retval = LOWEST_KEY;\n        return reinterpret_cast<T&>(retval);\n    }\n};\n\ntemplate <typename _T>\nstruct FpLimits;\n\ntemplate <>\nstruct FpLimits<float>\n{\n    static __host__ __device__ __forceinline__ float Max() {\n        return FLT_MAX;\n    }\n\n    static __host__ __device__ __forceinline__ float Lowest() {\n        return FLT_MAX * float(-1);\n    }\n};\n\ntemplate <>\nstruct FpLimits<double>\n{\n    static __host__ __device__ __forceinline__ double Max() {\n        return DBL_MAX;\n    }\n\n    static __host__ __device__ __forceinline__ double Lowest() {\n        return DBL_MAX  * double(-1);\n    }\n};\n\n\n/**\n * Basic type traits (fp primitive specialization)\n */\ntemplate <typename _UnsignedBits, typename T>\nstruct BaseTraits<FLOATING_POINT, true, false, _UnsignedBits, T>\n{\n    typedef _UnsignedBits       UnsignedBits;\n\n    static const Category       CATEGORY    = FLOATING_POINT;\n    static const UnsignedBits   HIGH_BIT    = UnsignedBits(1) << ((sizeof(UnsignedBits) * 8) - 1);\n    static const UnsignedBits   LOWEST_KEY  = UnsignedBits(-1);\n    static const UnsignedBits   MAX_KEY     = UnsignedBits(-1) ^ HIGH_BIT;\n\n    enum\n    {\n        PRIMITIVE       = true,\n        NULL_TYPE       = false,\n    };\n\n    static __device__ __forceinline__ UnsignedBits TwiddleIn(UnsignedBits key)\n    {\n        UnsignedBits mask = (key & HIGH_BIT) ? UnsignedBits(-1) : HIGH_BIT;\n        return key ^ mask;\n    };\n\n    static __device__ __forceinline__ UnsignedBits TwiddleOut(UnsignedBits key)\n    {\n        UnsignedBits mask = (key & HIGH_BIT) ? HIGH_BIT : UnsignedBits(-1);\n        return key ^ mask;\n    };\n\n    static __host__ __device__ __forceinline__ T Max() {\n        return FpLimits<T>::Max();\n    }\n\n    static __host__ __device__ __forceinline__ T Lowest() {\n        return FpLimits<T>::Lowest();\n    }\n};\n\n\n/**\n * \\brief Numeric type traits\n */\ntemplate <typename T> struct NumericTraits :            BaseTraits<NOT_A_NUMBER, false, false, T, T> {};\n\ntemplate <> struct NumericTraits<NullType> :            BaseTraits<NOT_A_NUMBER, false, true, NullType, NullType> {};\n\ntemplate <> struct NumericTraits<char> :                BaseTraits<(std::numeric_limits<char>::is_signed) ? SIGNED_INTEGER : UNSIGNED_INTEGER, true, false, unsigned char, char> {};\ntemplate <> struct NumericTraits<signed char> :         BaseTraits<SIGNED_INTEGER, true, false, unsigned char, signed char> {};\ntemplate <> struct NumericTraits<short> :               BaseTraits<SIGNED_INTEGER, true, false, unsigned short, short> {};\ntemplate <> struct NumericTraits<int> :                 BaseTraits<SIGNED_INTEGER, true, false, unsigned int, int> {};\ntemplate <> struct NumericTraits<long> :                BaseTraits<SIGNED_INTEGER, true, false, unsigned long, long> {};\ntemplate <> struct NumericTraits<long long> :           BaseTraits<SIGNED_INTEGER, true, false, unsigned long long, long long> {};\n\ntemplate <> struct NumericTraits<unsigned char> :       BaseTraits<UNSIGNED_INTEGER, true, false, unsigned char, unsigned char> {};\ntemplate <> struct NumericTraits<unsigned short> :      BaseTraits<UNSIGNED_INTEGER, true, false, unsigned short, unsigned short> {};\ntemplate <> struct NumericTraits<unsigned int> :        BaseTraits<UNSIGNED_INTEGER, true, false, unsigned int, unsigned int> {};\ntemplate <> struct NumericTraits<unsigned long> :       BaseTraits<UNSIGNED_INTEGER, true, false, unsigned long, unsigned long> {};\ntemplate <> struct NumericTraits<unsigned long long> :  BaseTraits<UNSIGNED_INTEGER, true, false, unsigned long long, unsigned long long> {};\n\ntemplate <> struct NumericTraits<float> :               BaseTraits<FLOATING_POINT, true, false, unsigned int, float> {};\ntemplate <> struct NumericTraits<double> :              BaseTraits<FLOATING_POINT, true, false, unsigned long long, double> {};\n\ntemplate <> struct NumericTraits<bool> :                BaseTraits<UNSIGNED_INTEGER, true, false, typename UnitWord<bool>::VolatileWord, bool> {};\n\n\n\n/**\n * \\brief Type traits\n */\ntemplate <typename T>\nstruct Traits : NumericTraits<typename RemoveQualifiers<T>::Type> {};\n\n\n#endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\n/** @} */       // end group UtilModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/specializations/warp_reduce_shfl.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::WarpReduceShfl provides SHFL-based variants of parallel reduction of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_macro.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\brief WarpReduceShfl provides SHFL-based variants of parallel reduction of items partitioned across a CUDA thread warp.\n *\n * LOGICAL_WARP_THREADS must be a power-of-two\n */\ntemplate <\n    typename    T,                      ///< Data type being reduced\n    int         LOGICAL_WARP_THREADS,   ///< Number of threads per logical warp\n    int         PTX_ARCH>               ///< The PTX compute capability for which to to specialize this collective\nstruct WarpReduceShfl\n{\n    //---------------------------------------------------------------------\n    // Constants and type definitions\n    //---------------------------------------------------------------------\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// The number of warp reduction steps\n        STEPS = Log2<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// Number of logical warps in a PTX warp\n        LOGICAL_WARPS = CUB_WARP_THREADS(PTX_ARCH) / LOGICAL_WARP_THREADS,\n    };\n\n    template <typename S>\n    struct IsInteger\n    {\n        enum {\n            ///Whether the data type is a small (32b or less) integer for which we can use a single SFHL instruction per exchange\n            IS_SMALL_UNSIGNED = (Traits<S>::CATEGORY == UNSIGNED_INTEGER) && (sizeof(S) <= sizeof(unsigned int))\n        };\n    };\n\n\n    // Creates a mask where the last thread in each logical warp is set\n    template <int WARP, int WARPS>\n    struct LastLaneMask\n    {\n        enum {\n            BASE_MASK   = 1 << (LOGICAL_WARP_THREADS - 1),\n            MASK        = (LastLaneMask<WARP + 1, WARPS>::MASK << LOGICAL_WARP_THREADS) | BASE_MASK,\n        };\n    };\n\n    // Creates a mask where the last thread in each logical warp is set\n    template <int WARP>\n    struct LastLaneMask<WARP, WARP>\n    {\n        enum {\n            MASK        = 1 << (LOGICAL_WARP_THREADS - 1),\n        };\n    };\n\n\n\n    /// Shared memory storage layout type\n    typedef NullType TempStorage;\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n\n    unsigned int lane_id;\n\n    unsigned int member_mask;\n\n    //---------------------------------------------------------------------\n    // Construction\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ WarpReduceShfl(\n        TempStorage &/*temp_storage*/)\n    :\n        lane_id(LaneId()),\n\n        member_mask((0xffffffff >> (32 - LOGICAL_WARP_THREADS)) << ((IS_ARCH_WARP) ?\n            0 : // arch-width subwarps need not be tiled within the arch-warp\n            ((lane_id / LOGICAL_WARP_THREADS) * LOGICAL_WARP_THREADS)))\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Reduction steps\n    //---------------------------------------------------------------------\n\n    /// Reduction (specialized for summation across uint32 types)\n    __device__ __forceinline__ unsigned int ReduceStep(\n        unsigned int    input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*reduction_op*/,   ///< [in] Binary reduction operator\n        int             last_lane,          ///< [in] Index of last lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        unsigned int output;\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.sync.down.b32 r0|p, %1, %2, %3, %5;\"\n            \"  @p add.u32 r0, r0, %4;\"\n            \"  mov.u32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(last_lane), \"r\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.down.b32 r0|p, %1, %2, %3;\"\n            \"  @p add.u32 r0, r0, %4;\"\n            \"  mov.u32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(last_lane), \"r\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Reduction (specialized for summation across fp32 types)\n    __device__ __forceinline__ float ReduceStep(\n        float           input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*reduction_op*/,   ///< [in] Binary reduction operator\n        int             last_lane,          ///< [in] Index of last lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        float output;\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .f32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.sync.down.b32 r0|p, %1, %2, %3, %5;\"\n            \"  @p add.f32 r0, r0, %4;\"\n            \"  mov.f32 %0, r0;\"\n            \"}\"\n            : \"=f\"(output) : \"f\"(input), \"r\"(offset), \"r\"(last_lane), \"f\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .f32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.down.b32 r0|p, %1, %2, %3;\"\n            \"  @p add.f32 r0, r0, %4;\"\n            \"  mov.f32 %0, r0;\"\n            \"}\"\n            : \"=f\"(output) : \"f\"(input), \"r\"(offset), \"r\"(last_lane), \"f\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Reduction (specialized for summation across unsigned long long types)\n    __device__ __forceinline__ unsigned long long ReduceStep(\n        unsigned long long  input,              ///< [in] Calling thread's input item.\n        cub::Sum            /*reduction_op*/,   ///< [in] Binary reduction operator\n        int                 last_lane,          ///< [in] Index of last lane in segment\n        int                 offset)             ///< [in] Up-offset to pull from\n    {\n        unsigned long long output;\n\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.down.b32 lo|p, lo, %2, %3, %4;\"\n            \"  shfl.sync.down.b32 hi|p, hi, %2, %3, %4;\"\n            \"  mov.b64 %0, {lo, hi};\"\n            \"  @p add.u64 %0, %0, %1;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(last_lane), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.down.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.down.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 %0, {lo, hi};\"\n            \"  @p add.u64 %0, %0, %1;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(last_lane));\n#endif\n\n        return output;\n    }\n\n\n    /// Reduction (specialized for summation across long long types)\n    __device__ __forceinline__ long long ReduceStep(\n        long long           input,              ///< [in] Calling thread's input item.\n        cub::Sum            /*reduction_op*/,   ///< [in] Binary reduction operator\n        int                 last_lane,          ///< [in] Index of last lane in segment\n        int                 offset)             ///< [in] Up-offset to pull from\n    {\n        long long output;\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.down.b32 lo|p, lo, %2, %3, %4;\"\n            \"  shfl.sync.down.b32 hi|p, hi, %2, %3, %4;\"\n            \"  mov.b64 %0, {lo, hi};\"\n            \"  @p add.s64 %0, %0, %1;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(last_lane), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.down.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.down.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 %0, {lo, hi};\"\n            \"  @p add.s64 %0, %0, %1;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(last_lane));\n#endif\n\n        return output;\n    }\n\n\n    /// Reduction (specialized for summation across double types)\n    __device__ __forceinline__ double ReduceStep(\n        double              input,              ///< [in] Calling thread's input item.\n        cub::Sum            /*reduction_op*/,   ///< [in] Binary reduction operator\n        int                 last_lane,          ///< [in] Index of last lane in segment\n        int                 offset)             ///< [in] Up-offset to pull from\n    {\n        double output;\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  .reg .f64 r0;\"\n            \"  mov.b64 %0, %1;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.down.b32 lo|p, lo, %2, %3, %4;\"\n            \"  shfl.sync.down.b32 hi|p, hi, %2, %3, %4;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.f64 %0, %0, r0;\"\n            \"}\"\n            : \"=d\"(output) : \"d\"(input), \"r\"(offset), \"r\"(last_lane), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  .reg .f64 r0;\"\n            \"  mov.b64 %0, %1;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.down.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.down.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.f64 %0, %0, r0;\"\n            \"}\"\n            : \"=d\"(output) : \"d\"(input), \"r\"(offset), \"r\"(last_lane));\n#endif\n\n        return output;\n    }\n\n\n    /// Reduction (specialized for swizzled ReduceByKeyOp<cub::Sum> across KeyValuePair<KeyT, ValueT> types)\n    template <typename ValueT, typename KeyT>\n    __device__ __forceinline__ KeyValuePair<KeyT, ValueT> ReduceStep(\n        KeyValuePair<KeyT, ValueT>                  input,              ///< [in] Calling thread's input item.\n        SwizzleScanOp<ReduceByKeyOp<cub::Sum> >     /*reduction_op*/,       ///< [in] Binary reduction operator\n        int                                         last_lane,          ///< [in] Index of last lane in segment\n        int                                         offset)             ///< [in] Up-offset to pull from\n    {\n        KeyValuePair<KeyT, ValueT> output;\n\n        KeyT other_key = ShuffleDown(input.key, offset, last_lane, member_mask);\n        \n        output.key = input.key;\n        output.value = ReduceStep(\n            input.value, \n            cub::Sum(), \n            last_lane, \n            offset, \n            Int2Type<IsInteger<ValueT>::IS_SMALL_UNSIGNED>());\n\n        if (input.key != other_key)\n            output.value = input.value;\n\n        return output;\n    }\n\n\n\n    /// Reduction (specialized for swizzled ReduceBySegmentOp<cub::Sum> across KeyValuePair<OffsetT, ValueT> types)\n    template <typename ValueT, typename OffsetT>\n    __device__ __forceinline__ KeyValuePair<OffsetT, ValueT> ReduceStep(\n        KeyValuePair<OffsetT, ValueT>                 input,              ///< [in] Calling thread's input item.\n        SwizzleScanOp<ReduceBySegmentOp<cub::Sum> >   /*reduction_op*/,   ///< [in] Binary reduction operator\n        int                                           last_lane,          ///< [in] Index of last lane in segment\n        int                                           offset)             ///< [in] Up-offset to pull from\n    {\n        KeyValuePair<OffsetT, ValueT> output;\n\n        output.value = ReduceStep(input.value, cub::Sum(), last_lane, offset, Int2Type<IsInteger<ValueT>::IS_SMALL_UNSIGNED>());\n        output.key = ReduceStep(input.key, cub::Sum(), last_lane, offset, Int2Type<IsInteger<OffsetT>::IS_SMALL_UNSIGNED>());\n\n        if (input.key > 0)\n            output.value = input.value;\n\n        return output;\n    }\n\n\n    /// Reduction step (generic)\n    template <typename _T, typename ReductionOp>\n    __device__ __forceinline__ _T ReduceStep(\n        _T                  input,              ///< [in] Calling thread's input item.\n        ReductionOp         reduction_op,       ///< [in] Binary reduction operator\n        int                 last_lane,          ///< [in] Index of last lane in segment\n        int                 offset)             ///< [in] Up-offset to pull from\n    {\n        _T output = input;\n\n        _T temp = ShuffleDown(output, offset, last_lane, member_mask);\n\n        // Perform reduction op if valid\n        if (offset + lane_id <= last_lane)\n            output = reduction_op(input, temp);\n\n        return output;\n    }\n\n\n    /// Reduction step (specialized for small unsigned integers size 32b or less)\n    template <typename _T, typename ReductionOp>\n    __device__ __forceinline__ _T ReduceStep(\n        _T              input,                  ///< [in] Calling thread's input item.\n        ReductionOp     reduction_op,           ///< [in] Binary reduction operator\n        int             last_lane,              ///< [in] Index of last lane in segment\n        int             offset,                 ///< [in] Up-offset to pull from\n        Int2Type<true>  /*is_small_unsigned*/)  ///< [in] Marker type indicating whether T is a small unsigned integer\n    {\n        return ReduceStep(input, reduction_op, last_lane, offset);\n    }\n\n\n    /// Reduction step (specialized for types other than small unsigned integers size 32b or less)\n    template <typename _T, typename ReductionOp>\n    __device__ __forceinline__ _T ReduceStep(\n        _T              input,                  ///< [in] Calling thread's input item.\n        ReductionOp     reduction_op,           ///< [in] Binary reduction operator\n        int             last_lane,              ///< [in] Index of last lane in segment\n        int             offset,                 ///< [in] Up-offset to pull from\n        Int2Type<false> /*is_small_unsigned*/)  ///< [in] Marker type indicating whether T is a small unsigned integer\n    {\n        return ReduceStep(input, reduction_op, last_lane, offset);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Templated inclusive scan iteration\n    //---------------------------------------------------------------------\n\n    template <typename ReductionOp, int STEP>\n    __device__ __forceinline__ void ReduceStep(\n        T&              input,              ///< [in] Calling thread's input item.\n        ReductionOp     reduction_op,       ///< [in] Binary reduction operator\n        int             last_lane,          ///< [in] Index of last lane in segment\n        Int2Type<STEP>  /*step*/)\n    {\n        input = ReduceStep(input, reduction_op, last_lane, 1 << STEP, Int2Type<IsInteger<T>::IS_SMALL_UNSIGNED>());\n\n        ReduceStep(input, reduction_op, last_lane, Int2Type<STEP + 1>());\n    }\n\n    template <typename ReductionOp>\n    __device__ __forceinline__ void ReduceStep(\n        T&              /*input*/,              ///< [in] Calling thread's input item.\n        ReductionOp     /*reduction_op*/,       ///< [in] Binary reduction operator\n        int             /*last_lane*/,          ///< [in] Index of last lane in segment\n        Int2Type<STEPS> /*step*/)\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Reduction operations\n    //---------------------------------------------------------------------\n\n    /// Reduction\n    template <\n        bool            ALL_LANES_VALID,        ///< Whether all lanes in each warp are contributing a valid fold of items\n        int             FOLDED_ITEMS_PER_LANE,  ///< Number of items folded into each lane\n        typename        ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T               input,                  ///< [in] Calling thread's input\n        int             folded_items_per_warp,  ///< [in] Total number of valid items folded into each logical warp\n        ReductionOp     reduction_op)           ///< [in] Binary reduction operator\n    {\n        // Get the lane of the first and last thread in the logical warp\n        int first_thread   = 0;\n        int last_thread    = LOGICAL_WARP_THREADS - 1;\n        if (!IS_ARCH_WARP)\n        {\n            first_thread = lane_id & (~(LOGICAL_WARP_THREADS - 1));\n            last_thread |= lane_id;\n        }\n\n        // Common case is FOLDED_ITEMS_PER_LANE = 1 (or a multiple of 32)\n        int lanes_with_valid_data = (folded_items_per_warp - 1) / FOLDED_ITEMS_PER_LANE;\n\n        // Get the last valid lane\n        int last_lane = (ALL_LANES_VALID) ?\n            last_thread :\n            CUB_MIN(last_thread, first_thread + lanes_with_valid_data);\n\n        T output = input;\n\n//        // Iterate reduction steps\n//        #pragma unroll\n//        for (int STEP = 0; STEP < STEPS; STEP++)\n//        {\n//            output = ReduceStep(output, reduction_op, last_lane, 1 << STEP, Int2Type<IsInteger<T>::IS_SMALL_UNSIGNED>());\n//        }\n\n        // Template-iterate reduction steps\n        ReduceStep(output, reduction_op, last_lane, Int2Type<0>());\n\n        return output;\n    }\n\n\n    /// Segmented reduction\n    template <\n        bool            HEAD_SEGMENTED,     ///< Whether flags indicate a segment-head or a segment-tail\n        typename        FlagT,\n        typename        ReductionOp>\n    __device__ __forceinline__ T SegmentedReduce(\n        T               input,              ///< [in] Calling thread's input\n        FlagT           flag,               ///< [in] Whether or not the current lane is a segment head/tail\n        ReductionOp     reduction_op)       ///< [in] Binary reduction operator\n    {\n        // Get the start flags for each thread in the warp.\n        int warp_flags = WARP_BALLOT(flag, member_mask);\n\n        // Convert to tail-segmented\n        if (HEAD_SEGMENTED)\n            warp_flags >>= 1;\n\n        // Mask in the last lanes of each logical warp\n        warp_flags |= LastLaneMask<1, LOGICAL_WARPS>::MASK;\n\n        // Mask out the bits below the current thread\n        warp_flags &= LaneMaskGe();\n\n        // Find the next set flag\n        int last_lane = __clz(__brev(warp_flags));\n\n        T output = input;\n\n//        // Iterate reduction steps\n//        #pragma unroll\n//        for (int STEP = 0; STEP < STEPS; STEP++)\n//        {\n//            output = ReduceStep(output, reduction_op, last_lane, 1 << STEP, Int2Type<IsInteger<T>::IS_SMALL_UNSIGNED>());\n//        }\n\n        // Template-iterate reduction steps\n        ReduceStep(output, reduction_op, last_lane, Int2Type<0>());\n\n        return output;\n    }\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/specializations/warp_reduce_smem.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::WarpReduceSmem provides smem-based variants of parallel reduction of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../thread/thread_load.cuh\"\n#include \"../../thread/thread_store.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief WarpReduceSmem provides smem-based variants of parallel reduction of items partitioned across a CUDA thread warp.\n */\ntemplate <\n    typename    T,                      ///< Data type being reduced\n    int         LOGICAL_WARP_THREADS,   ///< Number of threads per logical warp\n    int         PTX_ARCH>               ///< The PTX compute capability for which to to specialize this collective\nstruct WarpReduceSmem\n{\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// Whether the logical warp size is a power-of-two\n        IS_POW_OF_TWO = PowerOfTwo<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// The number of warp scan steps\n        STEPS = Log2<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// The number of threads in half a warp\n        HALF_WARP_THREADS = 1 << (STEPS - 1),\n\n        /// The number of shared memory elements per warp\n        WARP_SMEM_ELEMENTS =  LOGICAL_WARP_THREADS + HALF_WARP_THREADS,\n\n        /// FlagT status (when not using ballot)\n        UNSET   = 0x0,  // Is initially unset\n        SET     = 0x1,  // Is initially set\n        SEEN    = 0x2,  // Has seen another head flag from a successor peer\n    };\n\n    /// Shared memory flag type\n    typedef unsigned char SmemFlag;\n\n    /// Shared memory storage layout type (1.5 warps-worth of elements for each warp)\n    struct _TempStorage\n    {\n        T           reduce[WARP_SMEM_ELEMENTS];\n        SmemFlag    flags[WARP_SMEM_ELEMENTS];\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    _TempStorage    &temp_storage;\n    unsigned int    lane_id;\n    unsigned int    member_mask;\n\n\n    /******************************************************************************\n     * Construction\n     ******************************************************************************/\n\n    /// Constructor\n    __device__ __forceinline__ WarpReduceSmem(\n        TempStorage     &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n\n        lane_id(IS_ARCH_WARP ?\n            LaneId() :\n            LaneId() % LOGICAL_WARP_THREADS),\n\n        member_mask((0xffffffff >> (32 - LOGICAL_WARP_THREADS)) << ((IS_ARCH_WARP || !IS_POW_OF_TWO ) ?\n            0 : // arch-width and non-power-of-two subwarps cannot be tiled with the arch-warp\n            ((LaneId() / LOGICAL_WARP_THREADS) * LOGICAL_WARP_THREADS)))\n    {}\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    //---------------------------------------------------------------------\n    // Regular reduction\n    //---------------------------------------------------------------------\n\n    /**\n     * Reduction step\n     */\n    template <\n        bool                ALL_LANES_VALID,        ///< Whether all lanes in each warp are contributing a valid fold of items\n        int                 FOLDED_ITEMS_PER_LANE,  ///< Number of items folded into each lane\n        typename            ReductionOp,\n        int                 STEP>\n    __device__ __forceinline__ T ReduceStep(\n        T                   input,                  ///< [in] Calling thread's input\n        int                 folded_items_per_warp,  ///< [in] Total number of valid items folded into each logical warp\n        ReductionOp         reduction_op,           ///< [in] Reduction operator\n        Int2Type<STEP>      /*step*/)\n    {\n        const int OFFSET = 1 << STEP;\n\n        // Share input through buffer\n        ThreadStore<STORE_VOLATILE>(&temp_storage.reduce[lane_id], input);\n\n        WARP_SYNC(member_mask);\n\n        // Update input if peer_addend is in range\n        if ((ALL_LANES_VALID && IS_POW_OF_TWO) || ((lane_id + OFFSET) * FOLDED_ITEMS_PER_LANE < folded_items_per_warp))\n        {\n            T peer_addend = ThreadLoad<LOAD_VOLATILE>(&temp_storage.reduce[lane_id + OFFSET]);\n            input = reduction_op(input, peer_addend);\n        }\n\n        WARP_SYNC(member_mask);\n\n        return ReduceStep<ALL_LANES_VALID, FOLDED_ITEMS_PER_LANE>(input, folded_items_per_warp, reduction_op, Int2Type<STEP + 1>());\n    }\n\n\n    /**\n     * Reduction step (terminate)\n     */\n    template <\n        bool                ALL_LANES_VALID,            ///< Whether all lanes in each warp are contributing a valid fold of items\n        int                 FOLDED_ITEMS_PER_LANE,      ///< Number of items folded into each lane\n        typename            ReductionOp>\n    __device__ __forceinline__ T ReduceStep(\n        T                   input,                      ///< [in] Calling thread's input\n        int                 /*folded_items_per_warp*/,  ///< [in] Total number of valid items folded into each logical warp\n        ReductionOp         /*reduction_op*/,           ///< [in] Reduction operator\n        Int2Type<STEPS>     /*step*/)\n    {\n        return input;\n    }\n\n\n    //---------------------------------------------------------------------\n    // Segmented reduction\n    //---------------------------------------------------------------------\n\n\n    /**\n     * Ballot-based segmented reduce\n     */\n    template <\n        bool            HEAD_SEGMENTED,     ///< Whether flags indicate a segment-head or a segment-tail\n        typename        FlagT,\n        typename        ReductionOp>\n    __device__ __forceinline__ T SegmentedReduce(\n        T               input,                  ///< [in] Calling thread's input\n        FlagT           flag,                   ///< [in] Whether or not the current lane is a segment head/tail\n        ReductionOp     reduction_op,           ///< [in] Reduction operator\n        Int2Type<true>  /*has_ballot*/)         ///< [in] Marker type for whether the target arch has ballot functionality\n    {\n        // Get the start flags for each thread in the warp.\n        int warp_flags = WARP_BALLOT(flag, member_mask);\n\n        if (!HEAD_SEGMENTED)\n            warp_flags <<= 1;\n\n        // Keep bits above the current thread.\n        warp_flags &= LaneMaskGt();\n\n        // Accommodate packing of multiple logical warps in a single physical warp\n        if (!IS_ARCH_WARP)\n        {\n            warp_flags >>= (LaneId() / LOGICAL_WARP_THREADS) * LOGICAL_WARP_THREADS;\n        }\n\n        // Find next flag\n        int next_flag = __clz(__brev(warp_flags));\n\n        // Clip the next segment at the warp boundary if necessary\n        if (LOGICAL_WARP_THREADS != 32)\n            next_flag = CUB_MIN(next_flag, LOGICAL_WARP_THREADS);\n\n        #pragma unroll\n        for (int STEP = 0; STEP < STEPS; STEP++)\n        {\n            const int OFFSET = 1 << STEP;\n\n            // Share input into buffer\n            ThreadStore<STORE_VOLATILE>(&temp_storage.reduce[lane_id], input);\n\n            WARP_SYNC(member_mask);\n\n            // Update input if peer_addend is in range\n            if (OFFSET + lane_id < next_flag)\n            {\n                T peer_addend = ThreadLoad<LOAD_VOLATILE>(&temp_storage.reduce[lane_id + OFFSET]);\n                input = reduction_op(input, peer_addend);\n            }\n\n            WARP_SYNC(member_mask);\n        }\n\n        return input;\n    }\n\n\n    /**\n     * Smem-based segmented reduce\n     */\n    template <\n        bool            HEAD_SEGMENTED,     ///< Whether flags indicate a segment-head or a segment-tail\n        typename        FlagT,\n        typename        ReductionOp>\n    __device__ __forceinline__ T SegmentedReduce(\n        T               input,                  ///< [in] Calling thread's input\n        FlagT           flag,                   ///< [in] Whether or not the current lane is a segment head/tail\n        ReductionOp     reduction_op,           ///< [in] Reduction operator\n        Int2Type<false> /*has_ballot*/)         ///< [in] Marker type for whether the target arch has ballot functionality\n    {\n        enum\n        {\n            UNSET   = 0x0,  // Is initially unset\n            SET     = 0x1,  // Is initially set\n            SEEN    = 0x2,  // Has seen another head flag from a successor peer\n        };\n\n        // Alias flags onto shared data storage\n        volatile SmemFlag *flag_storage = temp_storage.flags;\n\n        SmemFlag flag_status = (flag) ? SET : UNSET;\n\n        for (int STEP = 0; STEP < STEPS; STEP++)\n        {\n            const int OFFSET = 1 << STEP;\n\n            // Share input through buffer\n            ThreadStore<STORE_VOLATILE>(&temp_storage.reduce[lane_id], input);\n\n            WARP_SYNC(member_mask);\n\n            // Get peer from buffer\n            T peer_addend = ThreadLoad<LOAD_VOLATILE>(&temp_storage.reduce[lane_id + OFFSET]);\n\n            WARP_SYNC(member_mask);\n\n            // Share flag through buffer\n            flag_storage[lane_id] = flag_status;\n\n            // Get peer flag from buffer\n            SmemFlag peer_flag_status = flag_storage[lane_id + OFFSET];\n\n            // Update input if peer was in range\n            if (lane_id < LOGICAL_WARP_THREADS - OFFSET)\n            {\n                if (HEAD_SEGMENTED)\n                {\n                    // Head-segmented\n                    if ((flag_status & SEEN) == 0)\n                    {\n                        // Has not seen a more distant head flag\n                        if (peer_flag_status & SET)\n                        {\n                            // Has now seen a head flag\n                            flag_status |= SEEN;\n                        }\n                        else\n                        {\n                            // Peer is not a head flag: grab its count\n                            input = reduction_op(input, peer_addend);\n                        }\n\n                        // Update seen status to include that of peer\n                        flag_status |= (peer_flag_status & SEEN);\n                    }\n                }\n                else\n                {\n                    // Tail-segmented.  Simply propagate flag status\n                    if (!flag_status)\n                    {\n                        input = reduction_op(input, peer_addend);\n                        flag_status |= peer_flag_status;\n                    }\n\n                }\n            }\n        }\n\n        return input;\n    }\n\n\n    /******************************************************************************\n     * Interface\n     ******************************************************************************/\n\n    /**\n     * Reduction\n     */\n    template <\n        bool                ALL_LANES_VALID,        ///< Whether all lanes in each warp are contributing a valid fold of items\n        int                 FOLDED_ITEMS_PER_LANE,  ///< Number of items folded into each lane\n        typename            ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   input,                  ///< [in] Calling thread's input\n        int                 folded_items_per_warp,  ///< [in] Total number of valid items folded into each logical warp\n        ReductionOp         reduction_op)           ///< [in] Reduction operator\n    {\n        return ReduceStep<ALL_LANES_VALID, FOLDED_ITEMS_PER_LANE>(input, folded_items_per_warp, reduction_op, Int2Type<0>());\n    }\n\n\n    /**\n     * Segmented reduction\n     */\n    template <\n        bool            HEAD_SEGMENTED,     ///< Whether flags indicate a segment-head or a segment-tail\n        typename        FlagT,\n        typename        ReductionOp>\n    __device__ __forceinline__ T SegmentedReduce(\n        T               input,              ///< [in] Calling thread's input\n        FlagT            flag,               ///< [in] Whether or not the current lane is a segment head/tail\n        ReductionOp     reduction_op)       ///< [in] Reduction operator\n    {\n        return SegmentedReduce<HEAD_SEGMENTED>(input, flag, reduction_op, Int2Type<(PTX_ARCH >= 200)>());\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/specializations/warp_scan_shfl.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::WarpScanShfl provides SHFL-based variants of parallel prefix scan of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_ptx.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief WarpScanShfl provides SHFL-based variants of parallel prefix scan of items partitioned across a CUDA thread warp.\n *\n * LOGICAL_WARP_THREADS must be a power-of-two\n */\ntemplate <\n    typename    T,                      ///< Data type being scanned\n    int         LOGICAL_WARP_THREADS,   ///< Number of threads per logical warp\n    int         PTX_ARCH>               ///< The PTX compute capability for which to to specialize this collective\nstruct WarpScanShfl\n{\n    //---------------------------------------------------------------------\n    // Constants and type definitions\n    //---------------------------------------------------------------------\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// The number of warp scan steps\n        STEPS = Log2<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// The 5-bit SHFL mask for logically splitting warps into sub-segments starts 8-bits up\n        SHFL_C = ((0xFFFFFFFFU << STEPS) & 31) << 8,\n    };\n\n    template <typename S>\n    struct IntegerTraits\n    {\n        enum {\n            ///Whether the data type is a small (32b or less) integer for which we can use a single SFHL instruction per exchange\n            IS_SMALL_UNSIGNED = (Traits<S>::CATEGORY == UNSIGNED_INTEGER) && (sizeof(S) <= sizeof(unsigned int))\n        };\n    };\n\n    /// Shared memory storage layout type\n    struct TempStorage {};\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    unsigned int lane_id;\n\n    unsigned int member_mask;\n\n    //---------------------------------------------------------------------\n    // Construction\n    //---------------------------------------------------------------------\n\n    /// Constructor\n    __device__ __forceinline__ WarpScanShfl(\n        TempStorage &/*temp_storage*/)\n    :\n        lane_id(LaneId()),\n\n        member_mask((0xffffffff >> (32 - LOGICAL_WARP_THREADS)) << ((IS_ARCH_WARP) ?\n            0 : // arch-width subwarps need not be tiled within the arch-warp\n            ((lane_id / LOGICAL_WARP_THREADS) * LOGICAL_WARP_THREADS)))\n    {}\n\n\n    //---------------------------------------------------------------------\n    // Inclusive scan steps\n    //---------------------------------------------------------------------\n\n    /// Inclusive prefix scan step (specialized for summation across int32 types)\n    __device__ __forceinline__ int InclusiveScanStep(\n        int             input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        int output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .s32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.sync.up.b32 r0|p, %1, %2, %3, %5;\"\n            \"  @p add.s32 r0, r0, %4;\"\n            \"  mov.s32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(shfl_c), \"r\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .s32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.up.b32 r0|p, %1, %2, %3;\"\n            \"  @p add.s32 r0, r0, %4;\"\n            \"  mov.s32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(shfl_c), \"r\"(input));\n#endif\n\n        return output;\n    }\n\n    /// Inclusive prefix scan step (specialized for summation across uint32 types)\n    __device__ __forceinline__ unsigned int InclusiveScanStep(\n        unsigned int    input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        unsigned int output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.sync.up.b32 r0|p, %1, %2, %3, %5;\"\n            \"  @p add.u32 r0, r0, %4;\"\n            \"  mov.u32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(shfl_c), \"r\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.up.b32 r0|p, %1, %2, %3;\"\n            \"  @p add.u32 r0, r0, %4;\"\n            \"  mov.u32 %0, r0;\"\n            \"}\"\n            : \"=r\"(output) : \"r\"(input), \"r\"(offset), \"r\"(shfl_c), \"r\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Inclusive prefix scan step (specialized for summation across fp32 types)\n    __device__ __forceinline__ float InclusiveScanStep(\n        float           input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        float output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .f32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.sync.up.b32 r0|p, %1, %2, %3, %5;\"\n            \"  @p add.f32 r0, r0, %4;\"\n            \"  mov.f32 %0, r0;\"\n            \"}\"\n            : \"=f\"(output) : \"f\"(input), \"r\"(offset), \"r\"(shfl_c), \"f\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .f32 r0;\"\n            \"  .reg .pred p;\"\n            \"  shfl.up.b32 r0|p, %1, %2, %3;\"\n            \"  @p add.f32 r0, r0, %4;\"\n            \"  mov.f32 %0, r0;\"\n            \"}\"\n            : \"=f\"(output) : \"f\"(input), \"r\"(offset), \"r\"(shfl_c), \"f\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Inclusive prefix scan step (specialized for summation across unsigned long long types)\n    __device__ __forceinline__ unsigned long long InclusiveScanStep(\n        unsigned long long  input,              ///< [in] Calling thread's input item.\n        cub::Sum            /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        unsigned long long output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u64 r0;\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.up.b32 lo|p, lo, %2, %3, %5;\"\n            \"  shfl.sync.up.b32 hi|p, hi, %2, %3, %5;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.u64 r0, r0, %4;\"\n            \"  mov.u64 %0, r0;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(shfl_c), \"l\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u64 r0;\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.up.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.up.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.u64 r0, r0, %4;\"\n            \"  mov.u64 %0, r0;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(shfl_c), \"l\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Inclusive prefix scan step (specialized for summation across long long types)\n    __device__ __forceinline__ long long InclusiveScanStep(\n        long long       input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        long long output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .s64 r0;\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.up.b32 lo|p, lo, %2, %3, %5;\"\n            \"  shfl.sync.up.b32 hi|p, hi, %2, %3, %5;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.s64 r0, r0, %4;\"\n            \"  mov.s64 %0, r0;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(shfl_c), \"l\"(input), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .s64 r0;\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.up.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.up.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.s64 r0, r0, %4;\"\n            \"  mov.s64 %0, r0;\"\n            \"}\"\n            : \"=l\"(output) : \"l\"(input), \"r\"(offset), \"r\"(shfl_c), \"l\"(input));\n#endif\n\n        return output;\n    }\n\n\n    /// Inclusive prefix scan step (specialized for summation across fp64 types)\n    __device__ __forceinline__ double InclusiveScanStep(\n        double          input,              ///< [in] Calling thread's input item.\n        cub::Sum        /*scan_op*/,        ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        double output;\n        int shfl_c = first_lane | SHFL_C;   // Shuffle control (mask and first-lane)\n\n        // Use predicate set from SHFL to guard against invalid peers\n#ifdef CUB_USE_COOPERATIVE_GROUPS\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  .reg .f64 r0;\"\n            \"  mov.b64 %0, %1;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.sync.up.b32 lo|p, lo, %2, %3, %4;\"\n            \"  shfl.sync.up.b32 hi|p, hi, %2, %3, %4;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.f64 %0, %0, r0;\"\n            \"}\"\n            : \"=d\"(output) : \"d\"(input), \"r\"(offset), \"r\"(shfl_c), \"r\"(member_mask));\n#else\n        asm volatile(\n            \"{\"\n            \"  .reg .u32 lo;\"\n            \"  .reg .u32 hi;\"\n            \"  .reg .pred p;\"\n            \"  .reg .f64 r0;\"\n            \"  mov.b64 %0, %1;\"\n            \"  mov.b64 {lo, hi}, %1;\"\n            \"  shfl.up.b32 lo|p, lo, %2, %3;\"\n            \"  shfl.up.b32 hi|p, hi, %2, %3;\"\n            \"  mov.b64 r0, {lo, hi};\"\n            \"  @p add.f64 %0, %0, r0;\"\n            \"}\"\n            : \"=d\"(output) : \"d\"(input), \"r\"(offset), \"r\"(shfl_c));\n#endif\n\n        return output;\n    }\n\n\n/*\n    /// Inclusive prefix scan (specialized for ReduceBySegmentOp<cub::Sum> across KeyValuePair<OffsetT, Value> types)\n    template <typename Value, typename OffsetT>\n    __device__ __forceinline__ KeyValuePair<OffsetT, Value>InclusiveScanStep(\n        KeyValuePair<OffsetT, Value>    input,              ///< [in] Calling thread's input item.\n        ReduceBySegmentOp<cub::Sum>     scan_op,            ///< [in] Binary scan operator\n        int                             first_lane,         ///< [in] Index of first lane in segment\n        int                             offset)             ///< [in] Up-offset to pull from\n    {\n        KeyValuePair<OffsetT, Value> output;\n\n        output.value = InclusiveScanStep(input.value, cub::Sum(), first_lane, offset, Int2Type<IntegerTraits<Value>::IS_SMALL_UNSIGNED>());\n        output.key = InclusiveScanStep(input.key, cub::Sum(), first_lane, offset, Int2Type<IntegerTraits<OffsetT>::IS_SMALL_UNSIGNED>());\n\n        if (input.key > 0)\n            output.value = input.value;\n\n        return output;\n    }\n*/\n\n    /// Inclusive prefix scan step (generic)\n    template <typename _T, typename ScanOpT>\n    __device__ __forceinline__ _T InclusiveScanStep(\n        _T              input,              ///< [in] Calling thread's input item.\n        ScanOpT          scan_op,            ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset)             ///< [in] Up-offset to pull from\n    {\n        _T temp = ShuffleUp(input, offset, first_lane, member_mask);\n\n        // Perform scan op if from a valid peer\n        _T output = scan_op(temp, input);\n        if (static_cast<int>(lane_id) < first_lane + offset)\n            output = input;\n\n        return output;\n    }\n\n\n    /// Inclusive prefix scan step (specialized for small integers size 32b or less)\n    template <typename _T, typename ScanOpT>\n    __device__ __forceinline__ _T InclusiveScanStep(\n        _T              input,              ///< [in] Calling thread's input item.\n        ScanOpT          scan_op,            ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset,             ///< [in] Up-offset to pull from\n        Int2Type<true>  /*is_small_unsigned*/)  ///< [in] Marker type indicating whether T is a small integer\n    {\n        return InclusiveScanStep(input, scan_op, first_lane, offset);\n    }\n\n\n    /// Inclusive prefix scan step (specialized for types other than small integers size 32b or less)\n    template <typename _T, typename ScanOpT>\n    __device__ __forceinline__ _T InclusiveScanStep(\n        _T              input,              ///< [in] Calling thread's input item.\n        ScanOpT          scan_op,            ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        int             offset,             ///< [in] Up-offset to pull from\n        Int2Type<false> /*is_small_unsigned*/)  ///< [in] Marker type indicating whether T is a small integer\n    {\n        return InclusiveScanStep(input, scan_op, first_lane, offset);\n    }\n\n    //---------------------------------------------------------------------\n    // Templated inclusive scan iteration\n    //---------------------------------------------------------------------\n\n    template <typename _T, typename ScanOp, int STEP>\n    __device__ __forceinline__ void InclusiveScanStep(\n        _T&             input,              ///< [in] Calling thread's input item.\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        int             first_lane,         ///< [in] Index of first lane in segment\n        Int2Type<STEP>  /*step*/)               ///< [in] Marker type indicating scan step\n    {\n        input = InclusiveScanStep(input, scan_op, first_lane, 1 << STEP, Int2Type<IntegerTraits<T>::IS_SMALL_UNSIGNED>());\n\n        InclusiveScanStep(input, scan_op, first_lane, Int2Type<STEP + 1>());\n    }\n\n    template <typename _T, typename ScanOp>\n    __device__ __forceinline__ void InclusiveScanStep(\n        _T&             /*input*/,              ///< [in] Calling thread's input item.\n        ScanOp          /*scan_op*/,            ///< [in] Binary scan operator\n        int             /*first_lane*/,         ///< [in] Index of first lane in segment\n        Int2Type<STEPS> /*step*/)               ///< [in] Marker type indicating scan step\n    {}\n\n\n    /******************************************************************************\n     * Interface\n     ******************************************************************************/\n\n    //---------------------------------------------------------------------\n    // Broadcast\n    //---------------------------------------------------------------------\n\n    /// Broadcast\n    __device__ __forceinline__ T Broadcast(\n        T               input,              ///< [in] The value to broadcast\n        int             src_lane)           ///< [in] Which warp lane is to do the broadcasting\n    {\n        return ShuffleIndex(input, src_lane, LOGICAL_WARP_THREADS, member_mask);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive operations\n    //---------------------------------------------------------------------\n\n    /// Inclusive scan\n    template <typename _T, typename ScanOpT>\n    __device__ __forceinline__ void InclusiveScan(\n        _T              input,              ///< [in] Calling thread's input item.\n        _T              &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOpT         scan_op)            ///< [in] Binary scan operator\n    {\n        inclusive_output = input;\n\n        // Iterate scan steps\n        int segment_first_lane = 0;\n\n        // Iterate scan steps\n//        InclusiveScanStep(inclusive_output, scan_op, segment_first_lane, Int2Type<0>());\n\n        // Iterate scan steps\n        #pragma unroll\n        for (int STEP = 0; STEP < STEPS; STEP++)\n        {\n            inclusive_output = InclusiveScanStep(\n                inclusive_output,\n                scan_op,\n                segment_first_lane,\n                (1 << STEP),\n                Int2Type<IntegerTraits<T>::IS_SMALL_UNSIGNED>());\n        }\n\n    }\n\n    /// Inclusive scan, specialized for reduce-value-by-key\n    template <typename KeyT, typename ValueT, typename ReductionOpT>\n    __device__ __forceinline__ void InclusiveScan(\n        KeyValuePair<KeyT, ValueT>      input,              ///< [in] Calling thread's input item.\n        KeyValuePair<KeyT, ValueT>      &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ReduceByKeyOp<ReductionOpT >    scan_op)            ///< [in] Binary scan operator\n    {\n        inclusive_output = input;\n\n        KeyT pred_key = ShuffleUp(inclusive_output.key, 1, 0, member_mask);\n\n        unsigned int ballot = WARP_BALLOT((pred_key != inclusive_output.key), member_mask);\n\n        // Mask away all lanes greater than ours\n        ballot = ballot & LaneMaskLe();\n\n        // Find index of first set bit\n        int segment_first_lane = CUB_MAX(0, 31 - __clz(ballot));\n\n        // Iterate scan steps\n//        InclusiveScanStep(inclusive_output.value, scan_op.op, segment_first_lane, Int2Type<0>());\n\n        // Iterate scan steps\n        #pragma unroll\n        for (int STEP = 0; STEP < STEPS; STEP++)\n        {\n            inclusive_output.value = InclusiveScanStep(\n                inclusive_output.value,\n                scan_op.op,\n                segment_first_lane,\n                (1 << STEP),\n                Int2Type<IntegerTraits<T>::IS_SMALL_UNSIGNED>());\n        }\n    }\n\n\n    /// Inclusive scan with aggregate\n    template <typename ScanOpT>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOpT         scan_op,            ///< [in] Binary scan operator\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InclusiveScan(input, inclusive_output, scan_op);\n\n        // Grab aggregate from last warp lane\n        warp_aggregate = ShuffleIndex(inclusive_output, LOGICAL_WARP_THREADS - 1, LOGICAL_WARP_THREADS, member_mask);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Get exclusive from inclusive\n    //---------------------------------------------------------------------\n\n    /// Update inclusive and exclusive using input and inclusive\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update(\n        T                       /*input*/,          ///< [in]\n        T                       &inclusive,         ///< [in, out]\n        T                       &exclusive,         ///< [out]\n        ScanOpT                 /*scan_op*/,        ///< [in]\n        IsIntegerT              /*is_integer*/)     ///< [in]\n    {\n        // initial value unknown\n        exclusive = ShuffleUp(inclusive, 1, 0, member_mask);\n    }\n\n    /// Update inclusive and exclusive using input and inclusive (specialized for summation of integer types)\n    __device__ __forceinline__ void Update(\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        cub::Sum                /*scan_op*/,\n        Int2Type<true>          /*is_integer*/)\n    {\n        // initial value presumed 0\n        exclusive = inclusive - input;\n    }\n\n    /// Update inclusive and exclusive using initial value using input, inclusive, and initial value\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       /*input*/,\n        T                       &inclusive,\n        T                       &exclusive,\n        ScanOpT                 scan_op,\n        T                       initial_value,\n        IsIntegerT              /*is_integer*/)\n    {\n        inclusive = scan_op(initial_value, inclusive);\n        exclusive = ShuffleUp(inclusive, 1, 0, member_mask);\n\n        unsigned int segment_id = (IS_ARCH_WARP) ?\n            lane_id :\n            lane_id % LOGICAL_WARP_THREADS;\n\n        if (segment_id == 0)\n            exclusive = initial_value;\n    }\n\n    /// Update inclusive and exclusive using initial value using input and inclusive (specialized for summation of integer types)\n    __device__ __forceinline__ void Update (\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        cub::Sum                scan_op,\n        T                       initial_value,\n        Int2Type<true>          /*is_integer*/)\n    {\n        inclusive = scan_op(initial_value, inclusive);\n        exclusive = inclusive - input;\n    }\n\n\n    /// Update inclusive, exclusive, and warp aggregate using input and inclusive\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        T                       &warp_aggregate,\n        ScanOpT                 scan_op,\n        IsIntegerT              is_integer)\n    {\n        warp_aggregate = ShuffleIndex(inclusive, LOGICAL_WARP_THREADS - 1, LOGICAL_WARP_THREADS, member_mask);\n        Update(input, inclusive, exclusive, scan_op, is_integer);\n    }\n\n    /// Update inclusive, exclusive, and warp aggregate using input, inclusive, and initial value\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        T                       &warp_aggregate,\n        ScanOpT                 scan_op,\n        T                       initial_value,\n        IsIntegerT              is_integer)\n    {\n        warp_aggregate = ShuffleIndex(inclusive, LOGICAL_WARP_THREADS - 1, LOGICAL_WARP_THREADS, member_mask);\n        Update(input, inclusive, exclusive, scan_op, initial_value, is_integer);\n    }\n\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/specializations/warp_scan_smem.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * cub::WarpScanSmem provides smem-based variants of parallel prefix scan of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"../../thread/thread_operators.cuh\"\n#include \"../../thread/thread_load.cuh\"\n#include \"../../thread/thread_store.cuh\"\n#include \"../../util_type.cuh\"\n#include \"../../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\brief WarpScanSmem provides smem-based variants of parallel prefix scan of items partitioned across a CUDA thread warp.\n */\ntemplate <\n    typename    T,                      ///< Data type being scanned\n    int         LOGICAL_WARP_THREADS,   ///< Number of threads per logical warp\n    int         PTX_ARCH>               ///< The PTX compute capability for which to to specialize this collective\nstruct WarpScanSmem\n{\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// Whether the logical warp size is a power-of-two\n        IS_POW_OF_TWO = PowerOfTwo<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// The number of warp scan steps\n        STEPS = Log2<LOGICAL_WARP_THREADS>::VALUE,\n\n        /// The number of threads in half a warp\n        HALF_WARP_THREADS = 1 << (STEPS - 1),\n\n        /// The number of shared memory elements per warp\n        WARP_SMEM_ELEMENTS =  LOGICAL_WARP_THREADS + HALF_WARP_THREADS,\n    };\n\n    /// Storage cell type (workaround for SM1x compiler bugs with custom-ops like Max() on signed chars)\n    typedef typename If<((Equals<T, char>::VALUE || Equals<T, signed char>::VALUE) && (PTX_ARCH < 200)), int, T>::Type CellT;\n\n    /// Shared memory storage layout type (1.5 warps-worth of elements for each warp)\n    typedef CellT _TempStorage[WARP_SMEM_ELEMENTS];\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    _TempStorage    &temp_storage;\n    unsigned int    lane_id;\n    unsigned int    member_mask;\n\n\n    /******************************************************************************\n     * Construction\n     ******************************************************************************/\n\n    /// Constructor\n    __device__ __forceinline__ WarpScanSmem(\n        TempStorage     &temp_storage)\n    :\n        temp_storage(temp_storage.Alias()),\n\n        lane_id(IS_ARCH_WARP ?\n            LaneId() :\n            LaneId() % LOGICAL_WARP_THREADS),\n\n        member_mask((0xffffffff >> (32 - LOGICAL_WARP_THREADS)) << ((IS_ARCH_WARP || !IS_POW_OF_TWO ) ?\n            0 : // arch-width and non-power-of-two subwarps cannot be tiled with the arch-warp\n            ((LaneId() / LOGICAL_WARP_THREADS) * LOGICAL_WARP_THREADS)))\n    {}\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\n    /// Basic inclusive scan iteration (template unrolled, inductive-case specialization)\n    template <\n        bool        HAS_IDENTITY,\n        int         STEP,\n        typename    ScanOp>\n    __device__ __forceinline__ void ScanStep(\n        T                       &partial,\n        ScanOp                  scan_op,\n        Int2Type<STEP>          /*step*/)\n    {\n        const int OFFSET = 1 << STEP;\n\n        // Share partial into buffer\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) partial);\n\n        WARP_SYNC(member_mask);\n\n        // Update partial if addend is in range\n        if (HAS_IDENTITY || (lane_id >= OFFSET))\n        {\n            T addend = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - OFFSET]);\n            partial = scan_op(addend, partial);\n        }\n        WARP_SYNC(member_mask);\n\n        ScanStep<HAS_IDENTITY>(partial, scan_op, Int2Type<STEP + 1>());\n    }\n\n\n    /// Basic inclusive scan iteration(template unrolled, base-case specialization)\n    template <\n        bool        HAS_IDENTITY,\n        typename    ScanOp>\n    __device__ __forceinline__ void ScanStep(\n        T                       &/*partial*/,\n        ScanOp                  /*scan_op*/,\n        Int2Type<STEPS>         /*step*/)\n    {}\n\n\n    /// Inclusive prefix scan (specialized for summation across primitive types)\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,              ///< [in] Calling thread's input item.\n        T                       &output,            ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        Sum                     scan_op,            ///< [in] Binary scan operator\n        Int2Type<true>          /*is_primitive*/)   ///< [in] Marker type indicating whether T is primitive type\n    {\n        T identity = 0;\n        ThreadStore<STORE_VOLATILE>(&temp_storage[lane_id], (CellT) identity);\n\n        WARP_SYNC(member_mask);\n\n        // Iterate scan steps\n        output = input;\n        ScanStep<true>(output, scan_op, Int2Type<0>());\n    }\n\n\n    /// Inclusive prefix scan\n    template <typename ScanOp, int IS_PRIMITIVE>\n    __device__ __forceinline__ void InclusiveScan(\n        T                       input,              ///< [in] Calling thread's input item.\n        T                       &output,            ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp                  scan_op,            ///< [in] Binary scan operator\n        Int2Type<IS_PRIMITIVE>  /*is_primitive*/)   ///< [in] Marker type indicating whether T is primitive type\n    {\n        // Iterate scan steps\n        output = input;\n        ScanStep<false>(output, scan_op, Int2Type<0>());\n    }\n\n\n    /******************************************************************************\n     * Interface\n     ******************************************************************************/\n\n    //---------------------------------------------------------------------\n    // Broadcast\n    //---------------------------------------------------------------------\n\n    /// Broadcast\n    __device__ __forceinline__ T Broadcast(\n        T               input,              ///< [in] The value to broadcast\n        unsigned int    src_lane)           ///< [in] Which warp lane is to do the broadcasting\n    {\n        if (lane_id == src_lane)\n        {\n            ThreadStore<STORE_VOLATILE>(temp_storage, (CellT) input);\n        }\n\n        WARP_SYNC(member_mask);\n\n        return (T)ThreadLoad<LOAD_VOLATILE>(temp_storage);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Inclusive operations\n    //---------------------------------------------------------------------\n\n    /// Inclusive scan\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InclusiveScan(input, inclusive_output, scan_op, Int2Type<Traits<T>::PRIMITIVE>());\n    }\n\n\n    /// Inclusive scan with aggregate\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InclusiveScan(input, inclusive_output, scan_op);\n\n        // Retrieve aggregate\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive_output);\n\n        WARP_SYNC(member_mask);\n\n        warp_aggregate = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[WARP_SMEM_ELEMENTS - 1]);\n\n        WARP_SYNC(member_mask);\n    }\n\n\n    //---------------------------------------------------------------------\n    // Get exclusive from inclusive\n    //---------------------------------------------------------------------\n\n    /// Update inclusive and exclusive using input and inclusive\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update(\n        T                       /*input*/,      ///< [in]\n        T                       &inclusive,     ///< [in, out]\n        T                       &exclusive,     ///< [out]\n        ScanOpT                 /*scan_op*/,    ///< [in]\n        IsIntegerT              /*is_integer*/) ///< [in]\n    {\n        // initial value unknown\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        exclusive = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - 1]);\n    }\n\n    /// Update inclusive and exclusive using input and inclusive (specialized for summation of integer types)\n    __device__ __forceinline__ void Update(\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        cub::Sum                /*scan_op*/,\n        Int2Type<true>          /*is_integer*/)\n    {\n        // initial value presumed 0\n        exclusive = inclusive - input;\n    }\n\n    /// Update inclusive and exclusive using initial value using input, inclusive, and initial value\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       /*input*/,\n        T                       &inclusive,\n        T                       &exclusive,\n        ScanOpT                 scan_op,\n        T                       initial_value,\n        IsIntegerT              /*is_integer*/)\n    {\n        inclusive = scan_op(initial_value, inclusive);\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        exclusive = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - 1]);\n        if (lane_id == 0)\n            exclusive = initial_value;\n    }\n\n    /// Update inclusive and exclusive using initial value using input and inclusive (specialized for summation of integer types)\n    __device__ __forceinline__ void Update (\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        cub::Sum                scan_op,\n        T                       initial_value,\n        Int2Type<true>          /*is_integer*/)\n    {\n        inclusive = scan_op(initial_value, inclusive);\n        exclusive = inclusive - input;\n    }\n\n\n    /// Update inclusive, exclusive, and warp aggregate using input and inclusive\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       /*input*/,\n        T                       &inclusive,\n        T                       &exclusive,\n        T                       &warp_aggregate,\n        ScanOpT                 /*scan_op*/,\n        IsIntegerT              /*is_integer*/)\n    {\n        // Initial value presumed to be unknown or identity (either way our padding is correct)\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        exclusive = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - 1]);\n        warp_aggregate = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[WARP_SMEM_ELEMENTS - 1]);\n    }\n\n    /// Update inclusive, exclusive, and warp aggregate using input and inclusive (specialized for summation of integer types)\n    __device__ __forceinline__ void Update (\n        T                       input,\n        T                       &inclusive,\n        T                       &exclusive,\n        T                       &warp_aggregate,\n        cub::Sum                /*scan_o*/,\n        Int2Type<true>          /*is_integer*/)\n    {\n        // Initial value presumed to be unknown or identity (either way our padding is correct)\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        warp_aggregate = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[WARP_SMEM_ELEMENTS - 1]);\n        exclusive = inclusive - input;\n    }\n\n    /// Update inclusive, exclusive, and warp aggregate using input, inclusive, and initial value\n    template <typename ScanOpT, typename IsIntegerT>\n    __device__ __forceinline__ void Update (\n        T                       /*input*/,\n        T                       &inclusive,\n        T                       &exclusive,\n        T                       &warp_aggregate,\n        ScanOpT                 scan_op,\n        T                       initial_value,\n        IsIntegerT              /*is_integer*/)\n    {\n        // Broadcast warp aggregate\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        warp_aggregate = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[WARP_SMEM_ELEMENTS - 1]);\n\n        WARP_SYNC(member_mask);\n\n        // Update inclusive with initial value\n        inclusive = scan_op(initial_value, inclusive);\n\n        // Get exclusive from exclusive\n        ThreadStore<STORE_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - 1], (CellT) inclusive);\n\n        WARP_SYNC(member_mask);\n\n        exclusive = (T) ThreadLoad<LOAD_VOLATILE>(&temp_storage[HALF_WARP_THREADS + lane_id - 2]);\n\n        if (lane_id == 0)\n            exclusive = initial_value;\n    }\n\n\n};\n\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/warp_reduce.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::WarpReduce class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel reduction of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"specializations/warp_reduce_shfl.cuh\"\n#include \"specializations/warp_reduce_smem.cuh\"\n#include \"../thread/thread_operators.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n\n/**\n * \\addtogroup WarpModule\n * @{\n */\n\n/**\n * \\brief The WarpReduce class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel reduction of items partitioned across a CUDA thread warp. ![](warp_reduce_logo.png)\n *\n * \\tparam T                        The reduction input/output element type\n * \\tparam LOGICAL_WARP_THREADS     <b>[optional]</b> The number of threads per \"logical\" warp (may be less than the number of hardware warp threads).  Default is the warp size of the targeted CUDA compute-capability (e.g., 32 threads for SM20).\n * \\tparam PTX_ARCH                 <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - A <a href=\"http://en.wikipedia.org/wiki/Reduce_(higher-order_function)\"><em>reduction</em></a> (or <em>fold</em>)\n *   uses a binary combining operator to compute a single aggregate from a list of input elements.\n * - Supports \"logical\" warps smaller than the physical warp size (e.g., logical warps of 8 threads)\n * - The number of entrant threads must be an multiple of \\p LOGICAL_WARP_THREADS\n *\n * \\par Performance Considerations\n * - Uses special instructions when applicable (e.g., warp \\p SHFL instructions)\n * - Uses synchronization-free communication between warp lanes when applicable\n * - Incurs zero bank conflicts for most types\n * - Computation is slightly more efficient (i.e., having lower instruction overhead) for:\n *     - Summation (<b><em>vs.</em></b> generic reduction)\n *     - The architecture's warp size is a whole multiple of \\p LOGICAL_WARP_THREADS\n *\n * \\par Simple Examples\n * \\warpcollective{WarpReduce}\n * \\par\n * The code snippet below illustrates four concurrent warp sum reductions within a block of\n * 128 threads (one per each of the 32-thread warps).\n * \\par\n * \\code\n * #include <cub/cub.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize WarpReduce for type int\n *     typedef cub::WarpReduce<int> WarpReduce;\n *\n *     // Allocate WarpReduce shared memory for 4 warps\n *     __shared__ typename WarpReduce::TempStorage temp_storage[4];\n *\n *     // Obtain one input item per thread\n *     int thread_data = ...\n *\n *     // Return the warp-wide sums to each lane0 (threads 0, 32, 64, and 96)\n *     int warp_id = threadIdx.x / 32;\n *     int aggregate = WarpReduce(temp_storage[warp_id]).Sum(thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, 1, 2, 3, ..., 127}</tt>.\n * The corresponding output \\p aggregate in threads 0, 32, 64, and 96 will \\p 496, \\p 1520,\n * \\p 2544, and \\p 3568, respectively (and is undefined in other threads).\n *\n * \\par\n * The code snippet below illustrates a single warp sum reduction within a block of\n * 128 threads.\n * \\par\n * \\code\n * #include <cub/cub.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize WarpReduce for type int\n *     typedef cub::WarpReduce<int> WarpReduce;\n *\n *     // Allocate WarpReduce shared memory for one warp\n *     __shared__ typename WarpReduce::TempStorage temp_storage;\n *     ...\n *\n *     // Only the first warp performs a reduction\n *     if (threadIdx.x < 32)\n *     {\n *         // Obtain one input item per thread\n *         int thread_data = ...\n *\n *         // Return the warp-wide sum to lane0\n *         int aggregate = WarpReduce(temp_storage).Sum(thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the warp of threads is <tt>{0, 1, 2, 3, ..., 31}</tt>.\n * The corresponding output \\p aggregate in thread0 will be \\p 496 (and is undefined in other threads).\n *\n */\ntemplate <\n    typename    T,\n    int         LOGICAL_WARP_THREADS    = CUB_PTX_WARP_THREADS,\n    int         PTX_ARCH                = CUB_PTX_ARCH>\nclass WarpReduce\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// Whether the logical warp size is a power-of-two\n        IS_POW_OF_TWO = PowerOfTwo<LOGICAL_WARP_THREADS>::VALUE,\n    };\n\npublic:\n\n    #ifndef DOXYGEN_SHOULD_SKIP_THIS    // Do not document\n\n    /// Internal specialization.  Use SHFL-based reduction if (architecture is >= SM30) and (LOGICAL_WARP_THREADS is a power-of-two)\n    typedef typename If<(PTX_ARCH >= 300) && (IS_POW_OF_TWO),\n        WarpReduceShfl<T, LOGICAL_WARP_THREADS, PTX_ARCH>,\n        WarpReduceSmem<T, LOGICAL_WARP_THREADS, PTX_ARCH> >::Type InternalWarpReduce;\n\n    #endif // DOXYGEN_SHOULD_SKIP_THIS\n\n\nprivate:\n\n    /// Shared memory storage layout type for WarpReduce\n    typedef typename InternalWarpReduce::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage &temp_storage;\n\n\n    /******************************************************************************\n     * Utility methods\n     ******************************************************************************/\n\npublic:\n\n    /// \\smemstorage{WarpReduce}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.  Logical warp and lane identifiers are constructed from <tt>threadIdx.x</tt>.\n     */\n    __device__ __forceinline__ WarpReduce(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias())\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Summation reductions\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes a warp-wide sum in the calling warp.  The output is valid in warp <em>lane</em><sub>0</sub>.\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp sum reductions within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for 4 warps\n     *     __shared__ typename WarpReduce::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Return the warp-wide sums to each lane0\n     *     int warp_id = threadIdx.x / 32;\n     *     int aggregate = WarpReduce(temp_storage[warp_id]).Sum(thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, 1, 2, 3, ..., 127}</tt>.\n     * The corresponding output \\p aggregate in threads 0, 32, 64, and 96 will \\p 496, \\p 1520,\n     * \\p 2544, and \\p 3568, respectively (and is undefined in other threads).\n     *\n     */\n    __device__ __forceinline__ T Sum(\n        T                   input)              ///< [in] Calling thread's input\n    {\n        return InternalWarpReduce(temp_storage).template Reduce<true, 1>(input, LOGICAL_WARP_THREADS, cub::Sum());\n    }\n\n    /**\n     * \\brief Computes a partially-full warp-wide sum in the calling warp.  The output is valid in warp <em>lane</em><sub>0</sub>.\n     *\n     * All threads across the calling warp must agree on the same value for \\p valid_items.  Otherwise the result is undefined.\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a sum reduction within a single, partially-full\n     * block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, int valid_items)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item per thread if in range\n     *     int thread_data;\n     *     if (threadIdx.x < valid_items)\n     *         thread_data = d_data[threadIdx.x];\n     *\n     *     // Return the warp-wide sums to each lane0\n     *     int aggregate = WarpReduce(temp_storage).Sum(\n     *         thread_data, valid_items);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>{0, 1, 2, 3, 4, ...</tt> and \\p valid_items\n     * is \\p 4.  The corresponding output \\p aggregate in thread0 is \\p 6 (and is\n     * undefined in other threads).\n     *\n     */\n    __device__ __forceinline__ T Sum(\n        T                   input,              ///< [in] Calling thread's input\n        int                 valid_items)        ///< [in] Total number of valid items in the calling thread's logical warp (may be less than \\p LOGICAL_WARP_THREADS)\n    {\n        // Determine if we don't need bounds checking\n        return InternalWarpReduce(temp_storage).template Reduce<false, 1>(input, valid_items, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes a segmented sum in the calling warp where segments are defined by head-flags.  The sum of each segment is returned to the first lane in that segment (which always includes <em>lane</em><sub>0</sub>).\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a head-segmented warp sum\n     * reduction within a block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item and flag per thread\n     *     int thread_data = ...\n     *     int head_flag = ...\n     *\n     *     // Return the warp-wide sums to each lane0\n     *     int aggregate = WarpReduce(temp_storage).HeadSegmentedSum(\n     *         thread_data, head_flag);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data and \\p head_flag across the block of threads\n     * is <tt>{0, 1, 2, 3, ..., 31</tt> and is <tt>{1, 0, 0, 0, 1, 0, 0, 0, ..., 1, 0, 0, 0</tt>,\n     * respectively.  The corresponding output \\p aggregate in threads 0, 4, 8, etc. will be\n     * \\p 6, \\p 22, \\p 38, etc. (and is undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     *\n     */\n    template <\n        typename            FlagT>\n    __device__ __forceinline__ T HeadSegmentedSum(\n        T                   input,              ///< [in] Calling thread's input\n        FlagT                head_flag)          ///< [in] Head flag denoting whether or not \\p input is the start of a new segment\n    {\n        return HeadSegmentedReduce(input, head_flag, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes a segmented sum in the calling warp where segments are defined by tail-flags.  The sum of each segment is returned to the first lane in that segment (which always includes <em>lane</em><sub>0</sub>).\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a tail-segmented warp sum\n     * reduction within a block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item and flag per thread\n     *     int thread_data = ...\n     *     int tail_flag = ...\n     *\n     *     // Return the warp-wide sums to each lane0\n     *     int aggregate = WarpReduce(temp_storage).TailSegmentedSum(\n     *         thread_data, tail_flag);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data and \\p tail_flag across the block of threads\n     * is <tt>{0, 1, 2, 3, ..., 31</tt> and is <tt>{0, 0, 0, 1, 0, 0, 0, 1, ..., 0, 0, 0, 1</tt>,\n     * respectively.  The corresponding output \\p aggregate in threads 0, 4, 8, etc. will be\n     * \\p 6, \\p 22, \\p 38, etc. (and is undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename            FlagT>\n    __device__ __forceinline__ T TailSegmentedSum(\n        T                   input,              ///< [in] Calling thread's input\n        FlagT                tail_flag)          ///< [in] Head flag denoting whether or not \\p input is the start of a new segment\n    {\n        return TailSegmentedReduce(input, tail_flag, cub::Sum());\n    }\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Generic reductions\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes a warp-wide reduction in the calling warp using the specified binary reduction functor.  The output is valid in warp <em>lane</em><sub>0</sub>.\n     *\n     * Supports non-commutative reduction operators\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp max reductions within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for 4 warps\n     *     __shared__ typename WarpReduce::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Return the warp-wide reductions to each lane0\n     *     int warp_id = threadIdx.x / 32;\n     *     int aggregate = WarpReduce(temp_storage[warp_id]).Reduce(\n     *         thread_data, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, 1, 2, 3, ..., 127}</tt>.\n     * The corresponding output \\p aggregate in threads 0, 32, 64, and 96 will \\p 31, \\p 63,\n     * \\p 95, and \\p 127, respectively  (and is undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   input,              ///< [in] Calling thread's input\n        ReductionOp         reduction_op)       ///< [in] Binary reduction operator\n    {\n        return InternalWarpReduce(temp_storage).template Reduce<true, 1>(input, LOGICAL_WARP_THREADS, reduction_op);\n    }\n\n    /**\n     * \\brief Computes a partially-full warp-wide reduction in the calling warp using the specified binary reduction functor.  The output is valid in warp <em>lane</em><sub>0</sub>.\n     *\n     * All threads across the calling warp must agree on the same value for \\p valid_items.  Otherwise the result is undefined.\n     *\n     * Supports non-commutative reduction operators\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a max reduction within a single, partially-full\n     * block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(int *d_data, int valid_items)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item per thread if in range\n     *     int thread_data;\n     *     if (threadIdx.x < valid_items)\n     *         thread_data = d_data[threadIdx.x];\n     *\n     *     // Return the warp-wide reductions to each lane0\n     *     int aggregate = WarpReduce(temp_storage).Reduce(\n     *         thread_data, cub::Max(), valid_items);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the input \\p d_data is <tt>{0, 1, 2, 3, 4, ...</tt> and \\p valid_items\n     * is \\p 4.  The corresponding output \\p aggregate in thread0 is \\p 3 (and is\n     * undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ReductionOp>\n    __device__ __forceinline__ T Reduce(\n        T                   input,              ///< [in] Calling thread's input\n        ReductionOp         reduction_op,       ///< [in] Binary reduction operator\n        int                 valid_items)        ///< [in] Total number of valid items in the calling thread's logical warp (may be less than \\p LOGICAL_WARP_THREADS)\n    {\n        return InternalWarpReduce(temp_storage).template Reduce<false, 1>(input, valid_items, reduction_op);\n    }\n\n\n    /**\n     * \\brief Computes a segmented reduction in the calling warp where segments are defined by head-flags.  The reduction of each segment is returned to the first lane in that segment (which always includes <em>lane</em><sub>0</sub>).\n     *\n     * Supports non-commutative reduction operators\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a head-segmented warp max\n     * reduction within a block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item and flag per thread\n     *     int thread_data = ...\n     *     int head_flag = ...\n     *\n     *     // Return the warp-wide reductions to each lane0\n     *     int aggregate = WarpReduce(temp_storage).HeadSegmentedReduce(\n     *         thread_data, head_flag, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data and \\p head_flag across the block of threads\n     * is <tt>{0, 1, 2, 3, ..., 31</tt> and is <tt>{1, 0, 0, 0, 1, 0, 0, 0, ..., 1, 0, 0, 0</tt>,\n     * respectively.  The corresponding output \\p aggregate in threads 0, 4, 8, etc. will be\n     * \\p 3, \\p 7, \\p 11, etc. (and is undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename            ReductionOp,\n        typename            FlagT>\n    __device__ __forceinline__ T HeadSegmentedReduce(\n        T                   input,              ///< [in] Calling thread's input\n        FlagT                head_flag,          ///< [in] Head flag denoting whether or not \\p input is the start of a new segment\n        ReductionOp         reduction_op)       ///< [in] Reduction operator\n    {\n        return InternalWarpReduce(temp_storage).template SegmentedReduce<true>(input, head_flag, reduction_op);\n    }\n\n\n    /**\n     * \\brief Computes a segmented reduction in the calling warp where segments are defined by tail-flags.  The reduction of each segment is returned to the first lane in that segment (which always includes <em>lane</em><sub>0</sub>).\n     *\n     * Supports non-commutative reduction operators\n     *\n     * \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates a tail-segmented warp max\n     * reduction within a block of 32 threads (one warp).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpReduce for type int\n     *     typedef cub::WarpReduce<int> WarpReduce;\n     *\n     *     // Allocate WarpReduce shared memory for one warp\n     *     __shared__ typename WarpReduce::TempStorage temp_storage;\n     *\n     *     // Obtain one input item and flag per thread\n     *     int thread_data = ...\n     *     int tail_flag = ...\n     *\n     *     // Return the warp-wide reductions to each lane0\n     *     int aggregate = WarpReduce(temp_storage).TailSegmentedReduce(\n     *         thread_data, tail_flag, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data and \\p tail_flag across the block of threads\n     * is <tt>{0, 1, 2, 3, ..., 31</tt> and is <tt>{0, 0, 0, 1, 0, 0, 0, 1, ..., 0, 0, 0, 1</tt>,\n     * respectively.  The corresponding output \\p aggregate in threads 0, 4, 8, etc. will be\n     * \\p 3, \\p 7, \\p 11, etc. (and is undefined in other threads).\n     *\n     * \\tparam ReductionOp     <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename            ReductionOp,\n        typename            FlagT>\n    __device__ __forceinline__ T TailSegmentedReduce(\n        T                   input,              ///< [in] Calling thread's input\n        FlagT                tail_flag,          ///< [in] Tail flag denoting whether or not \\p input is the end of the current segment\n        ReductionOp         reduction_op)       ///< [in] Reduction operator\n    {\n        return InternalWarpReduce(temp_storage).template SegmentedReduce<false>(input, tail_flag, reduction_op);\n    }\n\n\n\n    //@}  end member group\n};\n\n/** @} */       // end group WarpModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/cub/warp/warp_scan.cuh",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/**\n * \\file\n * The cub::WarpScan class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel prefix scan of items partitioned across a CUDA thread warp.\n */\n\n#pragma once\n\n#include \"specializations/warp_scan_shfl.cuh\"\n#include \"specializations/warp_scan_smem.cuh\"\n#include \"../thread/thread_operators.cuh\"\n#include \"../util_arch.cuh\"\n#include \"../util_type.cuh\"\n#include \"../util_namespace.cuh\"\n\n/// Optional outer namespace(s)\nCUB_NS_PREFIX\n\n/// CUB namespace\nnamespace cub {\n\n/**\n * \\addtogroup WarpModule\n * @{\n */\n\n/**\n * \\brief The WarpScan class provides [<em>collective</em>](index.html#sec0) methods for computing a parallel prefix scan of items partitioned across a CUDA thread warp.  ![](warp_scan_logo.png)\n *\n * \\tparam T                        The scan input/output element type\n * \\tparam LOGICAL_WARP_THREADS     <b>[optional]</b> The number of threads per \"logical\" warp (may be less than the number of hardware warp threads).  Default is the warp size associated with the CUDA Compute Capability targeted by the compiler (e.g., 32 threads for SM20).\n * \\tparam PTX_ARCH                 <b>[optional]</b> \\ptxversion\n *\n * \\par Overview\n * - Given a list of input elements and a binary reduction operator, a [<em>prefix scan</em>](http://en.wikipedia.org/wiki/Prefix_sum)\n *   produces an output list where each element is computed to be the reduction\n *   of the elements occurring earlier in the input list.  <em>Prefix sum</em>\n *   connotes a prefix scan with the addition operator. The term \\em inclusive indicates\n *   that the <em>i</em><sup>th</sup> output reduction incorporates the <em>i</em><sup>th</sup> input.\n *   The term \\em exclusive indicates the <em>i</em><sup>th</sup> input is not incorporated into\n *   the <em>i</em><sup>th</sup> output reduction.\n * - Supports non-commutative scan operators\n * - Supports \"logical\" warps smaller than the physical warp size (e.g., a logical warp of 8 threads)\n * - The number of entrant threads must be an multiple of \\p LOGICAL_WARP_THREADS\n *\n * \\par Performance Considerations\n * - Uses special instructions when applicable (e.g., warp \\p SHFL)\n * - Uses synchronization-free communication between warp lanes when applicable\n * - Incurs zero bank conflicts for most types\n * - Computation is slightly more efficient (i.e., having lower instruction overhead) for:\n *     - Summation (<b><em>vs.</em></b> generic scan)\n *     - The architecture's warp size is a whole multiple of \\p LOGICAL_WARP_THREADS\n *\n * \\par Simple Examples\n * \\warpcollective{WarpScan}\n * \\par\n * The code snippet below illustrates four concurrent warp prefix sums within a block of\n * 128 threads (one per each of the 32-thread warps).\n * \\par\n * \\code\n * #include <cub/cub.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize WarpScan for type int\n *     typedef cub::WarpScan<int> WarpScan;\n *\n *     // Allocate WarpScan shared memory for 4 warps\n *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n *\n *     // Obtain one input item per thread\n *     int thread_data = ...\n *\n *     // Compute warp-wide prefix sums\n *     int warp_id = threadIdx.x / 32;\n *     WarpScan(temp_storage[warp_id]).ExclusiveSum(thread_data, thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the block of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n * The corresponding output \\p thread_data in each of the four warps of threads will be\n * <tt>0, 1, 2, 3, ..., 31}</tt>.\n *\n * \\par\n * The code snippet below illustrates a single warp prefix sum within a block of\n * 128 threads.\n * \\par\n * \\code\n * #include <cub/cub.cuh>\n *\n * __global__ void ExampleKernel(...)\n * {\n *     // Specialize WarpScan for type int\n *     typedef cub::WarpScan<int> WarpScan;\n *\n *     // Allocate WarpScan shared memory for one warp\n *     __shared__ typename WarpScan::TempStorage temp_storage;\n *     ...\n *\n *     // Only the first warp performs a prefix sum\n *     if (threadIdx.x < 32)\n *     {\n *         // Obtain one input item per thread\n *         int thread_data = ...\n *\n *         // Compute warp-wide prefix sums\n *         WarpScan(temp_storage).ExclusiveSum(thread_data, thread_data);\n *\n * \\endcode\n * \\par\n * Suppose the set of input \\p thread_data across the warp of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n * The corresponding output \\p thread_data will be <tt>{0, 1, 2, 3, ..., 31}</tt>.\n *\n */\ntemplate <\n    typename    T,\n    int         LOGICAL_WARP_THREADS    = CUB_PTX_WARP_THREADS,\n    int         PTX_ARCH                = CUB_PTX_ARCH>\nclass WarpScan\n{\nprivate:\n\n    /******************************************************************************\n     * Constants and type definitions\n     ******************************************************************************/\n\n    enum\n    {\n        /// Whether the logical warp size and the PTX warp size coincide\n        IS_ARCH_WARP = (LOGICAL_WARP_THREADS == CUB_WARP_THREADS(PTX_ARCH)),\n\n        /// Whether the logical warp size is a power-of-two\n        IS_POW_OF_TWO = ((LOGICAL_WARP_THREADS & (LOGICAL_WARP_THREADS - 1)) == 0),\n\n        /// Whether the data type is an integer (which has fully-associative addition)\n        IS_INTEGER = ((Traits<T>::CATEGORY == SIGNED_INTEGER) || (Traits<T>::CATEGORY == UNSIGNED_INTEGER))\n    };\n\n    /// Internal specialization.  Use SHFL-based scan if (architecture is >= SM30) and (LOGICAL_WARP_THREADS is a power-of-two)\n    typedef typename If<(PTX_ARCH >= 300) && (IS_POW_OF_TWO),\n        WarpScanShfl<T, LOGICAL_WARP_THREADS, PTX_ARCH>,\n        WarpScanSmem<T, LOGICAL_WARP_THREADS, PTX_ARCH> >::Type InternalWarpScan;\n\n    /// Shared memory storage layout type for WarpScan\n    typedef typename InternalWarpScan::TempStorage _TempStorage;\n\n\n    /******************************************************************************\n     * Thread fields\n     ******************************************************************************/\n\n    /// Shared storage reference\n    _TempStorage    &temp_storage;\n    unsigned int    lane_id;\n\n\n\n    /******************************************************************************\n     * Public types\n     ******************************************************************************/\n\npublic:\n\n    /// \\smemstorage{WarpScan}\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    /******************************************************************//**\n     * \\name Collective constructors\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Collective constructor using the specified memory allocation as temporary storage.  Logical warp and lane identifiers are constructed from <tt>threadIdx.x</tt>.\n     */\n    __device__ __forceinline__ WarpScan(\n        TempStorage &temp_storage)             ///< [in] Reference to memory allocation having layout type TempStorage\n    :\n        temp_storage(temp_storage.Alias()),\n        lane_id(IS_ARCH_WARP ?\n            LaneId() :\n            LaneId() % LOGICAL_WARP_THREADS)\n    {}\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive prefix sums\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an inclusive prefix sum across the calling warp.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide inclusive prefix sums within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute inclusive warp-wide prefix sums\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).InclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n     * The corresponding output \\p thread_data in each of the four warps of threads will be\n     * <tt>1, 2, 3, ..., 32}</tt>.\n     */\n    __device__ __forceinline__ void InclusiveSum(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output)  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n    {\n        InclusiveScan(input, inclusive_output, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes an inclusive prefix sum across the calling warp.  Also provides every thread with the warp-wide \\p warp_aggregate of all inputs.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide inclusive prefix sums within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute inclusive warp-wide prefix sums\n     *     int warp_aggregate;\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).InclusiveSum(thread_data, thread_data, warp_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n     * The corresponding output \\p thread_data in each of the four warps of threads will be\n     * <tt>1, 2, 3, ..., 32}</tt>.  Furthermore, \\p warp_aggregate for all threads in all warps will be \\p 32.\n     */\n    __device__ __forceinline__ void InclusiveSum(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InclusiveScan(input, inclusive_output, cub::Sum(), warp_aggregate);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Exclusive prefix sums\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes an exclusive prefix sum across the calling warp.  The value of 0 is applied as the initial value, and is assigned to \\p exclusive_output in <em>thread</em><sub>0</sub>.\n     *\n     * \\par\n     *  - \\identityzero\n     *  - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix sums within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix sums\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveSum(thread_data, thread_data);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n     * The corresponding output \\p thread_data in each of the four warps of threads will be\n     * <tt>0, 1, 2, ..., 31}</tt>.\n     *\n     */\n    __device__ __forceinline__ void ExclusiveSum(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output)  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n    {\n        T initial_value = 0;\n        ExclusiveScan(input, exclusive_output, initial_value, cub::Sum());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive prefix sum across the calling warp.  The value of 0 is applied as the initial value, and is assigned to \\p exclusive_output in <em>thread</em><sub>0</sub>.  Also provides every thread with the warp-wide \\p warp_aggregate of all inputs.\n     *\n     * \\par\n     *  - \\identityzero\n     *  - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix sums within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix sums\n     *     int warp_aggregate;\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveSum(thread_data, thread_data, warp_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{1, 1, 1, 1, ...}</tt>.\n     * The corresponding output \\p thread_data in each of the four warps of threads will be\n     * <tt>0, 1, 2, ..., 31}</tt>.  Furthermore, \\p warp_aggregate for all threads in all warps will be \\p 32.\n     */\n    __device__ __forceinline__ void ExclusiveSum(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        T initial_value = 0;\n        ExclusiveScan(input, exclusive_output, initial_value, cub::Sum(), warp_aggregate);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Inclusive prefix scans\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes an inclusive prefix scan using the specified binary scan functor across the calling warp.\n     *\n     * \\par\n     *  - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide inclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute inclusive warp-wide prefix max scans\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).InclusiveScan(thread_data, thread_data, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>0, 0, 2, 2, ..., 30, 30</tt>, the output for the second warp would be <tt>32, 32, 34, 34, ..., 62, 62</tt>, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InternalWarpScan(temp_storage).InclusiveScan(input, inclusive_output, scan_op);\n    }\n\n\n    /**\n     * \\brief Computes an inclusive prefix scan using the specified binary scan functor across the calling warp.  Also provides every thread with the warp-wide \\p warp_aggregate of all inputs.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide inclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute inclusive warp-wide prefix max scans\n     *     int warp_aggregate;\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).InclusiveScan(\n     *         thread_data, thread_data, cub::Max(), warp_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>0, 0, 2, 2, ..., 30, 30</tt>, the output for the second warp would be <tt>32, 32, 34, 34, ..., 62, 62</tt>, etc.\n     * Furthermore, \\p warp_aggregate would be assigned \\p 30 for threads in the first warp, \\p 62 for threads\n     * in the second warp, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void InclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InternalWarpScan(temp_storage).InclusiveScan(input, inclusive_output, scan_op, warp_aggregate);\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Exclusive prefix scans\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Computes an exclusive prefix scan using the specified binary scan functor across the calling warp.  Because no initial value is supplied, the \\p output computed for <em>warp-lane</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix max scans\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveScan(thread_data, thread_data, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>?, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>?, 32, 32, 34, ..., 60, 62</tt>, etc.\n     * (The output \\p thread_data in warp lane<sub>0</sub> is undefined.)\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InternalWarpScan internal(temp_storage);\n\n        T inclusive_output;\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            scan_op,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive prefix scan using the specified binary scan functor across the calling warp.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix max scans\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>INT_MIN, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>30, 32, 32, 34, ..., 60, 62</tt>, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        T               initial_value,      ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InternalWarpScan internal(temp_storage);\n\n        T inclusive_output;\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            scan_op,\n            initial_value,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive prefix scan using the specified binary scan functor across the calling warp.  Because no initial value is supplied, the \\p output computed for <em>warp-lane</em><sub>0</sub> is undefined.  Also provides every thread with the warp-wide \\p warp_aggregate of all inputs.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix max scans\n     *     int warp_aggregate;\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveScan(thread_data, thread_data, cub::Max(), warp_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>?, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>?, 32, 32, 34, ..., 60, 62</tt>, etc.\n     * (The output \\p thread_data in warp lane<sub>0</sub> is undefined.)  Furthermore, \\p warp_aggregate would be assigned \\p 30 for threads in the first warp, \\p 62 for threads\n     * in the second warp, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output,   ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InternalWarpScan internal(temp_storage);\n\n        T inclusive_output;\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            warp_aggregate,\n            scan_op,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n    /**\n     * \\brief Computes an exclusive prefix scan using the specified binary scan functor across the calling warp.  Also provides every thread with the warp-wide \\p warp_aggregate of all inputs.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix max scans\n     *     int warp_aggregate;\n     *     int warp_id = threadIdx.x / 32;\n     *     WarpScan(temp_storage[warp_id]).ExclusiveScan(thread_data, thread_data, INT_MIN, cub::Max(), warp_aggregate);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p thread_data in the first warp would be\n     * <tt>INT_MIN, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>30, 32, 32, 34, ..., 60, 62</tt>, etc.\n     * Furthermore, \\p warp_aggregate would be assigned \\p 30 for threads in the first warp, \\p 62 for threads\n     * in the second warp, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void ExclusiveScan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &exclusive_output,  ///< [out] Calling thread's output item.  May be aliased with \\p input.\n        T               initial_value,      ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op,            ///< [in] Binary scan operator\n        T               &warp_aggregate)    ///< [out] Warp-wide aggregate reduction of input items.\n    {\n        InternalWarpScan internal(temp_storage);\n\n        T inclusive_output;\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            warp_aggregate,\n            scan_op,\n            initial_value,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Combination (inclusive & exclusive) prefix scans\n     *********************************************************************/\n    //@{\n\n\n    /**\n     * \\brief Computes both inclusive and exclusive prefix scans using the specified binary scan functor across the calling warp.  Because no initial value is supplied, the \\p exclusive_output computed for <em>warp-lane</em><sub>0</sub> is undefined.\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide exclusive prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute exclusive warp-wide prefix max scans\n     *     int inclusive_partial, exclusive_partial;\n     *     WarpScan(temp_storage[warp_id]).Scan(thread_data, inclusive_partial, exclusive_partial, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p inclusive_partial in the first warp would be\n     * <tt>0, 0, 2, 2, ..., 30, 30</tt>, the output for the second warp would be <tt>32, 32, 34, 34, ..., 62, 62</tt>, etc.\n     * The corresponding output \\p exclusive_partial in the first warp would be\n     * <tt>?, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>?, 32, 32, 34, ..., 60, 62</tt>, etc.\n     * (The output \\p thread_data in warp lane<sub>0</sub> is undefined.)\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void Scan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's inclusive-scan output item.\n        T               &exclusive_output,  ///< [out] Calling thread's exclusive-scan output item.\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InternalWarpScan internal(temp_storage);\n\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            scan_op,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n    /**\n     * \\brief Computes both inclusive and exclusive prefix scans using the specified binary scan functor across the calling warp.\n     *\n     * \\par\n     *  - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates four concurrent warp-wide prefix max scans within a block of\n     * 128 threads (one per each of the 32-thread warps).\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Compute inclusive warp-wide prefix max scans\n     *     int warp_id = threadIdx.x / 32;\n     *     int inclusive_partial, exclusive_partial;\n     *     WarpScan(temp_storage[warp_id]).Scan(thread_data, inclusive_partial, exclusive_partial, INT_MIN, cub::Max());\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, -1, 2, -3, ..., 126, -127}</tt>.\n     * The corresponding output \\p inclusive_partial in the first warp would be\n     * <tt>0, 0, 2, 2, ..., 30, 30</tt>, the output for the second warp would be <tt>32, 32, 34, 34, ..., 62, 62</tt>, etc.\n     * The corresponding output \\p exclusive_partial in the first warp would be\n     * <tt>INT_MIN, 0, 0, 2, ..., 28, 30</tt>, the output for the second warp would be <tt>30, 32, 32, 34, ..., 60, 62</tt>, etc.\n     *\n     * \\tparam ScanOp     <b>[inferred]</b> Binary scan operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <typename ScanOp>\n    __device__ __forceinline__ void Scan(\n        T               input,              ///< [in] Calling thread's input item.\n        T               &inclusive_output,  ///< [out] Calling thread's inclusive-scan output item.\n        T               &exclusive_output,  ///< [out] Calling thread's exclusive-scan output item.\n        T               initial_value,      ///< [in] Initial value to seed the exclusive scan\n        ScanOp          scan_op)            ///< [in] Binary scan operator\n    {\n        InternalWarpScan internal(temp_storage);\n\n        internal.InclusiveScan(input, inclusive_output, scan_op);\n\n        internal.Update(\n            input,\n            inclusive_output,\n            exclusive_output,\n            scan_op,\n            initial_value,\n            Int2Type<IS_INTEGER>());\n    }\n\n\n\n    //@}  end member group\n    /******************************************************************//**\n     * \\name Data exchange\n     *********************************************************************/\n    //@{\n\n    /**\n     * \\brief Broadcast the value \\p input from <em>warp-lane</em><sub><tt>src_lane</tt></sub> to all lanes in the warp\n     *\n     * \\par\n     * - \\smemreuse\n     *\n     * \\par Snippet\n     * The code snippet below illustrates the warp-wide broadcasts of values from\n     * lanes<sub>0</sub> in each of four warps to all other threads in those warps.\n     * \\par\n     * \\code\n     * #include <cub/cub.cuh>\n     *\n     * __global__ void ExampleKernel(...)\n     * {\n     *     // Specialize WarpScan for type int\n     *     typedef cub::WarpScan<int> WarpScan;\n     *\n     *     // Allocate WarpScan shared memory for 4 warps\n     *     __shared__ typename WarpScan::TempStorage temp_storage[4];\n     *\n     *     // Obtain one input item per thread\n     *     int thread_data = ...\n     *\n     *     // Broadcast from lane0 in each warp to all other threads in the warp\n     *     int warp_id = threadIdx.x / 32;\n     *     thread_data = WarpScan(temp_storage[warp_id]).Broadcast(thread_data, 0);\n     *\n     * \\endcode\n     * \\par\n     * Suppose the set of input \\p thread_data across the block of threads is <tt>{0, 1, 2, 3, ..., 127}</tt>.\n     * The corresponding output \\p thread_data will be\n     * <tt>{0, 0, ..., 0}</tt> in warp<sub>0</sub>,\n     * <tt>{32, 32, ..., 32}</tt> in warp<sub>1</sub>,\n     * <tt>{64, 64, ..., 64}</tt> in warp<sub>2</sub>, etc.\n     */\n    __device__ __forceinline__ T Broadcast(\n        T               input,              ///< [in] The value to broadcast\n        unsigned int    src_lane)           ///< [in] Which warp lane is to do the broadcasting\n    {\n        return InternalWarpScan(temp_storage).Broadcast(input, src_lane);\n    }\n\n    //@}  end member group\n\n};\n\n/** @} */       // end group WarpModule\n\n}               // CUB namespace\nCUB_NS_POSTFIX  // Optional outer namespace(s)\n"
  },
  {
    "path": "external/cub/eclipse code style profile.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\r\n<profiles version=\"1\">\r\n<profile kind=\"CodeFormatterProfile\" name=\"B40C\" version=\"1\">\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.lineSplit\" value=\"80\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer\" value=\"16\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.tabulation.size\" value=\"4\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_enumerator_list\" value=\"48\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_declarator_list\" value=\"16\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_empty_lines\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_method_declaration\" value=\"next_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_semicolon\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_unary_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation\" value=\"16\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration\" value=\"48\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve\" value=\"1\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_block\" value=\"next_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_type_declaration\" value=\"next_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.continuation_indentation\" value=\"1\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_expression_list\" value=\"0\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_binary_operator\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_conditional_expression\" value=\"48\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer\" value=\"1\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_compact_if\" value=\"0\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_binary_operator\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration\" value=\"48\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_unary_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_statements_compare_to_body\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indent_statements_compare_to_block\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration\" value=\"48\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.tabulation.char\" value=\"space\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_block_in_case\" value=\"end_of_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.compact_else_if\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line\" value=\"false\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_switch\" value=\"end_of_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line\" value=\"true\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.indentation.size\" value=\"4\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration\" value=\"end_of_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.brace_position_for_array_initializer\" value=\"next_line\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement\" value=\"do not insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters\" value=\"insert\"/>\r\n<setting id=\"org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments\" value=\"do not insert\"/>\r\n</profile>\r\n</profiles>\r\n"
  },
  {
    "path": "external/cub/examples/block/.gitignore",
    "content": "/bin\n/Debug\n/Release\n/cuda55.sdf\n/cuda55.suo\n/cuda60.sdf\n/cuda60.suo\n"
  },
  {
    "path": "external/cub/examples/block/Makefile",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n\n#-------------------------------------------------------------------------------\n#\n# Makefile usage\n#\n# make <target> [sm=<XXX,...>] [cdp=<0|1>] [force32=<0|1>] [abi=<0|1>] [open64=<0|1>] [verbose=<0|1>] [keep=<0|1>]\n#\n#-------------------------------------------------------------------------------\n \ninclude ../../common.mk \n \n \n#-------------------------------------------------------------------------------\n# Includes\n#-------------------------------------------------------------------------------\n\nINC += -I$(CUB_DIR) -I$(CUB_DIR)test \n\n\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nrwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nDEPS =\t\t\t\t$(CUB_DEPS) \\\n\t\t\t\t\t$(CUB_DIR)test/Makefile \\\n\t\t\t\t\t$(CUB_DIR)test/test_util.h \\\n\t\t\t\t\t$(CUB_DIR)test/mersenne.h \\\n\t\t\nALL = \texample_block_radix_sort \\\n\t \texample_block_reduce \\\n\t \texample_block_scan\n\t\t\n\n\n#-------------------------------------------------------------------------------\n# make default\n#-------------------------------------------------------------------------------\n\ndefault:\n\n\n#-------------------------------------------------------------------------------\n# make clean\n#-------------------------------------------------------------------------------\n\nclean :\n\trm -f bin/*$(CPU_ARCH_SUFFIX)* \n\trm -f *.i* *.cubin *.cu.c *.cudafe* *.fatbin.c *.ptx *.hash *.cu.cpp *.o\n\n\n#-------------------------------------------------------------------------------\n# make all\n#-------------------------------------------------------------------------------\n\nall : $(ALL)\n\n#-------------------------------------------------------------------------------\n# make run\n#-------------------------------------------------------------------------------\n\nrun : \n\tfor i in $(ALL); do ./bin/$${i}_$(BIN_SUFFIX) --device=$(device) || exit 1; done\n\n\n\n\n#-------------------------------------------------------------------------------\n# make example_block_reduce\n#-------------------------------------------------------------------------------\n\nexample_block_reduce: bin/example_block_reduce_$(BIN_SUFFIX)\n\nbin/example_block_reduce_$(BIN_SUFFIX) : example_block_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_block_reduce_$(BIN_SUFFIX) example_block_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_block_scan\n#-------------------------------------------------------------------------------\n\nexample_block_scan: bin/example_block_scan_$(BIN_SUFFIX)\n\nbin/example_block_scan_$(BIN_SUFFIX) : example_block_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_block_scan_$(BIN_SUFFIX) example_block_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_block_radix_sort\n#-------------------------------------------------------------------------------\n\nexample_block_radix_sort: bin/example_block_radix_sort_$(BIN_SUFFIX)\n\nbin/example_block_radix_sort_$(BIN_SUFFIX) : example_block_radix_sort.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_block_radix_sort_$(BIN_SUFFIX) example_block_radix_sort.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\t\n"
  },
  {
    "path": "external/cub/examples/block/example_block_radix_sort.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple demonstration of cub::BlockRadixSort\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_block_radix_sort.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console (define before including cub.h)\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <iostream>\n#include <algorithm>\n\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/block/block_radix_sort.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\n/// Verbose output\nbool g_verbose = false;\n\n/// Timing iterations\nint g_timing_iterations = 100;\n\n/// Default grid size\nint g_grid_size = 1;\n\n/// Uniform key samples\nbool g_uniform_keys;\n\n\n//---------------------------------------------------------------------\n// Kernels\n//---------------------------------------------------------------------\n\n/**\n * Simple kernel for performing a block-wide sorting over integers\n */\ntemplate <\n    typename    Key,\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD>\n__launch_bounds__ (BLOCK_THREADS)\n__global__ void BlockSortKernel(\n    Key         *d_in,          // Tile of input\n    Key         *d_out,         // Tile of output\n    clock_t     *d_elapsed)     // Elapsed cycle count of block scan\n{\n    enum { TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD };\n\n    // Specialize BlockLoad type for our thread block (uses warp-striped loads for coalescing, then transposes in shared memory to a blocked arrangement)\n    typedef BlockLoad<Key, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoadT;\n\n    // Specialize BlockRadixSort type for our thread block\n    typedef BlockRadixSort<Key, BLOCK_THREADS, ITEMS_PER_THREAD> BlockRadixSortT;\n\n    // Shared memory\n    __shared__ union TempStorage\n    {\n        typename BlockLoadT::TempStorage        load;\n        typename BlockRadixSortT::TempStorage   sort;\n    } temp_storage;\n\n    // Per-thread tile items\n    Key items[ITEMS_PER_THREAD];\n\n    // Our current block's offset\n    int block_offset = blockIdx.x * TILE_SIZE;\n\n    // Load items into a blocked arrangement\n    BlockLoadT(temp_storage.load).Load(d_in + block_offset, items);\n\n    // Barrier for smem reuse\n    __syncthreads();\n\n    // Start cycle timer\n    clock_t start = clock();\n\n    // Sort keys\n    BlockRadixSortT(temp_storage.sort).SortBlockedToStriped(items);\n\n    // Stop cycle timer\n    clock_t stop = clock();\n\n    // Store output in striped fashion\n    StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_out + block_offset, items);\n\n    // Store elapsed clocks\n    if (threadIdx.x == 0)\n    {\n        d_elapsed[blockIdx.x] = (start > stop) ? start - stop : stop - start;\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Host utilities\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize sorting problem (and solution).\n */\ntemplate <typename Key>\nvoid Initialize(\n    Key *h_in,\n    Key *h_reference,\n    int num_items,\n    int tile_size)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (g_uniform_keys)\n        {\n            h_in[i] = 0;\n        }\n        else\n        {\n            RandomBits(h_in[i]);\n        }\n        h_reference[i] = h_in[i];\n    }\n\n    // Only sort the first tile\n    std::sort(h_reference, h_reference + tile_size);\n}\n\n\n/**\n * Test BlockScan\n */\ntemplate <\n    typename    Key,\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD>\nvoid Test()\n{\n    const int TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Allocate host arrays\n    Key *h_in               = new Key[TILE_SIZE * g_grid_size];\n    Key *h_reference        = new Key[TILE_SIZE * g_grid_size];\n    clock_t *h_elapsed      = new clock_t[g_grid_size];\n\n    // Initialize problem and reference output on host\n    Initialize(h_in, h_reference, TILE_SIZE * g_grid_size, TILE_SIZE);\n\n    // Initialize device arrays\n    Key *d_in       = NULL;\n    Key *d_out      = NULL;\n    clock_t *d_elapsed  = NULL;\n    CubDebugExit(cudaMalloc((void**)&d_in,          sizeof(Key) * TILE_SIZE * g_grid_size));\n    CubDebugExit(cudaMalloc((void**)&d_out,         sizeof(Key) * TILE_SIZE * g_grid_size));\n    CubDebugExit(cudaMalloc((void**)&d_elapsed,     sizeof(clock_t) * g_grid_size));\n\n    // Display input problem data\n    if (g_verbose)\n    {\n        printf(\"Input data: \");\n        for (int i = 0; i < TILE_SIZE; i++)\n            std::cout << h_in[i] << \", \";\n        printf(\"\\n\\n\");\n    }\n\n    // Kernel props\n    int max_sm_occupancy;\n    CubDebugExit(MaxSmOccupancy(max_sm_occupancy, BlockSortKernel<Key, BLOCK_THREADS, ITEMS_PER_THREAD>, BLOCK_THREADS));\n\n    // Copy problem to device\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(Key) * TILE_SIZE * g_grid_size, cudaMemcpyHostToDevice));\n\n    printf(\"BlockRadixSort %d items (%d timing iterations, %d blocks, %d threads, %d items per thread, %d SM occupancy):\\n\",\n        TILE_SIZE * g_grid_size, g_timing_iterations, g_grid_size, BLOCK_THREADS, ITEMS_PER_THREAD, max_sm_occupancy);\n    fflush(stdout);\n\n    // Run kernel once to prime caches and check result\n    BlockSortKernel<Key, BLOCK_THREADS, ITEMS_PER_THREAD><<<g_grid_size, BLOCK_THREADS>>>(\n        d_in,\n        d_out,\n        d_elapsed);\n\n    // Check for kernel errors and STDIO from the kernel, if any\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Check results\n    printf(\"\\tOutput items: \");\n    int compare = CompareDeviceResults(h_reference, d_out, TILE_SIZE, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n    fflush(stdout);\n\n    // Run this several times and average the performance results\n    GpuTimer            timer;\n    float               elapsed_millis          = 0.0;\n    unsigned long long  elapsed_clocks          = 0;\n\n    for (int i = 0; i < g_timing_iterations; ++i)\n    {\n        timer.Start();\n\n        // Run kernel\n        BlockSortKernel<Key, BLOCK_THREADS, ITEMS_PER_THREAD><<<g_grid_size, BLOCK_THREADS>>>(\n            d_in,\n            d_out,\n            d_elapsed);\n\n        timer.Stop();\n        elapsed_millis += timer.ElapsedMillis();\n\n        // Copy clocks from device\n        CubDebugExit(cudaMemcpy(h_elapsed, d_elapsed, sizeof(clock_t) * g_grid_size, cudaMemcpyDeviceToHost));\n        for (int i = 0; i < g_grid_size; i++)\n            elapsed_clocks += h_elapsed[i];\n    }\n\n    // Check for kernel errors and STDIO from the kernel, if any\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Display timing results\n    float avg_millis            = elapsed_millis / g_timing_iterations;\n    float avg_items_per_sec     = float(TILE_SIZE * g_grid_size) / avg_millis / 1000.0f;\n    double avg_clocks           = double(elapsed_clocks) / g_timing_iterations / g_grid_size;\n    double avg_clocks_per_item  = avg_clocks / TILE_SIZE;\n\n    printf(\"\\tAverage BlockRadixSort::SortBlocked clocks: %.3f\\n\", avg_clocks);\n    printf(\"\\tAverage BlockRadixSort::SortBlocked clocks per item: %.3f\\n\", avg_clocks_per_item);\n    printf(\"\\tAverage kernel millis: %.4f\\n\", avg_millis);\n    printf(\"\\tAverage million items / sec: %.4f\\n\", avg_items_per_sec);\n    fflush(stdout);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (h_elapsed) delete[] h_elapsed;\n    if (d_in) CubDebugExit(cudaFree(d_in));\n    if (d_out) CubDebugExit(cudaFree(d_out));\n    if (d_elapsed) CubDebugExit(cudaFree(d_elapsed));\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_uniform_keys = args.CheckCmdLineFlag(\"uniform\");\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"grid-size\", g_grid_size);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--i=<timing iterations (default:%d)>]\"\n            \"[--grid-size=<grid size (default:%d)>]\"\n            \"[--v] \"\n            \"\\n\", argv[0], g_timing_iterations, g_grid_size);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    fflush(stdout);\n\n    // Run tests\n    printf(\"\\nuint32:\\n\"); fflush(stdout);\n    Test<unsigned int, 128, 13>();\n    printf(\"\\n\"); fflush(stdout);\n\n    printf(\"\\nfp32:\\n\"); fflush(stdout);\n    Test<float, 128, 13>();\n    printf(\"\\n\"); fflush(stdout);\n\n    printf(\"\\nuint8:\\n\"); fflush(stdout);\n    Test<unsigned char, 128, 13>();\n    printf(\"\\n\"); fflush(stdout);\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/examples/block/example_block_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple demonstration of cub::BlockReduce\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_block_reduce.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console (define before including cub.h)\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <iostream>\n\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/block/block_reduce.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\n/// Verbose output\nbool g_verbose = false;\n\n/// Timing iterations\nint g_timing_iterations = 100;\n\n/// Default grid size\nint g_grid_size = 1;\n\n\n\n//---------------------------------------------------------------------\n// Kernels\n//---------------------------------------------------------------------\n\n/**\n * Simple kernel for performing a block-wide exclusive prefix sum over integers\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockReduceAlgorithm    ALGORITHM>\n__global__ void BlockSumKernel(\n    int         *d_in,          // Tile of input\n    int         *d_out,         // Tile aggregate\n    clock_t     *d_elapsed)     // Elapsed cycle count of block reduction\n{\n    // Specialize BlockReduce type for our thread block\n    typedef BlockReduce<int, BLOCK_THREADS, ALGORITHM> BlockReduceT;\n\n    // Shared memory\n    __shared__ typename BlockReduceT::TempStorage temp_storage;\n\n    // Per-thread tile data\n    int data[ITEMS_PER_THREAD];\n    LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_in, data);\n\n    // Start cycle timer\n    clock_t start = clock();\n\n    // Compute sum\n    int aggregate = BlockReduceT(temp_storage).Sum(data);\n\n    // Stop cycle timer\n    clock_t stop = clock();\n\n    // Store aggregate and elapsed clocks\n    if (threadIdx.x == 0)\n    {\n        *d_elapsed = (start > stop) ? start - stop : stop - start;\n        *d_out = aggregate;\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Host utilities\n//---------------------------------------------------------------------\n\n/**\n * Initialize reduction problem (and solution).\n * Returns the aggregate\n */\nint Initialize(int *h_in, int num_items)\n{\n    int inclusive = 0;\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_in[i] = i % 17;\n        inclusive += h_in[i];\n    }\n\n    return inclusive;\n}\n\n\n/**\n * Test thread block reduction\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockReduceAlgorithm    ALGORITHM>\nvoid Test()\n{\n    const int TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Allocate host arrays\n    int *h_in           = new int[TILE_SIZE];\n    int *h_gpu          = new int[TILE_SIZE + 1];\n\n    // Initialize problem and reference output on host\n    int h_aggregate = Initialize(h_in, TILE_SIZE);\n\n    // Initialize device arrays\n    int *d_in           = NULL;\n    int *d_out          = NULL;\n    clock_t *d_elapsed  = NULL;\n    cudaMalloc((void**)&d_in,          sizeof(int) * TILE_SIZE);\n    cudaMalloc((void**)&d_out,         sizeof(int) * 1);\n    cudaMalloc((void**)&d_elapsed,     sizeof(clock_t));\n\n    // Display input problem data\n    if (g_verbose)\n    {\n        printf(\"Input data: \");\n        for (int i = 0; i < TILE_SIZE; i++)\n            printf(\"%d, \", h_in[i]);\n        printf(\"\\n\\n\");\n    }\n\n    // Kernel props\n    int max_sm_occupancy;\n    CubDebugExit(MaxSmOccupancy(max_sm_occupancy, BlockSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM>, BLOCK_THREADS));\n\n    // Copy problem to device\n    cudaMemcpy(d_in, h_in, sizeof(int) * TILE_SIZE, cudaMemcpyHostToDevice);\n\n    printf(\"BlockReduce algorithm %s on %d items (%d timing iterations, %d blocks, %d threads, %d items per thread, %d SM occupancy):\\n\",\n        (ALGORITHM == BLOCK_REDUCE_RAKING) ? \"BLOCK_REDUCE_RAKING\" : \"BLOCK_REDUCE_WARP_REDUCTIONS\",\n        TILE_SIZE, g_timing_iterations, g_grid_size, BLOCK_THREADS, ITEMS_PER_THREAD, max_sm_occupancy);\n\n    // Run aggregate/prefix kernel\n    BlockSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM><<<g_grid_size, BLOCK_THREADS>>>(\n        d_in,\n        d_out,\n        d_elapsed);\n\n    // Check total aggregate\n    printf(\"\\tAggregate: \");\n    int compare = CompareDeviceResults(&h_aggregate, d_out, 1, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Run this several times and average the performance results\n    GpuTimer    timer;\n    float       elapsed_millis          = 0.0;\n    clock_t     elapsed_clocks          = 0;\n\n    for (int i = 0; i < g_timing_iterations; ++i)\n    {\n        // Copy problem to device\n        cudaMemcpy(d_in, h_in, sizeof(int) * TILE_SIZE, cudaMemcpyHostToDevice);\n\n        timer.Start();\n\n        // Run aggregate/prefix kernel\n        BlockSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM><<<g_grid_size, BLOCK_THREADS>>>(\n            d_in,\n            d_out,\n            d_elapsed);\n\n        timer.Stop();\n        elapsed_millis += timer.ElapsedMillis();\n\n        // Copy clocks from device\n        clock_t clocks;\n        CubDebugExit(cudaMemcpy(&clocks, d_elapsed, sizeof(clock_t), cudaMemcpyDeviceToHost));\n        elapsed_clocks += clocks;\n\n    }\n\n    // Check for kernel errors and STDIO from the kernel, if any\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Display timing results\n    float avg_millis            = elapsed_millis / g_timing_iterations;\n    float avg_items_per_sec     = float(TILE_SIZE * g_grid_size) / avg_millis / 1000.0f;\n    float avg_clocks            = float(elapsed_clocks) / g_timing_iterations;\n    float avg_clocks_per_item   = avg_clocks / TILE_SIZE;\n\n    printf(\"\\tAverage BlockReduce::Sum clocks: %.3f\\n\", avg_clocks);\n    printf(\"\\tAverage BlockReduce::Sum clocks per item: %.3f\\n\", avg_clocks_per_item);\n    printf(\"\\tAverage kernel millis: %.4f\\n\", avg_millis);\n    printf(\"\\tAverage million items / sec: %.4f\\n\", avg_items_per_sec);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_gpu) delete[] h_gpu;\n    if (d_in) cudaFree(d_in);\n    if (d_out) cudaFree(d_out);\n    if (d_elapsed) cudaFree(d_elapsed);\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"grid-size\", g_grid_size);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--i=<timing iterations>] \"\n            \"[--grid-size=<grid size>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Run tests\n    Test<1024, 1, BLOCK_REDUCE_RAKING>();\n    Test<512, 2, BLOCK_REDUCE_RAKING>();\n    Test<256, 4, BLOCK_REDUCE_RAKING>();\n    Test<128, 8, BLOCK_REDUCE_RAKING>();\n    Test<64, 16, BLOCK_REDUCE_RAKING>();\n    Test<32, 32, BLOCK_REDUCE_RAKING>();\n    Test<16, 64, BLOCK_REDUCE_RAKING>();\n\n    printf(\"-------------\\n\");\n\n    Test<1024, 1, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<512, 2, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<256, 4, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<128, 8, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<64, 16, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<32, 32, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    Test<16, 64, BLOCK_REDUCE_WARP_REDUCTIONS>();\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/examples/block/example_block_scan.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple demonstration of cub::BlockScan\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_block_scan.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console (define before including cub.h)\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <iostream>\n\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/block/block_scan.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\n/// Verbose output\nbool g_verbose = false;\n\n/// Timing iterations\nint g_timing_iterations = 100;\n\n/// Default grid size\nint g_grid_size = 1;\n\n\n\n//---------------------------------------------------------------------\n// Kernels\n//---------------------------------------------------------------------\n\n/**\n * Simple kernel for performing a block-wide exclusive prefix sum over integers\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockScanAlgorithm      ALGORITHM>\n__global__ void BlockPrefixSumKernel(\n    int         *d_in,          // Tile of input\n    int         *d_out,         // Tile of output\n    clock_t     *d_elapsed)     // Elapsed cycle count of block scan\n{\n    // Specialize BlockLoad type for our thread block (uses warp-striped loads for coalescing, then transposes in shared memory to a blocked arrangement)\n    typedef BlockLoad<int, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_WARP_TRANSPOSE> BlockLoadT;\n\n    // Specialize BlockStore type for our thread block (uses warp-striped loads for coalescing, then transposes in shared memory to a blocked arrangement)\n    typedef BlockStore<int, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_STORE_WARP_TRANSPOSE> BlockStoreT;\n\n    // Specialize BlockScan type for our thread block\n    typedef BlockScan<int, BLOCK_THREADS, ALGORITHM> BlockScanT;\n\n    // Shared memory\n    __shared__ union TempStorage\n    {\n        typename BlockLoadT::TempStorage    load;\n        typename BlockStoreT::TempStorage   store;\n        typename BlockScanT::TempStorage    scan;\n    } temp_storage;\n\n    // Per-thread tile data\n    int data[ITEMS_PER_THREAD];\n\n    // Load items into a blocked arrangement\n    BlockLoadT(temp_storage.load).Load(d_in, data);\n\n    // Barrier for smem reuse\n    __syncthreads();\n\n    // Start cycle timer\n    clock_t start = clock();\n\n    // Compute exclusive prefix sum\n    int aggregate;\n    BlockScanT(temp_storage.scan).ExclusiveSum(data, data, aggregate);\n\n    // Stop cycle timer\n    clock_t stop = clock();\n\n    // Barrier for smem reuse\n    __syncthreads();\n\n    // Store items from a blocked arrangement\n    BlockStoreT(temp_storage.store).Store(d_out, data);\n\n    // Store aggregate and elapsed clocks\n    if (threadIdx.x == 0)\n    {\n        *d_elapsed = (start > stop) ? start - stop : stop - start;\n        d_out[BLOCK_THREADS * ITEMS_PER_THREAD] = aggregate;\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Host utilities\n//---------------------------------------------------------------------\n\n/**\n * Initialize exclusive prefix sum problem (and solution).\n * Returns the aggregate\n */\nint Initialize(\n    int *h_in,\n    int *h_reference,\n    int num_items)\n{\n    int inclusive = 0;\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_in[i] = i % 17;\n\n        h_reference[i] = inclusive;\n        inclusive += h_in[i];\n    }\n\n    return inclusive;\n}\n\n\n/**\n * Test thread block scan\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockScanAlgorithm  ALGORITHM>\nvoid Test()\n{\n    const int TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Allocate host arrays\n    int *h_in           = new int[TILE_SIZE];\n    int *h_reference    = new int[TILE_SIZE];\n    int *h_gpu          = new int[TILE_SIZE + 1];\n\n    // Initialize problem and reference output on host\n    int h_aggregate = Initialize(h_in, h_reference, TILE_SIZE);\n\n    // Initialize device arrays\n    int *d_in           = NULL;\n    int *d_out          = NULL;\n    clock_t *d_elapsed  = NULL;\n    cudaMalloc((void**)&d_in,          sizeof(int) * TILE_SIZE);\n    cudaMalloc((void**)&d_out,         sizeof(int) * (TILE_SIZE + 1));\n    cudaMalloc((void**)&d_elapsed,     sizeof(clock_t));\n\n    // Display input problem data\n    if (g_verbose)\n    {\n        printf(\"Input data: \");\n        for (int i = 0; i < TILE_SIZE; i++)\n            printf(\"%d, \", h_in[i]);\n        printf(\"\\n\\n\");\n    }\n\n    // Kernel props\n    int max_sm_occupancy;\n    CubDebugExit(MaxSmOccupancy(max_sm_occupancy, BlockPrefixSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM>, BLOCK_THREADS));\n\n    // Copy problem to device\n    cudaMemcpy(d_in, h_in, sizeof(int) * TILE_SIZE, cudaMemcpyHostToDevice);\n\n    printf(\"BlockScan algorithm %s on %d items (%d timing iterations, %d blocks, %d threads, %d items per thread, %d SM occupancy):\\n\",\n        (ALGORITHM == BLOCK_SCAN_RAKING) ? \"BLOCK_SCAN_RAKING\" : (ALGORITHM == BLOCK_SCAN_RAKING_MEMOIZE) ? \"BLOCK_SCAN_RAKING_MEMOIZE\" : \"BLOCK_SCAN_WARP_SCANS\",\n        TILE_SIZE, g_timing_iterations, g_grid_size, BLOCK_THREADS, ITEMS_PER_THREAD, max_sm_occupancy);\n\n    // Run aggregate/prefix kernel\n    BlockPrefixSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM><<<g_grid_size, BLOCK_THREADS>>>(\n        d_in,\n        d_out,\n        d_elapsed);\n\n    // Check results\n    printf(\"\\tOutput items: \");\n    int compare = CompareDeviceResults(h_reference, d_out, TILE_SIZE, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Check total aggregate\n    printf(\"\\tAggregate: \");\n    compare = CompareDeviceResults(&h_aggregate, d_out + TILE_SIZE, 1, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Run this several times and average the performance results\n    GpuTimer    timer;\n    float       elapsed_millis          = 0.0;\n    clock_t     elapsed_clocks          = 0;\n\n    for (int i = 0; i < g_timing_iterations; ++i)\n    {\n        // Copy problem to device\n        cudaMemcpy(d_in, h_in, sizeof(int) * TILE_SIZE, cudaMemcpyHostToDevice);\n\n        timer.Start();\n\n        // Run aggregate/prefix kernel\n        BlockPrefixSumKernel<BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM><<<g_grid_size, BLOCK_THREADS>>>(\n            d_in,\n            d_out,\n            d_elapsed);\n\n        timer.Stop();\n        elapsed_millis += timer.ElapsedMillis();\n\n        // Copy clocks from device\n        clock_t clocks;\n        CubDebugExit(cudaMemcpy(&clocks, d_elapsed, sizeof(clock_t), cudaMemcpyDeviceToHost));\n        elapsed_clocks += clocks;\n\n    }\n\n    // Check for kernel errors and STDIO from the kernel, if any\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Display timing results\n    float avg_millis            = elapsed_millis / g_timing_iterations;\n    float avg_items_per_sec     = float(TILE_SIZE * g_grid_size) / avg_millis / 1000.0f;\n    float avg_clocks            = float(elapsed_clocks) / g_timing_iterations;\n    float avg_clocks_per_item   = avg_clocks / TILE_SIZE;\n\n    printf(\"\\tAverage BlockScan::Sum clocks: %.3f\\n\", avg_clocks);\n    printf(\"\\tAverage BlockScan::Sum clocks per item: %.3f\\n\", avg_clocks_per_item);\n    printf(\"\\tAverage kernel millis: %.4f\\n\", avg_millis);\n    printf(\"\\tAverage million items / sec: %.4f\\n\", avg_items_per_sec);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (h_gpu) delete[] h_gpu;\n    if (d_in) cudaFree(d_in);\n    if (d_out) cudaFree(d_out);\n    if (d_elapsed) cudaFree(d_elapsed);\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"grid-size\", g_grid_size);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--i=<timing iterations (default:%d)>]\"\n            \"[--grid-size=<grid size (default:%d)>]\"\n            \"[--v] \"\n            \"\\n\", argv[0], g_timing_iterations, g_grid_size);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Run tests\n    Test<1024, 1, BLOCK_SCAN_RAKING>();\n    Test<512, 2, BLOCK_SCAN_RAKING>();\n    Test<256, 4, BLOCK_SCAN_RAKING>();\n    Test<128, 8, BLOCK_SCAN_RAKING>();\n    Test<64, 16, BLOCK_SCAN_RAKING>();\n    Test<32, 32, BLOCK_SCAN_RAKING>();\n\n    printf(\"-------------\\n\");\n\n    Test<1024, 1, BLOCK_SCAN_RAKING_MEMOIZE>();\n    Test<512, 2, BLOCK_SCAN_RAKING_MEMOIZE>();\n    Test<256, 4, BLOCK_SCAN_RAKING_MEMOIZE>();\n    Test<128, 8, BLOCK_SCAN_RAKING_MEMOIZE>();\n    Test<64, 16, BLOCK_SCAN_RAKING_MEMOIZE>();\n    Test<32, 32, BLOCK_SCAN_RAKING_MEMOIZE>();\n\n    printf(\"-------------\\n\");\n\n    Test<1024, 1, BLOCK_SCAN_WARP_SCANS>();\n    Test<512, 2, BLOCK_SCAN_WARP_SCANS>();\n    Test<256, 4, BLOCK_SCAN_WARP_SCANS>();\n    Test<128, 8, BLOCK_SCAN_WARP_SCANS>();\n    Test<64, 16, BLOCK_SCAN_WARP_SCANS>();\n    Test<32, 32, BLOCK_SCAN_WARP_SCANS>();\n\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/examples/block/reduce_by_key.cu",
    "content": "\n\n#include <cub/cub.cuh>\n\n\ntemplate <\n    int         BLOCK_THREADS,          ///< Number of CTA threads\n    typename    KeyT,                   ///< Key type\n    typename    ValueT>                 ///< Value type\n__global__ void Kernel()\n{\n    // Tuple type for scanning (pairs accumulated segment-value with segment-index)\n    typedef cub::KeyValuePair<int, ValueT> OffsetValuePairT;\n\n    // Reduce-value-by-segment scan operator\n    typedef cub::ReduceBySegmentOp<cub::Sum> ReduceBySegmentOpT;\n\n    // Parameterized BlockDiscontinuity type for setting head flags\n    typedef cub::BlockDiscontinuity<\n            KeyT,\n            BLOCK_THREADS>\n        BlockDiscontinuityKeysT;\n\n    // Parameterized BlockScan type\n    typedef cub::BlockScan<\n            OffsetValuePairT,\n            BLOCK_THREADS,\n            cub::BLOCK_SCAN_WARP_SCANS>\n        BlockScanT;\n\n    // Shared memory\n    __shared__ union TempStorage\n    {\n        typename BlockScanT::TempStorage                scan;           // Scan storage\n        typename BlockDiscontinuityKeysT::TempStorage   discontinuity;  // Discontinuity storage\n    } temp_storage;\n\n\n    // Read data (each thread gets 3 items each, every 9 items is a segment)\n    KeyT    my_keys[3]      = {threadIdx.x / 3, threadIdx.x / 3, threadIdx.x / 3};\n    ValueT  my_values[3]    = {1, 1, 1};\n\n    // Set head segment head flags\n    int     my_flags[3];\n    BlockDiscontinuityKeysT(temp_storage.discontinuity).FlagHeads(\n        my_flags,\n        my_keys,\n        cub::Inequality());\n\n    __syncthreads();\n\n\n\n\n\n\n}\n"
  },
  {
    "path": "external/cub/examples/device/.gitignore",
    "content": "/bin\n/Debug\n/ipch\n/Release\n/cuda55.sdf\n/cuda55.suo\n/cuda60.sdf\n/cuda60.suo\n"
  },
  {
    "path": "external/cub/examples/device/Makefile",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n\n#-------------------------------------------------------------------------------\n#\n# Makefile usage\n#\n# make <target> [sm=<XXX,...>] [cdp=<0|1>] [force32=<0|1>] [abi=<0|1>] [open64=<0|1>] [verbose=<0|1>] [keep=<0|1>]\n#\n#-------------------------------------------------------------------------------\n \ninclude ../../common.mk \n \n \n#-------------------------------------------------------------------------------\n# Includes\n#-------------------------------------------------------------------------------\n\nINC += -I$(CUB_DIR) -I$(CUB_DIR)test \n\n\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nrwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nDEPS =\t\t\t\t$(CUB_DEPS) \\\n\t\t\t\t\t$(CUB_DIR)test/Makefile \\\n\t\t\t\t\t$(CUB_DIR)test/test_util.h \\\n\t\t\t\t\t$(CUB_DIR)test/mersenne.h \\\n\t\t\nALL = \texample_device_partition_flagged \\\n\t\texample_device_partition_if \\\n\t \texample_device_radix_sort \\\n\t\texample_device_reduce \\\n\t \texample_device_scan \\\n\t \texample_device_select_unique \\\n\t\texample_device_select_flagged \\\n\t\texample_device_select_if \\\n\t\texample_device_sort_find_non_trivial_runs\n\t\t\n\n\n#-------------------------------------------------------------------------------\n# make default\n#-------------------------------------------------------------------------------\n\ndefault:\n\n\n#-------------------------------------------------------------------------------\n# make clean\n#-------------------------------------------------------------------------------\n\nclean :\n\trm -f bin/*$(CPU_ARCH_SUFFIX)* \n\trm -f *.i* *.cubin *.cu.c *.cudafe* *.fatbin.c *.ptx *.hash *.cu.cpp *.o\n\n\n#-------------------------------------------------------------------------------\n# make all\n#-------------------------------------------------------------------------------\n\nall : $(ALL)\n\n#-------------------------------------------------------------------------------\n# make run\n#-------------------------------------------------------------------------------\n\nrun : \n\tfor i in $(ALL); do ./bin/$${i}_$(BIN_SUFFIX) --device=$(device) || exit 1; done\n\n\n#-------------------------------------------------------------------------------\n# make example_device_reduce\n#-------------------------------------------------------------------------------\n\nexample_device_reduce: bin/example_device_reduce_$(BIN_SUFFIX)\n\nbin/example_device_reduce_$(BIN_SUFFIX) : example_device_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_reduce_$(BIN_SUFFIX) example_device_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_device_partition_flagged\n#-------------------------------------------------------------------------------\n\nexample_device_partition_flagged: bin/example_device_partition_flagged_$(BIN_SUFFIX)\n\nbin/example_device_partition_flagged_$(BIN_SUFFIX) : example_device_partition_flagged.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_partition_flagged_$(BIN_SUFFIX) example_device_partition_flagged.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make example_device_partition_if\n#-------------------------------------------------------------------------------\n\nexample_device_partition_if: bin/example_device_partition_if_$(BIN_SUFFIX)\n\nbin/example_device_partition_if_$(BIN_SUFFIX) : example_device_partition_if.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_partition_if_$(BIN_SUFFIX) example_device_partition_if.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make example_device_scan\n#-------------------------------------------------------------------------------\n\nexample_device_scan: bin/example_device_scan_$(BIN_SUFFIX)\n\nbin/example_device_scan_$(BIN_SUFFIX) : example_device_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_scan_$(BIN_SUFFIX) example_device_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_device_radix_sort\n#-------------------------------------------------------------------------------\n\nexample_device_radix_sort: bin/example_device_radix_sort_$(BIN_SUFFIX)\n\nbin/example_device_radix_sort_$(BIN_SUFFIX) : example_device_radix_sort.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_radix_sort_$(BIN_SUFFIX) example_device_radix_sort.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_device_select_unique\n#-------------------------------------------------------------------------------\n\nexample_device_select_unique: bin/example_device_select_unique_$(BIN_SUFFIX)\n\nbin/example_device_select_unique_$(BIN_SUFFIX) : example_device_select_unique.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_select_unique_$(BIN_SUFFIX) example_device_select_unique.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_device_select_flagged\n#-------------------------------------------------------------------------------\n\nexample_device_select_flagged: bin/example_device_select_flagged_$(BIN_SUFFIX)\n\nbin/example_device_select_flagged_$(BIN_SUFFIX) : example_device_select_flagged.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_select_flagged_$(BIN_SUFFIX) example_device_select_flagged.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make example_device_select_if\n#-------------------------------------------------------------------------------\n\nexample_device_select_if: bin/example_device_select_if_$(BIN_SUFFIX)\n\nbin/example_device_select_if_$(BIN_SUFFIX) : example_device_select_if.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_select_if_$(BIN_SUFFIX) example_device_select_if.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make example_device_sort_find_non_trivial_runs\n#-------------------------------------------------------------------------------\n\nexample_device_sort_find_non_trivial_runs: bin/example_device_sort_find_non_trivial_runs_$(BIN_SUFFIX)\n\nbin/example_device_sort_find_non_trivial_runs_$(BIN_SUFFIX) : example_device_sort_find_non_trivial_runs.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/example_device_sort_find_non_trivial_runs_$(BIN_SUFFIX) example_device_sort_find_non_trivial_runs.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_partition_flagged.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DevicePartition::Flagged().\n *\n * Partition flagged items from from a sequence of int keys using a\n * corresponding sequence of unsigned char flags.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_partition_flagged.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_partition.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem, setting flags at distances of random length\n * chosen from [1..max_segment]\n */\nvoid Initialize(\n    int             *h_in,\n    unsigned char   *h_flags,\n    int             num_items,\n    int             max_segment)\n{\n    unsigned short max_short = (unsigned short) -1;\n\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Select number of repeating occurrences\n        unsigned short repeat;\n        RandomBits(repeat);\n        repeat = (unsigned short) ((float(repeat) * (float(max_segment) / float(max_short))));\n        repeat = CUB_MAX(1, repeat);\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            h_flags[j] = 0;\n            h_in[j] = key;\n            j++;\n        }\n\n        h_flags[i] = 1;\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"Flags:\\n\");\n        DisplayResults(h_flags, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\nint Solve(\n    int             *h_in,\n    unsigned char   *h_flags,\n    int             *h_reference,\n    int             num_items)\n{\n    int num_selected = 0;\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (h_flags[i])\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n        else\n        {\n            h_reference[num_items - (i - num_selected) - 1] = h_in[i];\n        }\n    }\n\n    return num_selected;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = 150;\n    int max_segment         = 40;       // Maximum segment length\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays\n    int             *h_in        = new int[num_items];\n    int             *h_reference = new int[num_items];\n    unsigned char   *h_flags     = new unsigned char[num_items];\n\n    // Initialize problem and solution\n    Initialize(h_in, h_flags, num_items, max_segment);\n    int num_selected = Solve(h_in, h_flags, h_reference, num_items);\n\n    printf(\"cub::DevicePartition::Flagged %d items, %d selected (avg distance %d), %d-byte elements\\n\",\n        num_items, num_selected, (num_selected > 0) ? num_items / num_selected : 0, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    int             *d_in = NULL;\n    unsigned char   *d_flags = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_flags, sizeof(unsigned char) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_flags, h_flags, sizeof(unsigned char) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array and num selected\n    int     *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DevicePartition::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DevicePartition::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_items, true, g_verbose);\n    printf(\"\\t Data %s \", compare ? \"FAIL\" : \"PASS\");\n    compare |= CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_flags) CubDebugExit(g_allocator.DeviceFree(d_flags));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_partition_if.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DevicePartition::If().\n *\n * Partitions items from from a sequence of int keys using a\n * section functor (greater-than)\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_select_if.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_partition.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n/// Selection functor type\nstruct GreaterThan\n{\n    int compare;\n\n    __host__ __device__ __forceinline__\n    GreaterThan(int compare) : compare(compare) {}\n\n    __host__ __device__ __forceinline__\n    bool operator()(const int &a) const {\n        return (a > compare);\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem, setting runs of random length chosen from [1..max_segment]\n */\nvoid Initialize(\n    int     *h_in,\n    int     num_items,\n    int     max_segment)\n{\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Randomly select number of repeating occurrences uniformly from [1..max_segment]\n        unsigned short max_short = (unsigned short) -1;\n        unsigned short repeat;\n        RandomBits(repeat);\n        repeat = (unsigned short) ((float(repeat) * (float(max_segment) / float(max_short))));\n        repeat = CUB_MAX(1, repeat);\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            h_in[j] = key;\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\ntemplate <typename SelectOp>\nint Solve(\n    int             *h_in,\n    SelectOp        select_op,\n    int             *h_reference,\n    int             num_items)\n{\n    int num_selected = 0;\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (select_op(h_in[i]))\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n        else\n        {\n            h_reference[num_items - (i - num_selected) - 1] = h_in[i];\n        }\n    }\n\n    return num_selected;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = 150;\n    int max_segment         = 40;       // Maximum segment length\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays\n    int *h_in        = new int[num_items];\n    int *h_reference = new int[num_items];\n\n    // DevicePartition a pivot index\n    unsigned int pivot_index;\n    unsigned int max_int = (unsigned int) -1;\n    RandomBits(pivot_index);\n    pivot_index = (unsigned int) ((float(pivot_index) * (float(num_items - 1) / float(max_int))));\n    printf(\"Pivot idx: %d\\n\", pivot_index); fflush(stdout);\n\n    // Initialize problem and solution\n    Initialize(h_in, num_items, max_segment);\n    GreaterThan select_op(h_in[pivot_index]);\n\n    int num_selected = Solve(h_in, select_op, h_reference, num_items);\n\n    printf(\"cub::DevicePartition::If %d items, %d selected (avg run length %d), %d-byte elements\\n\",\n        num_items, num_selected, (num_selected > 0) ? num_items / num_selected : 0, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    int *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array and num selected\n    int     *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DevicePartition::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DevicePartition::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_items, true, g_verbose);\n    printf(\"\\t Data %s \", compare ? \"FAIL\" : \"PASS\");\n    compare = compare | CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_radix_sort.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceRadixSort::SortPairs().\n *\n * Sorts an array of float keys paired with a corresponding array of int values.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_radix_sort.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <algorithm>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_radix_sort.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Simple key-value pairing for floating point types.  Distinguishes\n * between positive and negative zero.\n */\nstruct Pair\n{\n    float   key;\n    int     value;\n\n    bool operator<(const Pair &b) const\n    {\n        if (key < b.key)\n            return true;\n\n        if (key > b.key)\n            return false;\n\n        // Return true if key is negative zero and b.key is positive zero\n        unsigned int key_bits   = *reinterpret_cast<unsigned*>(const_cast<float*>(&key));\n        unsigned int b_key_bits = *reinterpret_cast<unsigned*>(const_cast<float*>(&b.key));\n        unsigned int HIGH_BIT   = 1u << 31;\n\n        return ((key_bits & HIGH_BIT) != 0) && ((b_key_bits & HIGH_BIT) == 0);\n    }\n};\n\n\n/**\n * Initialize key-value sorting problem.\n */\nvoid Initialize(\n    float           *h_keys,\n    int             *h_values,\n    float           *h_reference_keys,\n    int             *h_reference_values,\n    int             num_items)\n{\n    Pair *h_pairs = new Pair[num_items];\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        RandomBits(h_keys[i]);\n        RandomBits(h_values[i]);\n        h_pairs[i].key    = h_keys[i];\n        h_pairs[i].value  = h_values[i];\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input keys:\\n\");\n        DisplayResults(h_keys, num_items);\n        printf(\"\\n\\n\");\n\n        printf(\"Input values:\\n\");\n        DisplayResults(h_values, num_items);\n        printf(\"\\n\\n\");\n    }\n\n    std::stable_sort(h_pairs, h_pairs + num_items);\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_reference_keys[i]     = h_pairs[i].key;\n        h_reference_values[i]   = h_pairs[i].value;\n    }\n\n    delete[] h_pairs;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items = 150;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    printf(\"cub::DeviceRadixSort::SortPairs() %d items (%d-byte keys %d-byte values)\\n\",\n        num_items, int(sizeof(float)), int(sizeof(int)));\n    fflush(stdout);\n\n    // Allocate host arrays\n    float   *h_keys             = new float[num_items];\n    float   *h_reference_keys   = new float[num_items];\n    int     *h_values           = new int[num_items];\n    int     *h_reference_values = new int[num_items];\n\n    // Initialize problem and solution on host\n    Initialize(h_keys, h_values, h_reference_keys, h_reference_values, num_items);\n\n    // Allocate device arrays\n    DoubleBuffer<float> d_keys;\n    DoubleBuffer<int>   d_values;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[0], sizeof(float) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(float) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[0], sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[1], sizeof(int) * num_items));\n\n    // Allocate temporary storage\n    size_t  temp_storage_bytes  = 0;\n    void    *d_temp_storage     = NULL;\n\n    CubDebugExit(DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Initialize device arrays\n    CubDebugExit(cudaMemcpy(d_keys.d_buffers[d_keys.selector], h_keys, sizeof(float) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_values.d_buffers[d_values.selector], h_values, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Run\n    CubDebugExit(DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference_keys, d_keys.Current(), num_items, true, g_verbose);\n    printf(\"\\t Compare keys (selector %d): %s\\n\", d_keys.selector, compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n    compare = CompareDeviceResults(h_reference_values, d_values.Current(), num_items, true, g_verbose);\n    printf(\"\\t Compare values (selector %d): %s\\n\", d_values.selector, compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_keys) delete[] h_keys;\n    if (h_reference_keys) delete[] h_reference_keys;\n    if (h_values) delete[] h_values;\n    if (h_reference_values) delete[] h_reference_values;\n\n    if (d_keys.d_buffers[0]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[0]));\n    if (d_keys.d_buffers[1]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[1]));\n    if (d_values.d_buffers[0]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[0]));\n    if (d_values.d_buffers[1]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[1]));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceReduce::Sum().\n *\n * Sums an array of int keys.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_reduce.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_reduce.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem\n */\nvoid Initialize(\n    int   *h_in,\n    int     num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n        h_in[i] = i;\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Compute solution\n */\nvoid Solve(\n    int           *h_in,\n    int           &h_reference,\n    int             num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (i == 0)\n            h_reference = h_in[0];\n        else\n            h_reference += h_in[i];\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items = 150;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    printf(\"cub::DeviceReduce::Sum() %d items (%d-byte elements)\\n\",\n        num_items, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate host arrays\n    int* h_in = new int[num_items];\n    int  h_reference;\n\n    // Initialize problem and solution\n    Initialize(h_in, num_items);\n    Solve(h_in, h_reference, num_items);\n\n    // Allocate problem device arrays\n    int *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array\n    int *d_out = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * 1));\n\n    // Request and allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DeviceReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DeviceReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(&h_reference, d_out, 1, g_verbose, g_verbose);\n    printf(\"\\t%s\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_scan.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceScan::ExclusiveSum().\n *\n * Computes an exclusive sum of int keys.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_scan.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_scan.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\nvoid Initialize(\n    int        *h_in,\n    int          num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n        h_in[i] = i;\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n/**\n * Solve exclusive-scan problem\n */\nint Solve(\n    int           *h_in,\n    int           *h_reference,\n    int             num_items)\n{\n    int inclusive = 0;\n    int aggregate = 0;\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_reference[i] = inclusive;\n        inclusive += h_in[i];\n        aggregate += h_in[i];\n    }\n\n    return aggregate;\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items = 150;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    printf(\"cub::DeviceScan::ExclusiveSum %d items (%d-byte elements)\\n\",\n        num_items, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate host arrays\n    int*  h_in = new int[num_items];\n    int*  h_reference = new int[num_items];\n\n    // Initialize problem and solution\n    Initialize(h_in, num_items);\n    Solve(h_in, h_reference, num_items);\n\n    // Allocate problem device arrays\n    int *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array\n    int *d_out = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_items, true, g_verbose);\n    printf(\"\\t%s\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_select_flagged.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceSelect::Flagged().\n *\n * Selects flagged items from from a sequence of int keys using a\n * corresponding sequence of unsigned char flags.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_select_flagged.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_select.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem, setting flags at distances of random length\n * chosen from [1..max_segment]\n */\nvoid Initialize(\n    int             *h_in,\n    unsigned char   *h_flags,\n    int             num_items,\n    int             max_segment)\n{\n    unsigned short max_short = (unsigned short) -1;\n\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Select number of repeating occurrences\n        unsigned short repeat;\n        RandomBits(repeat);\n        repeat = (unsigned short) ((float(repeat) * (float(max_segment) / float(max_short))));\n        repeat = CUB_MAX(1, repeat);\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            h_flags[j] = 0;\n            h_in[j] = key;\n            j++;\n        }\n\n        h_flags[i] = 1;\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"Flags:\\n\");\n        DisplayResults(h_flags, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\nint Solve(\n    int             *h_in,\n    unsigned char   *h_flags,\n    int             *h_reference,\n    int             num_items)\n{\n    int num_selected = 0;\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (h_flags[i])\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n        else\n        {\n            h_reference[num_items - (i - num_selected) - 1] = h_in[i];\n        }\n    }\n\n    return num_selected;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = 150;\n    int max_segment         = 40;       // Maximum segment length\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays\n    int             *h_in        = new int[num_items];\n    int             *h_reference = new int[num_items];\n    unsigned char   *h_flags     = new unsigned char[num_items];\n\n    // Initialize problem and solution\n    Initialize(h_in, h_flags, num_items, max_segment);\n    int num_selected = Solve(h_in, h_flags, h_reference, num_items);\n\n    printf(\"cub::DeviceSelect::Flagged %d items, %d selected (avg distance %d), %d-byte elements\\n\",\n        num_items, num_selected, (num_selected > 0) ? num_items / num_selected : 0, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    int             *d_in = NULL;\n    unsigned char   *d_flags = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_flags, sizeof(unsigned char) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_flags, h_flags, sizeof(unsigned char) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array and num selected\n    int     *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DeviceSelect::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DeviceSelect::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_selected, true, g_verbose);\n    printf(\"\\t Data %s \", compare ? \"FAIL\" : \"PASS\");\n    compare |= CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_flags) CubDebugExit(g_allocator.DeviceFree(d_flags));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_select_if.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceSelect::If().\n *\n * Selects items from from a sequence of int keys using a\n * section functor (greater-than)\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_select_if.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_select.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n/// Selection functor type\nstruct GreaterThan\n{\n    int compare;\n\n    __host__ __device__ __forceinline__\n    GreaterThan(int compare) : compare(compare) {}\n\n    __host__ __device__ __forceinline__\n    bool operator()(const int &a) const {\n        return (a > compare);\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem, setting runs of random length chosen from [1..max_segment]\n */\nvoid Initialize(\n    int     *h_in,\n    int     num_items,\n    int     max_segment)\n{\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Randomly select number of repeating occurrences uniformly from [1..max_segment]\n        unsigned short max_short = (unsigned short) -1;\n        unsigned short repeat;\n        RandomBits(repeat);\n        repeat = (unsigned short) ((float(repeat) * (float(max_segment) / float(max_short))));\n        repeat = CUB_MAX(1, repeat);\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            h_in[j] = key;\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\ntemplate <typename SelectOp>\nint Solve(\n    int             *h_in,\n    SelectOp        select_op,\n    int             *h_reference,\n    int             num_items)\n{\n    int num_selected = 0;\n    for (int i = 0; i < num_items; ++i)\n    {\n        if (select_op(h_in[i]))\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n        else\n        {\n            h_reference[num_items - (i - num_selected) - 1] = h_in[i];\n        }\n    }\n\n    return num_selected;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = 150;\n    int max_segment         = 40;       // Maximum segment length\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays\n    int *h_in        = new int[num_items];\n    int *h_reference = new int[num_items];\n\n    // Select a pivot index\n    unsigned int pivot_index;\n    unsigned int max_int = (unsigned int) -1;\n    RandomBits(pivot_index);\n    pivot_index = (unsigned int) ((float(pivot_index) * (float(num_items - 1) / float(max_int))));\n    printf(\"Pivot idx: %d\\n\", pivot_index); fflush(stdout);\n\n    // Initialize problem and solution\n    Initialize(h_in, num_items, max_segment);\n    GreaterThan select_op(h_in[pivot_index]);\n\n    int num_selected = Solve(h_in, select_op, h_reference, num_items);\n\n    printf(\"cub::DeviceSelect::If %d items, %d selected (avg run length %d), %d-byte elements\\n\",\n        num_items, num_selected, (num_selected > 0) ? num_items / num_selected : 0, (int) sizeof(int));\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    int *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array and num selected\n    int     *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_selected, true, g_verbose);\n    printf(\"\\t Data %s \", compare ? \"FAIL\" : \"PASS\");\n    compare = compare | CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_select_unique.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of DeviceSelect::Unique().\n *\n * Selects the first element from each run of identical values from a sequence\n * of int keys.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_select_unique.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_select.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem, setting runs of random length chosen from [1..max_segment]\n */\nvoid Initialize(\n    int     *h_in,\n    int     num_items,\n    int     max_segment)\n{\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Randomly select number of repeating occurrences uniformly from [1..max_segment]\n        unsigned short max_short = (unsigned short) -1;\n        unsigned short repeat;\n        RandomBits(repeat);\n        repeat = (unsigned short) ((float(repeat) * (float(max_segment) / float(max_short))));\n        repeat = CUB_MAX(1, repeat);\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            h_in[j] = key;\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\nint Solve(\n    int         *h_in,\n    int         *h_reference,\n    int         num_items)\n{\n    int num_selected = 0;\n    if (num_items > 0)\n    {\n        h_reference[num_selected] = h_in[0];\n        num_selected++;\n    }\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        if (h_in[i] != h_in[i - 1])\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n    }\n\n    return num_selected;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = 150;\n    int max_segment         = 40;       // Maximum segment length\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays\n    int*  h_in        = new int[num_items];\n    int*  h_reference = new int[num_items];\n\n    // Initialize problem and solution\n    Initialize(h_in, num_items, max_segment);\n    int num_selected = Solve(h_in, h_reference, num_items);\n\n    printf(\"cub::DeviceSelect::Unique %d items (%d-byte elements), %d selected (avg run length %d)\\n\",\n        num_items, (int) sizeof(int), num_selected, num_items / num_selected);\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    int *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(int) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n    // Allocate device output array and num selected\n    int     *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(int) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(DeviceSelect::Unique(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Run\n    CubDebugExit(DeviceSelect::Unique(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_selected, true, g_verbose);\n    printf(\"\\t Data %s \", compare ? \"FAIL\" : \"PASS\");\n    compare = compare | CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/examples/device/example_device_sort_find_non_trivial_runs.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Simple example of sorting a sequence of keys and values (each pair is a\n * randomly-selected int32 paired with its original offset in the unsorted sequence), and then\n * isolating all maximal, non-trivial (having length > 1) \"runs\" of duplicates.\n *\n * To compile using the command line:\n *   nvcc -arch=sm_XX example_device_sort_find_non_trivial_runs.cu -I../.. -lcudart -O3\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <algorithm>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_radix_sort.cuh>\n#include <cub/device/device_run_length_encode.cuh>\n\n#include \"../../test/test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Simple key-value pairing for using std::sort on key-value pairs.\n */\ntemplate <typename Key, typename Value>\nstruct Pair\n{\n    Key     key;\n    Value   value;\n\n    bool operator<(const Pair &b) const\n    {\n        return (key < b.key);\n    }\n};\n\n\n/**\n * Pair ostream operator\n */\ntemplate <typename Key, typename Value>\nstd::ostream& operator<<(std::ostream& os, const Pair<Key, Value>& val)\n{\n    os << '<' << val.key << ',' << val.value << '>';\n    return os;\n}\n\n\n/**\n * Initialize problem\n */\ntemplate <typename Key, typename Value>\nvoid Initialize(\n    Key    *h_keys,\n    Value  *h_values,\n    int    num_items,\n    int    max_key)\n{\n    float scale = float(max_key) / float(UINT_MAX);\n    for (int i = 0; i < num_items; ++i)\n    {\n        Key sample;\n        RandomBits(sample);\n        h_keys[i] = (max_key == -1) ? i : (Key) (scale * sample);\n        h_values[i] = i;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Keys:\\n\");\n        DisplayResults(h_keys, num_items);\n        printf(\"\\n\\n\");\n\n        printf(\"Values:\\n\");\n        DisplayResults(h_values, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve sorted non-trivial subrange problem.  Returns the number\n * of non-trivial runs found.\n */\ntemplate <typename Key, typename Value>\nint Solve(\n    Key     *h_keys,\n    Value   *h_values,\n    int     num_items,\n    int     *h_offsets_reference,\n    int     *h_lengths_reference)\n{\n    // Sort\n\n    Pair<Key, Value> *h_pairs = new Pair<Key, Value>[num_items];\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_pairs[i].key    = h_keys[i];\n        h_pairs[i].value  = h_values[i];\n    }\n\n    std::stable_sort(h_pairs, h_pairs + num_items);\n\n    if (g_verbose)\n    {\n        printf(\"Sorted pairs:\\n\");\n        DisplayResults(h_pairs, num_items);\n        printf(\"\\n\\n\");\n    }\n\n    // Find non-trivial runs\n\n    Key     previous        = h_pairs[0].key;\n    int     length          = 1;\n    int     num_runs        = 0;\n    int     run_begin       = 0;\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        if (previous != h_pairs[i].key)\n        {\n            if (length > 1)\n            {\n                h_offsets_reference[num_runs]     = run_begin;\n                h_lengths_reference[num_runs]     = length;\n                num_runs++;\n            }\n            length = 1;\n            run_begin = i;\n        }\n        else\n        {\n            length++;\n        }\n        previous = h_pairs[i].key;\n    }\n\n    if (length > 1)\n    {\n        h_offsets_reference[num_runs]   = run_begin;\n        h_lengths_reference[num_runs]   = length;\n        num_runs++;\n    }\n\n    delete[] h_pairs;\n\n    return num_runs;\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    typedef unsigned int    Key;\n    typedef int             Value;\n\n    int timing_iterations   = 0;\n    int num_items           = 40;\n    Key max_key             = 20;       // Max item\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"maxkey\", max_key);\n    args.GetCmdLineArgument(\"i\", timing_iterations);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--i=<timing iterations> \"\n            \"[--n=<input items, default 40> \"\n            \"[--maxkey=<max key, default 20 (use -1 to test only unique keys)>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Allocate host arrays (problem and reference solution)\n\n    Key     *h_keys                 = new Key[num_items];\n    Value   *h_values               = new Value[num_items];\n    int     *h_offsets_reference    = new int[num_items];\n    int     *h_lengths_reference    = new int[num_items];\n\n    // Initialize key-value pairs and compute reference solution (sort them, and identify non-trivial runs)\n    printf(\"Computing reference solution on CPU for %d items (max key %d)\\n\", num_items, max_key);\n    fflush(stdout);\n\n    Initialize(h_keys, h_values, num_items, max_key);\n    int num_runs = Solve(h_keys, h_values, num_items, h_offsets_reference, h_lengths_reference);\n\n    printf(\"%d non-trivial runs\\n\", num_runs);\n    fflush(stdout);\n\n    // Repeat for performance timing\n    GpuTimer gpu_timer;\n    GpuTimer gpu_rle_timer;\n    float elapsed_millis = 0.0;\n    float elapsed_rle_millis = 0.0;\n    for (int i = 0; i <= timing_iterations; ++i)\n    {\n\n        // Allocate and initialize device arrays for sorting\n        DoubleBuffer<Key>       d_keys;\n        DoubleBuffer<Value>     d_values;\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[0], sizeof(Key) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(Key) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[0], sizeof(Value) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[1], sizeof(Value) * num_items));\n\n        CubDebugExit(cudaMemcpy(d_keys.d_buffers[d_keys.selector], h_keys, sizeof(float) * num_items, cudaMemcpyHostToDevice));\n        CubDebugExit(cudaMemcpy(d_values.d_buffers[d_values.selector], h_values, sizeof(int) * num_items, cudaMemcpyHostToDevice));\n\n        // Start timer\n        gpu_timer.Start();\n\n        // Allocate temporary storage for sorting\n        size_t  temp_storage_bytes  = 0;\n        void    *d_temp_storage     = NULL;\n        CubDebugExit(DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items));\n        CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n        // Do the sort\n        CubDebugExit(DeviceRadixSort::SortPairs(d_temp_storage, temp_storage_bytes, d_keys, d_values, num_items));\n\n        // Free unused buffers and sorting temporary storage\n        if (d_keys.d_buffers[d_keys.selector ^ 1]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[d_keys.selector ^ 1]));\n        if (d_values.d_buffers[d_values.selector ^ 1]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[d_values.selector ^ 1]));\n        if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n        // Start timer\n        gpu_rle_timer.Start();\n\n        // Allocate device arrays for enumerating non-trivial runs\n        int     *d_offests_out   = NULL;\n        int     *d_lengths_out   = NULL;\n        int     *d_num_runs      = NULL;\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_offests_out, sizeof(int) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_lengths_out, sizeof(int) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_runs, sizeof(int) * 1));\n\n        // Allocate temporary storage for isolating non-trivial runs\n        d_temp_storage = NULL;\n        CubDebugExit(DeviceRunLengthEncode::NonTrivialRuns(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys.d_buffers[d_keys.selector],\n            d_offests_out,\n            d_lengths_out,\n            d_num_runs,\n            num_items));\n        CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n        // Do the isolation\n        CubDebugExit(DeviceRunLengthEncode::NonTrivialRuns(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys.d_buffers[d_keys.selector],\n            d_offests_out,\n            d_lengths_out,\n            d_num_runs,\n            num_items));\n\n        // Free keys buffer\n        if (d_keys.d_buffers[d_keys.selector]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[d_keys.selector]));\n\n        //\n        // Hypothetically do stuff with the original key-indices corresponding to non-trivial runs of identical keys\n        //\n\n        // Stop sort timer\n        gpu_timer.Stop();\n        gpu_rle_timer.Stop();\n\n        if (i == 0)\n        {\n            // First iteration is a warmup: // Check for correctness (and display results, if specified)\n\n            printf(\"\\nRUN OFFSETS: \\n\");\n            int compare = CompareDeviceResults(h_offsets_reference, d_offests_out, num_runs, true, g_verbose);\n            printf(\"\\t\\t %s \", compare ? \"FAIL\" : \"PASS\");\n\n            printf(\"\\nRUN LENGTHS: \\n\");\n            compare |= CompareDeviceResults(h_lengths_reference, d_lengths_out, num_runs, true, g_verbose);\n            printf(\"\\t\\t %s \", compare ? \"FAIL\" : \"PASS\");\n\n            printf(\"\\nNUM RUNS: \\n\");\n            compare |= CompareDeviceResults(&num_runs, d_num_runs, 1, true, g_verbose);\n            printf(\"\\t\\t %s \", compare ? \"FAIL\" : \"PASS\");\n\n            AssertEquals(0, compare);\n        }\n        else\n        {\n            elapsed_millis += gpu_timer.ElapsedMillis();\n            elapsed_rle_millis += gpu_rle_timer.ElapsedMillis();\n        }\n\n        // GPU cleanup\n\n        if (d_values.d_buffers[d_values.selector]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[d_values.selector]));\n        if (d_offests_out) CubDebugExit(g_allocator.DeviceFree(d_offests_out));\n        if (d_lengths_out) CubDebugExit(g_allocator.DeviceFree(d_lengths_out));\n        if (d_num_runs) CubDebugExit(g_allocator.DeviceFree(d_num_runs));\n        if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n    }\n\n    // Host cleanup\n    if (h_keys) delete[] h_keys;\n    if (h_values) delete[] h_values;\n    if (h_offsets_reference) delete[] h_offsets_reference;\n    if (h_lengths_reference) delete[] h_lengths_reference;\n\n    printf(\"\\n\\n\");\n\n    if (timing_iterations > 0)\n    {\n        printf(\"%d timing iterations, average time to sort and isolate non-trivial duplicates: %.3f ms (%.3f ms spent in RLE isolation)\\n\",\n            timing_iterations,\n            elapsed_millis / timing_iterations,\n            elapsed_rle_millis / timing_iterations);\n    }\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/experimental/.gitignore",
    "content": "/bin\n"
  },
  {
    "path": "external/cub/experimental/Makefile",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n\n#-------------------------------------------------------------------------------\n#\n# Makefile usage\n#\n# make <target> [sm=<XXX,...>] [cdp=<0|1>] [force32=<0|1>] [abi=<0|1>] [open64=<0|1>] [verbose=<0|1>] [keep=<0|1>] [quicktest=<0|1>]\n#\n#-------------------------------------------------------------------------------\n \ninclude ../common.mk \n\n#-------------------------------------------------------------------------------\n# Commandline Options\n#-------------------------------------------------------------------------------\n\n# [mkl=<0|1>] compile against Intel MKL\nifeq ($(mkl), 1)\n\tDEFINES \t+= -DCUB_MKL\n\nifeq (WIN_NT, $(findstring WIN_NT, $(OSUPPER)))\n\tLIBS \t\t+=\tmkl_intel_lp64.lib mkl_intel_thread.lib  mkl_core.lib libiomp5md.lib\n\tNVCCFLAGS \t+= -Xcompiler /openmp\nelse\n\tLIBS\t\t+= -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm\n\tNVCCFLAGS \t+= -Xcompiler -fopenmp\n\t\nendif\t\n\nendif\n\n\n#-------------------------------------------------------------------------------\n# Compiler and compilation platform\n#-------------------------------------------------------------------------------\n\n# Includes\nINC += -I$(CUB_DIR) -I$(CUB_DIR)test \n\n# detect OS\nOSUPPER = $(shell uname -s 2>/dev/null | tr [:lower:] [:upper:])\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nexp_rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nEXP_DEPS = \t$(call rwildcard, ./,*.cuh) \\\n\t\t\t$(call rwildcard, ./,*.h)\n\nDEPS =\t\t\t\t$(CUB_DEPS) \\\n\t\t\t\t\t$(EXP_DEPS) \\\n\t\t\t\t\t$(CUB_DIR)test/Makefile \\\n\t\t\t\t\t$(CUB_DIR)test/test_util.h \\\n\t\t\t\t\t$(CUB_DIR)test/mersenne.h \\\n\n\t\t\n\n#-------------------------------------------------------------------------------\n# make default\n#-------------------------------------------------------------------------------\n\ndefault:\n\n\n#-------------------------------------------------------------------------------\n# make clean\n#-------------------------------------------------------------------------------\n\nclean :\n\trm -f bin/*$(CPU_ARCH_SUFFIX)* \n\trm -f *.i* *.cubin *.cu.c *.cudafe* *.fatbin.c *.ptx *.hash *.cu.cpp *.o\n\n\n\n#-------------------------------------------------------------------------------\n# make histogram_compare\n#-------------------------------------------------------------------------------\n\nhistogram_compare: bin/histogram_compare_$(BIN_SUFFIX)\n\nbin/histogram_compare_$(BIN_SUFFIX) : histogram_compare.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/histogram_compare_$(BIN_SUFFIX) histogram_compare.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\t\n\n\n#-------------------------------------------------------------------------------\n# make spmv_compare\n#-------------------------------------------------------------------------------\n\nspmv_compare: bin/spmv_compare_$(BIN_SUFFIX)\n\nbin/spmv_compare_$(BIN_SUFFIX) : spmv_compare.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/spmv_compare_$(BIN_SUFFIX) spmv_compare.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -lcusparse $(MKL_LIBS) -O3\n\t\n\n"
  },
  {
    "path": "external/cub/experimental/defunct/example_coo_spmv.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * An implementation of COO SpMV using prefix scan to implement a\n * reduce-value-by-row strategy\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <iterator>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <stdio.h>\n\n#include <cub/cub.cuh>\n\n#include \"coo_graph.cuh\"\n#include \"../test/test_util.h\"\n\nusing namespace cub;\nusing namespace std;\n\n\n/******************************************************************************\n * Globals, constants, and typedefs\n ******************************************************************************/\n\ntypedef int         VertexId;   // uint32s as vertex ids\ntypedef double      Value;      // double-precision floating point values\n\nbool                    g_verbose       = false;\nint                     g_timing_iterations    = 1;\nCachingDeviceAllocator  g_allocator;\n\n\n/******************************************************************************\n * Texture referencing\n ******************************************************************************/\n\n/**\n * Templated texture reference type for multiplicand vector\n */\ntemplate <typename Value>\nstruct TexVector\n{\n    // Texture type to actually use (e.g., because CUDA doesn't load doubles as texture items)\n    typedef typename If<(Equals<Value, double>::VALUE), uint2, Value>::Type CastType;\n\n    // Texture reference type\n    typedef texture<CastType, cudaTextureType1D, cudaReadModeElementType> TexRef;\n\n    static TexRef ref;\n\n    /**\n     * Bind textures\n     */\n    static void BindTexture(void *d_in, int elements)\n    {\n        cudaChannelFormatDesc tex_desc = cudaCreateChannelDesc<CastType>();\n        if (d_in)\n        {\n            size_t offset;\n            size_t bytes = sizeof(CastType) * elements;\n            CubDebugExit(cudaBindTexture(&offset, ref, d_in, tex_desc, bytes));\n        }\n    }\n\n    /**\n     * Unbind textures\n     */\n    static void UnbindTexture()\n    {\n        CubDebugExit(cudaUnbindTexture(ref));\n    }\n\n    /**\n     * Load\n     */\n    static __device__ __forceinline__ Value Load(int offset)\n    {\n        Value output;\n        reinterpret_cast<typename TexVector<Value>::CastType &>(output) = tex1Dfetch(TexVector<Value>::ref, offset);\n        return output;\n    }\n};\n\n// Texture reference definitions\ntemplate <typename Value>\ntypename TexVector<Value>::TexRef TexVector<Value>::ref = 0;\n\n\n/******************************************************************************\n * Utility types\n ******************************************************************************/\n\n\n/**\n * A partial dot-product sum paired with a corresponding row-id\n */\ntemplate <typename VertexId, typename Value>\nstruct PartialProduct\n{\n    VertexId    row;            /// Row-id\n    Value       partial;        /// PartialProduct sum\n};\n\n\n/**\n * A partial dot-product sum paired with a corresponding row-id (specialized for double-int pairings)\n */\ntemplate <>\nstruct PartialProduct<int, double>\n{\n    long long   row;            /// Row-id\n    double      partial;        /// PartialProduct sum\n};\n\n\n/**\n * Reduce-value-by-row scan operator\n */\nstruct ReduceByKeyOp\n{\n    template <typename PartialProduct>\n    __device__ __forceinline__ PartialProduct operator()(\n        const PartialProduct &first,\n        const PartialProduct &second)\n    {\n        PartialProduct retval;\n\n        retval.partial = (second.row != first.row) ?\n                second.partial :\n                first.partial + second.partial;\n\n        retval.row = second.row;\n        return retval;\n    }\n};\n\n\n/**\n * Stateful block-wide prefix operator for BlockScan\n */\ntemplate <typename PartialProduct>\nstruct BlockPrefixCallbackOp\n{\n    // Running block-wide prefix\n    PartialProduct running_prefix;\n\n    /**\n     * Returns the block-wide running_prefix in thread-0\n     */\n    __device__ __forceinline__ PartialProduct operator()(\n        const PartialProduct &block_aggregate)              ///< The aggregate sum of the BlockScan inputs\n    {\n        ReduceByKeyOp scan_op;\n\n        PartialProduct retval = running_prefix;\n        running_prefix = scan_op(running_prefix, block_aggregate);\n        return retval;\n    }\n};\n\n\n/**\n * Operator for detecting discontinuities in a list of row identifiers.\n */\nstruct NewRowOp\n{\n    /// Returns true if row_b is the start of a new row\n    template <typename VertexId>\n    __device__ __forceinline__ bool operator()(\n        const VertexId& row_a,\n        const VertexId& row_b)\n    {\n        return (row_a != row_b);\n    }\n};\n\n\n\n/******************************************************************************\n * Persistent thread block types\n ******************************************************************************/\n\n/**\n * SpMV thread block abstraction for processing a contiguous segment of\n * sparse COO tiles.\n */\ntemplate <\n    int             BLOCK_THREADS,\n    int             ITEMS_PER_THREAD,\n    typename        VertexId,\n    typename        Value>\nstruct PersistentBlockSpmv\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // Constants\n    enum\n    {\n        TILE_ITEMS = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    // Head flag type\n    typedef int HeadFlag;\n\n    // Partial dot product type\n    typedef PartialProduct<VertexId, Value> PartialProduct;\n\n    // Parameterized BlockScan type for reduce-value-by-row scan\n    typedef BlockScan<PartialProduct, BLOCK_THREADS, BLOCK_SCAN_RAKING_MEMOIZE> BlockScan;\n\n    // Parameterized BlockExchange type for exchanging rows between warp-striped -> blocked arrangements\n    typedef BlockExchange<VertexId, BLOCK_THREADS, ITEMS_PER_THREAD, true> BlockExchangeRows;\n\n    // Parameterized BlockExchange type for exchanging values between warp-striped -> blocked arrangements\n    typedef BlockExchange<Value, BLOCK_THREADS, ITEMS_PER_THREAD, true> BlockExchangeValues;\n\n    // Parameterized BlockDiscontinuity type for setting head-flags for each new row segment\n    typedef BlockDiscontinuity<HeadFlag, BLOCK_THREADS> BlockDiscontinuity;\n\n    // Shared memory type for this thread block\n    struct TempStorage\n    {\n        union\n        {\n            typename BlockExchangeRows::TempStorage         exchange_rows;      // Smem needed for BlockExchangeRows\n            typename BlockExchangeValues::TempStorage       exchange_values;    // Smem needed for BlockExchangeValues\n            struct\n            {\n                typename BlockScan::TempStorage             scan;               // Smem needed for BlockScan\n                typename BlockDiscontinuity::TempStorage    discontinuity;      // Smem needed for BlockDiscontinuity\n            };\n        };\n\n        VertexId        first_block_row;    ///< The first row-ID seen by this thread block\n        VertexId        last_block_row;     ///< The last row-ID seen by this thread block\n        Value           first_product;      ///< The first dot-product written by this thread block\n    };\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    TempStorage                     &temp_storage;\n    BlockPrefixCallbackOp<PartialProduct>   prefix_op;\n    VertexId                        *d_rows;\n    VertexId                        *d_columns;\n    Value                           *d_values;\n    Value                           *d_vector;\n    Value                           *d_result;\n    PartialProduct                  *d_block_partials;\n    int                             block_offset;\n    int                             block_end;\n\n\n    //---------------------------------------------------------------------\n    // Operations\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__\n    PersistentBlockSpmv(\n        TempStorage                 &temp_storage,\n        VertexId                    *d_rows,\n        VertexId                    *d_columns,\n        Value                       *d_values,\n        Value                       *d_vector,\n        Value                       *d_result,\n        PartialProduct              *d_block_partials,\n        int                         block_offset,\n        int                         block_end)\n    :\n        temp_storage(temp_storage),\n        d_rows(d_rows),\n        d_columns(d_columns),\n        d_values(d_values),\n        d_vector(d_vector),\n        d_result(d_result),\n        d_block_partials(d_block_partials),\n        block_offset(block_offset),\n        block_end(block_end)\n    {\n        // Initialize scalar shared memory values\n        if (threadIdx.x == 0)\n        {\n            VertexId first_block_row            = d_rows[block_offset];\n            VertexId last_block_row             = d_rows[block_end - 1];\n\n            temp_storage.first_block_row        = first_block_row;\n            temp_storage.last_block_row         = last_block_row;\n            temp_storage.first_product          = Value(0);\n\n            // Initialize prefix_op to identity\n            prefix_op.running_prefix.row        = first_block_row;\n            prefix_op.running_prefix.partial    = Value(0);\n        }\n\n        __syncthreads();\n    }\n\n\n    /**\n     * Processes a COO input tile of edges, outputting dot products for each row\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void ProcessTile(\n        int block_offset,\n        int guarded_items = 0)\n    {\n        VertexId        columns[ITEMS_PER_THREAD];\n        VertexId        rows[ITEMS_PER_THREAD];\n        Value           values[ITEMS_PER_THREAD];\n        PartialProduct  partial_sums[ITEMS_PER_THREAD];\n        HeadFlag        head_flags[ITEMS_PER_THREAD];\n\n        // Load a thread block-striped tile of A (sparse row-ids, column-ids, and values)\n        if (FULL_TILE)\n        {\n            // Unguarded loads\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_columns + block_offset, columns);\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_values + block_offset, values);\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_rows + block_offset, rows);\n        }\n        else\n        {\n            // This is a partial-tile (e.g., the last tile of input).  Extend the coordinates of the last\n            // vertex for out-of-bound items, but zero-valued\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_columns + block_offset, columns, guarded_items, VertexId(0));\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_values + block_offset, values, guarded_items, Value(0));\n            LoadDirectWarpStriped<LOAD_DEFAULT>(threadIdx.x, d_rows + block_offset, rows, guarded_items, temp_storage.last_block_row);\n        }\n\n        // Load the referenced values from x and compute the dot product partials sums\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n#if CUB_PTX_ARCH >= 350\n            values[ITEM] *= ThreadLoad<LOAD_LDG>(d_vector + columns[ITEM]);\n#else\n            values[ITEM] *= TexVector<Value>::Load(columns[ITEM]);\n#endif\n        }\n\n        // Transpose from warp-striped to blocked arrangement\n        BlockExchangeValues(temp_storage.exchange_values).WarpStripedToBlocked(values);\n\n        __syncthreads();\n\n        // Transpose from warp-striped to blocked arrangement\n        BlockExchangeRows(temp_storage.exchange_rows).WarpStripedToBlocked(rows);\n\n        // Barrier for smem reuse and coherence\n        __syncthreads();\n\n        // FlagT row heads by looking for discontinuities\n        BlockDiscontinuity(temp_storage.discontinuity).FlagHeads(\n            head_flags,                     // (Out) Head flags\n            rows,                           // Original row ids\n            NewRowOp(),                     // Functor for detecting start of new rows\n            prefix_op.running_prefix.row);  // Last row ID from previous tile to compare with first row ID in this tile\n\n        // Assemble partial product structures\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            partial_sums[ITEM].partial = values[ITEM];\n            partial_sums[ITEM].row = rows[ITEM];\n        }\n\n        // Reduce reduce-value-by-row across partial_sums using exclusive prefix scan\n        PartialProduct block_aggregate;\n        BlockScan(temp_storage.scan).ExclusiveScan(\n            partial_sums,                   // Scan input\n            partial_sums,                   // Scan output\n            ReduceByKeyOp(),                // Scan operator\n            block_aggregate,                // Block-wide total (unused)\n            prefix_op);                     // Prefix operator for seeding the block-wide scan with the running total\n\n        // Barrier for smem reuse and coherence\n        __syncthreads();\n\n        // Scatter an accumulated dot product if it is the head of a valid row\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if (head_flags[ITEM])\n            {\n                d_result[partial_sums[ITEM].row] = partial_sums[ITEM].partial;\n\n                // Save off the first partial product that this thread block will scatter\n                if (partial_sums[ITEM].row == temp_storage.first_block_row)\n                {\n                    temp_storage.first_product = partial_sums[ITEM].partial;\n                }\n            }\n        }\n    }\n\n\n    /**\n     * Iterate over input tiles belonging to this thread block\n     */\n    __device__ __forceinline__\n    void ProcessTiles()\n    {\n        // Process full tiles\n        while (block_offset <= block_end - TILE_ITEMS)\n        {\n            ProcessTile<true>(block_offset);\n            block_offset += TILE_ITEMS;\n        }\n\n        // Process the last, partially-full tile (if present)\n        int guarded_items = block_end - block_offset;\n        if (guarded_items)\n        {\n            ProcessTile<false>(block_offset, guarded_items);\n        }\n\n        if (threadIdx.x == 0)\n        {\n            if (gridDim.x == 1)\n            {\n                // Scatter the final aggregate (this kernel contains only 1 thread block)\n                d_result[prefix_op.running_prefix.row] = prefix_op.running_prefix.partial;\n            }\n            else\n            {\n                // Write the first and last partial products from this thread block so\n                // that they can be subsequently \"fixed up\" in the next kernel.\n\n                PartialProduct first_product;\n                first_product.row       = temp_storage.first_block_row;\n                first_product.partial   = temp_storage.first_product;\n\n                d_block_partials[blockIdx.x * 2]          = first_product;\n                d_block_partials[(blockIdx.x * 2) + 1]    = prefix_op.running_prefix;\n            }\n        }\n    }\n};\n\n\n/**\n * Threadblock abstraction for \"fixing up\" an array of interblock SpMV partial products.\n */\ntemplate <\n    int             BLOCK_THREADS,\n    int             ITEMS_PER_THREAD,\n    typename        VertexId,\n    typename        Value>\nstruct FinalizeSpmvBlock\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // Constants\n    enum\n    {\n        TILE_ITEMS = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    // Head flag type\n    typedef int HeadFlag;\n\n    // Partial dot product type\n    typedef PartialProduct<VertexId, Value> PartialProduct;\n\n    // Parameterized BlockScan type for reduce-value-by-row scan\n    typedef BlockScan<PartialProduct, BLOCK_THREADS, BLOCK_SCAN_RAKING_MEMOIZE> BlockScan;\n\n    // Parameterized BlockDiscontinuity type for setting head-flags for each new row segment\n    typedef BlockDiscontinuity<HeadFlag, BLOCK_THREADS> BlockDiscontinuity;\n\n    // Shared memory type for this thread block\n    struct TempStorage\n    {\n        typename BlockScan::TempStorage           scan;               // Smem needed for reduce-value-by-row scan\n        typename BlockDiscontinuity::TempStorage  discontinuity;      // Smem needed for head-flagging\n\n        VertexId last_block_row;\n    };\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    TempStorage                     &temp_storage;\n    BlockPrefixCallbackOp<PartialProduct>   prefix_op;\n    Value                           *d_result;\n    PartialProduct                  *d_block_partials;\n    int                             num_partials;\n\n\n    //---------------------------------------------------------------------\n    // Operations\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__\n    FinalizeSpmvBlock(\n        TempStorage                 &temp_storage,\n        Value                       *d_result,\n        PartialProduct              *d_block_partials,\n        int                         num_partials)\n    :\n        temp_storage(temp_storage),\n        d_result(d_result),\n        d_block_partials(d_block_partials),\n        num_partials(num_partials)\n    {\n        // Initialize scalar shared memory values\n        if (threadIdx.x == 0)\n        {\n            VertexId first_block_row            = d_block_partials[0].row;\n            VertexId last_block_row             = d_block_partials[num_partials - 1].row;\n            temp_storage.last_block_row         = last_block_row;\n\n            // Initialize prefix_op to identity\n            prefix_op.running_prefix.row        = first_block_row;\n            prefix_op.running_prefix.partial    = Value(0);\n        }\n\n        __syncthreads();\n    }\n\n\n    /**\n     * Processes a COO input tile of edges, outputting dot products for each row\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__\n    void ProcessTile(\n        int block_offset,\n        int guarded_items = 0)\n    {\n        VertexId        rows[ITEMS_PER_THREAD];\n        PartialProduct  partial_sums[ITEMS_PER_THREAD];\n        HeadFlag        head_flags[ITEMS_PER_THREAD];\n\n        // Load a tile of block partials from previous kernel\n        if (FULL_TILE)\n        {\n            // Full tile\n#if CUB_PTX_ARCH >= 350\n            LoadDirectBlocked<LOAD_LDG>(threadIdx.x, d_block_partials + block_offset, partial_sums);\n#else\n            LoadDirectBlocked(threadIdx.x, d_block_partials + block_offset, partial_sums);\n#endif\n        }\n        else\n        {\n            // Partial tile (extend zero-valued coordinates of the last partial-product for out-of-bounds items)\n            PartialProduct default_sum;\n            default_sum.row = temp_storage.last_block_row;\n            default_sum.partial = Value(0);\n\n#if CUB_PTX_ARCH >= 350\n            LoadDirectBlocked<LOAD_LDG>(threadIdx.x, d_block_partials + block_offset, partial_sums, guarded_items, default_sum);\n#else\n            LoadDirectBlocked(threadIdx.x, d_block_partials + block_offset, partial_sums, guarded_items, default_sum);\n#endif\n        }\n\n        // Copy out row IDs for row-head flagging\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            rows[ITEM] = partial_sums[ITEM].row;\n        }\n\n        // FlagT row heads by looking for discontinuities\n        BlockDiscontinuity(temp_storage.discontinuity).FlagHeads(\n            rows,                           // Original row ids\n            head_flags,                     // (Out) Head flags\n            NewRowOp(),                     // Functor for detecting start of new rows\n            prefix_op.running_prefix.row);   // Last row ID from previous tile to compare with first row ID in this tile\n\n        // Reduce reduce-value-by-row across partial_sums using exclusive prefix scan\n        PartialProduct block_aggregate;\n        BlockScan(temp_storage.scan).ExclusiveScan(\n            partial_sums,                   // Scan input\n            partial_sums,                   // Scan output\n            ReduceByKeyOp(),                // Scan operator\n            block_aggregate,                // Block-wide total (unused)\n            prefix_op);                     // Prefix operator for seeding the block-wide scan with the running total\n\n        // Scatter an accumulated dot product if it is the head of a valid row\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if (head_flags[ITEM])\n            {\n                d_result[partial_sums[ITEM].row] = partial_sums[ITEM].partial;\n            }\n        }\n    }\n\n\n    /**\n     * Iterate over input tiles belonging to this thread block\n     */\n    __device__ __forceinline__\n    void ProcessTiles()\n    {\n        // Process full tiles\n        int block_offset = 0;\n        while (block_offset <= num_partials - TILE_ITEMS)\n        {\n            ProcessTile<true>(block_offset);\n            block_offset += TILE_ITEMS;\n        }\n\n        // Process final partial tile (if present)\n        int guarded_items = num_partials - block_offset;\n        if (guarded_items)\n        {\n            ProcessTile<false>(block_offset, guarded_items);\n        }\n\n        // Scatter the final aggregate (this kernel contains only 1 thread block)\n        if (threadIdx.x == 0)\n        {\n            d_result[prefix_op.running_prefix.row] = prefix_op.running_prefix.partial;\n        }\n    }\n};\n\n\n/******************************************************************************\n * Kernel entrypoints\n ******************************************************************************/\n\n\n\n/**\n * SpMV kernel whose thread blocks each process a contiguous segment of sparse COO tiles.\n */\ntemplate <\n    int                             BLOCK_THREADS,\n    int                             ITEMS_PER_THREAD,\n    typename                        VertexId,\n    typename                        Value>\n__launch_bounds__ (BLOCK_THREADS)\n__global__ void CooKernel(\n    GridEvenShare<int>              even_share,\n    PartialProduct<VertexId, Value> *d_block_partials,\n    VertexId                        *d_rows,\n    VertexId                        *d_columns,\n    Value                           *d_values,\n    Value                           *d_vector,\n    Value                           *d_result)\n{\n    // Specialize SpMV thread block abstraction type\n    typedef PersistentBlockSpmv<BLOCK_THREADS, ITEMS_PER_THREAD, VertexId, Value> PersistentBlockSpmv;\n\n    // Shared memory allocation\n    __shared__ typename PersistentBlockSpmv::TempStorage temp_storage;\n\n    // Initialize thread block even-share to tell us where to start and stop our tile-processing\n    even_share.BlockInit();\n\n    // Construct persistent thread block\n    PersistentBlockSpmv persistent_block(\n        temp_storage,\n        d_rows,\n        d_columns,\n        d_values,\n        d_vector,\n        d_result,\n        d_block_partials,\n        even_share.block_offset,\n        even_share.block_end);\n\n    // Process input tiles\n    persistent_block.ProcessTiles();\n}\n\n\n/**\n * Kernel for \"fixing up\" an array of interblock SpMV partial products.\n */\ntemplate <\n    int                             BLOCK_THREADS,\n    int                             ITEMS_PER_THREAD,\n    typename                        VertexId,\n    typename                        Value>\n__launch_bounds__ (BLOCK_THREADS,  1)\n__global__ void CooFinalizeKernel(\n    PartialProduct<VertexId, Value> *d_block_partials,\n    int                             num_partials,\n    Value                           *d_result)\n{\n    // Specialize \"fix-up\" thread block abstraction type\n    typedef FinalizeSpmvBlock<BLOCK_THREADS, ITEMS_PER_THREAD, VertexId, Value> FinalizeSpmvBlock;\n\n    // Shared memory allocation\n    __shared__ typename FinalizeSpmvBlock::TempStorage temp_storage;\n\n    // Construct persistent thread block\n    FinalizeSpmvBlock persistent_block(temp_storage, d_result, d_block_partials, num_partials);\n\n    // Process input tiles\n    persistent_block.ProcessTiles();\n}\n\n\n\n//---------------------------------------------------------------------\n// Host subroutines\n//---------------------------------------------------------------------\n\n\n/**\n * Simple test of device\n */\ntemplate <\n    int                         COO_BLOCK_THREADS,\n    int                         COO_ITEMS_PER_THREAD,\n    int                         COO_SUBSCRIPTION_FACTOR,\n    int                         FINALIZE_BLOCK_THREADS,\n    int                         FINALIZE_ITEMS_PER_THREAD,\n    typename                    VertexId,\n    typename                    Value>\nvoid TestDevice(\n    CooGraph<VertexId, Value>&  coo_graph,\n    Value*                      h_vector,\n    Value*                      h_reference)\n{\n    typedef PartialProduct<VertexId, Value> PartialProduct;\n\n    const int COO_TILE_SIZE = COO_BLOCK_THREADS * COO_ITEMS_PER_THREAD;\n\n    // SOA device storage\n    VertexId        *d_rows;             // SOA graph row coordinates\n    VertexId        *d_columns;          // SOA graph col coordinates\n    Value           *d_values;           // SOA graph values\n    Value           *d_vector;           // Vector multiplicand\n    Value           *d_result;           // Output row\n    PartialProduct  *d_block_partials;   // Temporary storage for communicating dot product partials between thread blocks\n\n    // Create SOA version of coo_graph on host\n    int             num_edges   = coo_graph.coo_tuples.size();\n    VertexId        *h_rows     = new VertexId[num_edges];\n    VertexId        *h_columns  = new VertexId[num_edges];\n    Value           *h_values   = new Value[num_edges];\n    for (int i = 0; i < num_edges; i++)\n    {\n        h_rows[i]       = coo_graph.coo_tuples[i].row;\n        h_columns[i]    = coo_graph.coo_tuples[i].col;\n        h_values[i]     = coo_graph.coo_tuples[i].val;\n    }\n\n    // Get CUDA properties\n    Device device_props;\n    CubDebugExit(device_props.Init());\n\n    // Determine launch configuration from kernel properties\n    int coo_sm_occupancy;\n    CubDebugExit(device_props.MaxSmOccupancy(\n        coo_sm_occupancy,\n        CooKernel<COO_BLOCK_THREADS, COO_ITEMS_PER_THREAD, VertexId, Value>,\n        COO_BLOCK_THREADS));\n    int max_coo_grid_size   = device_props.sm_count * coo_sm_occupancy * COO_SUBSCRIPTION_FACTOR;\n\n    // Construct an even-share work distribution\n    GridEvenShare<int> even_share(num_edges, max_coo_grid_size, COO_TILE_SIZE);\n    int coo_grid_size  = even_share.grid_size;\n    int num_partials   = coo_grid_size * 2;\n\n    // Allocate COO device arrays\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_rows,            sizeof(VertexId) * num_edges));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_columns,         sizeof(VertexId) * num_edges));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values,          sizeof(Value) * num_edges));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_vector,          sizeof(Value) * coo_graph.col_dim));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_result,          sizeof(Value) * coo_graph.row_dim));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_block_partials,  sizeof(PartialProduct) * num_partials));\n\n    // Copy host arrays to device\n    CubDebugExit(cudaMemcpy(d_rows,     h_rows,     sizeof(VertexId) * num_edges,       cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_columns,  h_columns,  sizeof(VertexId) * num_edges,       cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_values,   h_values,   sizeof(Value) * num_edges,          cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_vector,   h_vector,   sizeof(Value) * coo_graph.col_dim,  cudaMemcpyHostToDevice));\n\n    // Bind textures\n    TexVector<Value>::BindTexture(d_vector, coo_graph.col_dim);\n\n    // Print debug info\n    printf(\"CooKernel<%d, %d><<<%d, %d>>>(...), Max SM occupancy: %d\\n\",\n        COO_BLOCK_THREADS, COO_ITEMS_PER_THREAD, coo_grid_size, COO_BLOCK_THREADS, coo_sm_occupancy);\n    if (coo_grid_size > 1)\n    {\n        printf(\"CooFinalizeKernel<<<1, %d>>>(...)\\n\", FINALIZE_BLOCK_THREADS);\n    }\n    fflush(stdout);\n\n    CubDebugExit(cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeEightByte));\n\n    // Run kernel (always run one iteration without timing)\n    GpuTimer gpu_timer;\n    float elapsed_millis = 0.0;\n    for (int i = 0; i <= g_timing_iterations; i++)\n    {\n        gpu_timer.Start();\n\n        // Initialize output\n        CubDebugExit(cudaMemset(d_result, 0, coo_graph.row_dim * sizeof(Value)));\n\n        // Run the COO kernel\n        CooKernel<COO_BLOCK_THREADS, COO_ITEMS_PER_THREAD><<<coo_grid_size, COO_BLOCK_THREADS>>>(\n            even_share,\n            d_block_partials,\n            d_rows,\n            d_columns,\n            d_values,\n            d_vector,\n            d_result);\n\n        if (coo_grid_size > 1)\n        {\n            // Run the COO finalize kernel\n            CooFinalizeKernel<FINALIZE_BLOCK_THREADS, FINALIZE_ITEMS_PER_THREAD><<<1, FINALIZE_BLOCK_THREADS>>>(\n                d_block_partials,\n                num_partials,\n                d_result);\n        }\n\n        gpu_timer.Stop();\n\n        if (i > 0)\n            elapsed_millis += gpu_timer.ElapsedMillis();\n    }\n\n    // Force any kernel stdio to screen\n    CubDebugExit(cudaThreadSynchronize());\n    fflush(stdout);\n\n    // Display timing\n    if (g_timing_iterations > 0)\n    {\n        float avg_elapsed = elapsed_millis / g_timing_iterations;\n        int total_bytes = ((sizeof(VertexId) + sizeof(VertexId)) * 2 * num_edges) + (sizeof(Value) * coo_graph.row_dim);\n        printf(\"%d iterations, average elapsed (%.3f ms), utilized bandwidth (%.3f GB/s), GFLOPS(%.3f)\\n\",\n            g_timing_iterations,\n            avg_elapsed,\n            total_bytes / avg_elapsed / 1000.0 / 1000.0,\n            num_edges * 2 / avg_elapsed / 1000.0 / 1000.0);\n    }\n\n    // Check results\n    int compare = CompareDeviceResults(h_reference, d_result, coo_graph.row_dim, true, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    TexVector<Value>::UnbindTexture();\n    CubDebugExit(g_allocator.DeviceFree(d_block_partials));\n    CubDebugExit(g_allocator.DeviceFree(d_rows));\n    CubDebugExit(g_allocator.DeviceFree(d_columns));\n    CubDebugExit(g_allocator.DeviceFree(d_values));\n    CubDebugExit(g_allocator.DeviceFree(d_vector));\n    CubDebugExit(g_allocator.DeviceFree(d_result));\n    delete[] h_rows;\n    delete[] h_columns;\n    delete[] h_values;\n}\n\n\n/**\n * Compute reference answer on CPU\n */\ntemplate <typename VertexId, typename Value>\nvoid ComputeReference(\n    CooGraph<VertexId, Value>&  coo_graph,\n    Value*                      h_vector,\n    Value*                      h_reference)\n{\n    for (VertexId i = 0; i < coo_graph.row_dim; i++)\n    {\n        h_reference[i] = 0.0;\n    }\n\n    for (VertexId i = 0; i < coo_graph.coo_tuples.size(); i++)\n    {\n        h_reference[coo_graph.coo_tuples[i].row] +=\n            coo_graph.coo_tuples[i].val *\n            h_vector[coo_graph.coo_tuples[i].col];\n    }\n}\n\n\n/**\n * Assign arbitrary values to vector items\n */\ntemplate <typename Value>\nvoid AssignVectorValues(Value *vector, int col_dim)\n{\n    for (int i = 0; i < col_dim; i++)\n    {\n        vector[i] = 1.0;\n    }\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s\\n [--device=<device-id>] [--v] [--iterations=<test iterations>] [--grid-size=<grid-size>]\\n\"\n            \"\\t--type=wheel --spokes=<spokes>\\n\"\n            \"\\t--type=grid2d --width=<width> [--no-self-loops]\\n\"\n            \"\\t--type=grid3d --width=<width> [--no-self-loops]\\n\"\n            \"\\t--type=market --file=<file>\\n\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get graph type\n    string type;\n    args.GetCmdLineArgument(\"type\", type);\n\n    // Generate graph structure\n\n    CpuTimer timer;\n    timer.Start();\n    CooGraph<VertexId, Value> coo_graph;\n    if (type == string(\"grid2d\"))\n    {\n        VertexId width;\n        args.GetCmdLineArgument(\"width\", width);\n        bool self_loops = !args.CheckCmdLineFlag(\"no-self-loops\");\n        printf(\"Generating %s grid2d width(%d)... \", (self_loops) ? \"5-pt\" : \"4-pt\", width); fflush(stdout);\n        if (coo_graph.InitGrid2d(width, self_loops)) exit(1);\n    } else if (type == string(\"grid3d\"))\n    {\n        VertexId width;\n        args.GetCmdLineArgument(\"width\", width);\n        bool self_loops = !args.CheckCmdLineFlag(\"no-self-loops\");\n        printf(\"Generating %s grid3d width(%d)... \", (self_loops) ? \"7-pt\" : \"6-pt\", width); fflush(stdout);\n        if (coo_graph.InitGrid3d(width, self_loops)) exit(1);\n    }\n    else if (type == string(\"wheel\"))\n    {\n        VertexId spokes;\n        args.GetCmdLineArgument(\"spokes\", spokes);\n        printf(\"Generating wheel spokes(%d)... \", spokes); fflush(stdout);\n        if (coo_graph.InitWheel(spokes)) exit(1);\n    }\n    else if (type == string(\"market\"))\n    {\n        string filename;\n        args.GetCmdLineArgument(\"file\", filename);\n        printf(\"Generating MARKET for %s... \", filename.c_str()); fflush(stdout);\n        if (coo_graph.InitMarket(filename)) exit(1);\n    }\n    else\n    {\n        printf(\"Unsupported graph type\\n\");\n        exit(1);\n    }\n    timer.Stop();\n    printf(\"Done (%.3fs). %d non-zeros, %d rows, %d columns\\n\",\n        timer.ElapsedMillis() / 1000.0,\n        coo_graph.coo_tuples.size(),\n        coo_graph.row_dim,\n        coo_graph.col_dim);\n    fflush(stdout);\n\n    if (g_verbose)\n    {\n        cout << coo_graph << \"\\n\";\n    }\n\n    // Create vector\n    Value *h_vector = new Value[coo_graph.col_dim];\n    AssignVectorValues(h_vector, coo_graph.col_dim);\n    if (g_verbose)\n    {\n        printf(\"Vector[%d]: \", coo_graph.col_dim);\n        DisplayResults(h_vector, coo_graph.col_dim);\n        printf(\"\\n\\n\");\n    }\n\n    // Compute reference answer\n    Value *h_reference = new Value[coo_graph.row_dim];\n    ComputeReference(coo_graph, h_vector, h_reference);\n    if (g_verbose)\n    {\n        printf(\"Results[%d]: \", coo_graph.row_dim);\n        DisplayResults(h_reference, coo_graph.row_dim);\n        printf(\"\\n\\n\");\n    }\n\n    // Parameterization for SM35\n    enum\n    {\n        COO_BLOCK_THREADS           = 64,\n        COO_ITEMS_PER_THREAD        = 10,\n        COO_SUBSCRIPTION_FACTOR     = 4,\n        FINALIZE_BLOCK_THREADS      = 256,\n        FINALIZE_ITEMS_PER_THREAD   = 4,\n    };\n\n    // Run GPU version\n    TestDevice<\n        COO_BLOCK_THREADS,\n        COO_ITEMS_PER_THREAD,\n        COO_SUBSCRIPTION_FACTOR,\n        FINALIZE_BLOCK_THREADS,\n        FINALIZE_ITEMS_PER_THREAD>(coo_graph, h_vector, h_reference);\n\n    // Cleanup\n    delete[] h_vector;\n    delete[] h_reference;\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/experimental/defunct/test_device_seg_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * An implementation of segmented reduction using a load-balanced parallelization\n * strategy based on the MergePath decision path.\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <iterator>\n#include <vector>\n#include <string>\n#include <algorithm>\n#include <stdio.h>\n\n#include <cub/cub.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\nusing namespace std;\n\n\n/******************************************************************************\n * Globals, constants, and typedefs\n ******************************************************************************/\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 1;\nCachingDeviceAllocator  g_allocator(true);\n\n\n/******************************************************************************\n * Utility routines\n ******************************************************************************/\n\n\n/**\n * An pair of index offsets\n */\ntemplate <typename OffsetT>\nstruct IndexPair\n{\n    OffsetT a_idx;\n    OffsetT b_idx;\n};\n\n\n/**\n * Computes the begin offsets into A and B for the specified\n * location (diagonal) along the merge decision path\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    typename            IteratorA,\n    typename            IteratorB,\n    typename            OffsetT>\n__device__ __forceinline__ void ParallelMergePathSearch(\n    OffsetT             diagonal,\n    IteratorA           a,\n    IteratorB           b,\n    IndexPair<OffsetT>  begin,          // Begin offsets into a and b\n    IndexPair<OffsetT>  end,            // End offsets into a and b\n    IndexPair<OffsetT>  &intersection)  // [out] Intersection offsets into a and b\n{\n    OffsetT a_split_min = CUB_MAX(diagonal - end.b_idx, begin.a_idx);\n    OffsetT a_split_max = CUB_MIN(diagonal, end.a_idx);\n\n    while (a_split_min < a_split_max)\n    {\n        OffsetT a_distance       = a_split_max - a_split_min;\n        OffsetT a_slice          = (a_distance + BLOCK_THREADS - 1) >> Log2<BLOCK_THREADS>::VALUE;\n        OffsetT a_split_pivot    = CUB_MIN(a_split_min + (threadIdx.x * a_slice), end.a_idx - 1);\n\n        int move_up = (a[a_split_pivot] <= b[diagonal - a_split_pivot - 1]);\n        int num_up = __syncthreads_count(move_up);\n/*\n        _CubLog(\"a_split_min(%d), a_split_max(%d) a_distance(%d), a_slice(%d), a_split_pivot(%d), move_up(%d), num_up(%d), a_begin(%d), a_end(%d)\\n\",\n            a_split_min, a_split_max, a_distance, a_slice, a_split_pivot, move_up, num_up, a_begin, a_end);\n*/\n        a_split_max = CUB_MIN(num_up * a_slice, end.a_idx);\n        a_split_min = CUB_MAX(a_split_max - a_slice, begin.a_idx) + 1;\n    }\n\n    intersection.a_idx = CUB_MIN(a_split_min, end.a_idx);\n    intersection.b_idx = CUB_MIN(diagonal - a_split_min, end.b_idx);\n}\n\n/**\n * Computes the begin offsets into A and B for the specified\n * location (diagonal) along the merge decision path\n */\ntemplate <\n    typename            IteratorA,\n    typename            IteratorB,\n    typename            OffsetT>\n__device__ __forceinline__ void MergePathSearch(\n    OffsetT             diagonal,\n    IteratorA           a,\n    IteratorB           b,\n    IndexPair<OffsetT>  begin,          // Begin offsets into a and b\n    IndexPair<OffsetT>  end,            // End offsets into a and b\n    IndexPair<OffsetT>  &intersection)  // [out] Intersection offsets into a and b\n{\n    OffsetT split_min = CUB_MAX(diagonal - end.b_idx, begin.a_idx);\n    OffsetT split_max = CUB_MIN(diagonal, end.a_idx);\n\n    while (split_min < split_max)\n    {\n        OffsetT split_pivot = (split_min + split_max) >> 1;\n        if (a[split_pivot] <= b[diagonal - split_pivot - 1])\n        {\n            // Move candidate split range up A, down B\n            split_min = split_pivot + 1;\n        }\n        else\n        {\n            // Move candidate split range up B, down A\n            split_max = split_pivot;\n        }\n    }\n\n    intersection.a_idx = CUB_MIN(split_min, end.a_idx);\n    intersection.b_idx = CUB_MIN(diagonal - split_min, end.b_idx);\n}\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for BlockSegReduceRegion\n */\ntemplate <\n    int                     _BLOCK_THREADS,             ///< Threads per thread block\n    int                     _ITEMS_PER_THREAD,          ///< Items per thread (per tile of input)\n    bool                    _USE_SMEM_SEGMENT_CACHE,    ///< Whether or not to cache incoming segment offsets in shared memory before reducing each tile\n    bool                    _USE_SMEM_VALUE_CACHE,      ///< Whether or not to cache incoming values in shared memory before reducing each tile\n    CacheLoadModifier       _LOAD_MODIFIER_SEGMENTS,    ///< Cache load modifier for reading segment offsets\n    CacheLoadModifier       _LOAD_MODIFIER_VALUES,      ///< Cache load modifier for reading values\n    BlockReduceAlgorithm    _REDUCE_ALGORITHM,          ///< The BlockReduce algorithm to use\n    BlockScanAlgorithm      _SCAN_ALGORITHM>            ///< The BlockScan algorithm to use\nstruct BlockSegReduceRegionPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n        USE_SMEM_SEGMENT_CACHE  = _USE_SMEM_SEGMENT_CACHE,      ///< Whether or not to cache incoming segment offsets in shared memory before reducing each tile\n        USE_SMEM_VALUE_CACHE    = _USE_SMEM_VALUE_CACHE,        ///< Whether or not to cache incoming upcoming values in shared memory before reducing each tile\n    };\n\n    static const CacheLoadModifier      LOAD_MODIFIER_SEGMENTS  = _LOAD_MODIFIER_SEGMENTS;  ///< Cache load modifier for reading segment offsets\n    static const CacheLoadModifier      LOAD_MODIFIER_VALUES    = _LOAD_MODIFIER_VALUES;    ///< Cache load modifier for reading values\n    static const BlockReduceAlgorithm   REDUCE_ALGORITHM        = _REDUCE_ALGORITHM;        ///< The BlockReduce algorithm to use\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;          ///< The BlockScan algorithm to use\n};\n\n\n/******************************************************************************\n * Persistent thread block types\n ******************************************************************************/\n\n/**\n * \\brief BlockSegReduceTiles implements a stateful abstraction of CUDA thread blocks for participating in device-wide segmented reduction.\n */\ntemplate <\n    typename BlockSegReduceRegionPolicy,    ///< Parameterized BlockSegReduceRegionPolicy tuning policy\n    typename SegmentOffsetIterator,         ///< Random-access input iterator type for reading segment end-offsets\n    typename ValueIterator,                 ///< Random-access input iterator type for reading values\n    typename OutputIteratorT,               ///< Random-access output iterator type for writing segment reductions\n    typename ReductionOp,                   ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename OffsetT>                       ///< Signed integer type for global offsets\nstruct BlockSegReduceRegion\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // Constants\n    enum\n    {\n        BLOCK_THREADS       = BlockSegReduceRegionPolicy::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = BlockSegReduceRegionPolicy::ITEMS_PER_THREAD,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,                     /// Number of work items to be processed per tile\n\n        USE_SMEM_SEGMENT_CACHE  = BlockSegReduceRegionPolicy::USE_SMEM_SEGMENT_CACHE,      ///< Whether or not to cache incoming segment offsets in shared memory before reducing each tile\n        USE_SMEM_VALUE_CACHE    = BlockSegReduceRegionPolicy::USE_SMEM_VALUE_CACHE,        ///< Whether or not to cache incoming upcoming values in shared memory before reducing each tile\n\n        SMEM_SEGMENT_CACHE_ITEMS    = USE_SMEM_SEGMENT_CACHE ? TILE_ITEMS : 1,\n        SMEM_VALUE_CACHE_ITEMS      = USE_SMEM_VALUE_CACHE ? TILE_ITEMS : 1,\n    };\n\n    // Segment offset type\n    typedef typename std::iterator_traits<SegmentOffsetIterator>::value_type SegmentOffset;\n\n    // Value type\n    typedef typename std::iterator_traits<ValueIterator>::value_type Value;\n\n    // Counting iterator type\n    typedef CountingInputIterator<SegmentOffsetT, OffsetT> CountingIterator;\n\n    // Segment offsets iterator wrapper type\n    typedef typename If<(IsPointer<SegmentOffsetIterator>::VALUE),\n            CacheModifiedInputIterator<BlockSegReduceRegionPolicy::LOAD_MODIFIER_SEGMENTS, SegmentOffsetT, OffsetT>,  // Wrap the native input pointer with CacheModifiedInputIterator\n            SegmentOffsetIterator>::Type                                                                            // Directly use the supplied input iterator type\n        WrappedSegmentOffsetIterator;\n\n    // Values iterator wrapper type\n    typedef typename If<(IsPointer<ValueIterator>::VALUE),\n            CacheModifiedInputIterator<BlockSegReduceRegionPolicy::LOAD_MODIFIER_VALUES, Value, OffsetT>,        // Wrap the native input pointer with CacheModifiedInputIterator\n            ValueIterator>::Type                                                                                // Directly use the supplied input iterator type\n        WrappedValueIterator;\n\n    // Tail flag type for marking segment discontinuities\n    typedef int TailFlag;\n\n    // Reduce-by-key data type tuple (segment-ID, value)\n    typedef KeyValuePair<OffsetT, Value> KeyValuePair;\n\n    // Index pair data type\n    typedef IndexPair<OffsetT> IndexPair;\n\n    // BlockScan scan operator for reduction-by-segment\n    typedef ReduceByKeyOp<ReductionOp> ReduceByKeyOp;\n\n    // Stateful BlockScan prefix callback type for managing a running total while scanning consecutive tiles\n    typedef RunningBlockPrefixCallbackOp<\n            KeyValuePair,\n            ReduceByKeyOp>\n        RunningPrefixCallbackOp;\n\n    // Parameterized BlockShift type for exchanging index pairs\n    typedef BlockShift<\n            IndexPair,\n            BLOCK_THREADS>\n        BlockShift;\n\n    // Parameterized BlockReduce type for block-wide reduction\n    typedef BlockReduce<\n            Value,\n            BLOCK_THREADS,\n            BlockSegReduceRegionPolicy::REDUCE_ALGORITHM>\n        BlockReduce;\n\n    // Parameterized BlockScan type for block-wide reduce-value-by-key\n    typedef BlockScan<\n            KeyValuePair,\n            BLOCK_THREADS,\n            BlockSegReduceRegionPolicy::SCAN_ALGORITHM>\n        BlockScan;\n\n    // Shared memory type for this thread block\n    struct _TempStorage\n    {\n        union\n        {\n            // Smem needed for BlockScan\n            typename BlockScan::TempStorage scan;\n\n            // Smem needed for BlockReduce\n            typename BlockReduce::TempStorage reduce;\n\n            struct\n            {\n                // Smem needed for communicating start/end indices between threads for a given work tile\n                typename BlockShift::TempStorage shift;\n\n                // Smem needed for caching segment end-offsets\n                SegmentOffset cached_segment_end_offsets[SMEM_SEGMENT_CACHE_ITEMS + 1];\n            };\n\n            // Smem needed for caching values\n            Value cached_values[SMEM_VALUE_CACHE_ITEMS];\n        };\n\n        IndexPair block_region_idx[2];      // The starting [0] and ending [1] pairs of segment and value indices for the thread block's region\n\n        // The first partial reduction tuple scattered by this thread block\n        KeyValuePair first_tuple;\n    };\n\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage                    &temp_storage;          ///< Reference to shared storage\n    WrappedSegmentOffsetIterator    d_segment_end_offsets;  ///< A sequence of \\p num_segments segment end-offsets\n    WrappedValueIterator            d_values;               ///< A sequence of \\p num_values data to reduce\n    OutputIteratorT                  d_output;               ///< A sequence of \\p num_segments segment totals\n    CountingIterator                d_value_offsets;        ///< A sequence of \\p num_values value-offsets\n    IndexPair                       *d_block_idx;\n    OffsetT                         num_values;             ///< Total number of values to reduce\n    OffsetT                         num_segments;           ///< Number of segments being reduced\n    Value                           identity;               ///< Identity value (for zero-length segments)\n    ReductionOp                     reduction_op;           ///< Reduction operator\n    ReduceByKeyOp                   scan_op;                ///< Reduce-by-key scan operator\n    RunningPrefixCallbackOp         prefix_op;              ///< Stateful running total for block-wide prefix scan of partial reduction tuples\n\n\n    //---------------------------------------------------------------------\n    // Operations\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__\n    BlockSegReduceRegion(\n        TempStorage             &temp_storage,          ///< Reference to shared storage\n        SegmentOffsetIterator   d_segment_end_offsets,  ///< A sequence of \\p num_segments segment end-offsets\n        ValueIterator           d_values,               ///< A sequence of \\p num_values values\n        OutputIteratorT          d_output,               ///< A sequence of \\p num_segments segment totals\n        IndexPair               *d_block_idx,\n        OffsetT                 num_values,             ///< Number of values to reduce\n        OffsetT                 num_segments,           ///< Number of segments being reduced\n        Value                   identity,               ///< Identity value (for zero-length segments)\n        ReductionOp             reduction_op)           ///< Reduction operator\n    :\n        temp_storage(temp_storage.Alias()),\n        d_segment_end_offsets(d_segment_end_offsets),\n        d_values(d_values),\n        d_value_offsets(0),\n        d_output(d_output),\n        d_block_idx(d_block_idx),\n        num_values(num_values),\n        num_segments(num_segments),\n        identity(identity),\n        reduction_op(reduction_op),\n        scan_op(reduction_op),\n        prefix_op(scan_op)\n    {}\n\n\n    /**\n     * Fast-path single-segment tile reduction.  Perform a\n     * simple block-wide reduction and accumulate the result into\n     * the running total.\n     */\n    __device__ __forceinline__ void SingleSegmentTile(\n        IndexPair next_tile_idx,\n        IndexPair block_idx)\n    {\n        OffsetT tile_values = next_tile_idx.b_idx - block_idx.b_idx;\n\n        // Load a tile's worth of values (using identity for out-of-bounds items)\n        Value values[ITEMS_PER_THREAD];\n        LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_values + block_idx.b_idx, values, tile_values, identity);\n\n        // Barrier for smem reuse\n        __syncthreads();\n\n        // Reduce the tile of values and update the running total in thread-0\n        KeyValuePair tile_aggregate;\n        tile_aggregate.key      = block_idx.a_idx;\n        tile_aggregate.value    = BlockReduce(temp_storage.reduce).Reduce(values, reduction_op);\n\n        if (threadIdx.x == 0)\n        {\n            prefix_op.running_total = scan_op(prefix_op.running_total, tile_aggregate);\n        }\n    }\n\n    /**\n     * Fast-path empty-segment tile reduction.  Write out a tile of identity\n     * values to output.\n     */\n    __device__ __forceinline__ void EmptySegmentsTile(\n        IndexPair next_tile_idx,\n        IndexPair block_idx)\n    {\n        Value segment_reductions[ITEMS_PER_THREAD];\n\n        if (threadIdx.x == 0)\n        {\n            // The first segment gets the running segment total\n            segment_reductions[0] = prefix_op.running_total.value;\n\n            // Update the running prefix\n            prefix_op.running_total.value = identity;\n            prefix_op.running_total.key = next_tile_idx.a_idx;\n        }\n        else\n        {\n            // Remainder of segments in this tile get identity\n            segment_reductions[0] = identity;\n        }\n\n        // Remainder of segments in this tile get identity\n        #pragma unroll\n        for (int ITEM = 1; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            segment_reductions[ITEM] = identity;\n\n        // Store reductions\n        OffsetT tile_segments = next_tile_idx.a_idx - block_idx.a_idx;\n        StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_output + block_idx.a_idx, segment_reductions, tile_segments);\n    }\n\n\n    /**\n     * Multi-segment tile reduction.\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__ void MultiSegmentTile(\n        IndexPair block_idx,\n        IndexPair thread_idx,\n        IndexPair next_thread_idx,\n        IndexPair next_tile_idx)\n    {\n        IndexPair local_thread_idx;\n        local_thread_idx.a_idx = thread_idx.a_idx - block_idx.a_idx;\n        local_thread_idx.b_idx = thread_idx.b_idx - block_idx.b_idx;\n\n        // Check if first segment end-offset is in range\n        bool valid_segment = FULL_TILE || (thread_idx.a_idx < next_thread_idx.a_idx);\n\n        // Check if first value offset is in range\n        bool valid_value = FULL_TILE || (thread_idx.b_idx < next_thread_idx.b_idx);\n\n        // Load first segment end-offset\n        OffsetT segment_end_offset = (valid_segment) ?\n            (USE_SMEM_SEGMENT_CACHE)?\n                temp_storage.cached_segment_end_offsets[local_thread_idx.a_idx] :\n                d_segment_end_offsets[thread_idx.a_idx] :\n            -1;\n\n        OffsetT segment_ids[ITEMS_PER_THREAD];\n        OffsetT value_offsets[ITEMS_PER_THREAD];\n\n        KeyValuePair first_partial;\n        first_partial.key    = thread_idx.a_idx;\n        first_partial.value  = identity;\n\n        // Get segment IDs and gather-offsets for values\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            segment_ids[ITEM]   = -1;\n            value_offsets[ITEM] = -1;\n\n            // Whether or not we slide (a) right along the segment path or (b) down the value path\n            if (valid_segment && (!valid_value || (segment_end_offset <= thread_idx.b_idx)))\n            {\n                // Consume this segment index\n                segment_ids[ITEM] = thread_idx.a_idx;\n                thread_idx.a_idx++;\n                local_thread_idx.a_idx++;\n\n                valid_segment = FULL_TILE || (thread_idx.a_idx < next_thread_idx.a_idx);\n\n                // Read next segment end-offset (if valid)\n                if (valid_segment)\n                {\n                    if (USE_SMEM_SEGMENT_CACHE)\n                        segment_end_offset = temp_storage.cached_segment_end_offsets[local_thread_idx.a_idx];\n                    else\n                        segment_end_offset = d_segment_end_offsets[thread_idx.a_idx];\n                }\n            }\n            else if (valid_value)\n            {\n                // Consume this value index\n                value_offsets[ITEM] = thread_idx.b_idx;\n                thread_idx.b_idx++;\n                local_thread_idx.b_idx++;\n\n                valid_value = FULL_TILE || (thread_idx.b_idx < next_thread_idx.b_idx);\n            }\n        }\n\n        // Load values\n        Value values[ITEMS_PER_THREAD];\n\n        if (USE_SMEM_VALUE_CACHE)\n        {\n            // Barrier for smem reuse\n            __syncthreads();\n\n            OffsetT tile_values = next_tile_idx.b_idx - block_idx.b_idx;\n\n            // Load a tile's worth of values (using identity for out-of-bounds items)\n            LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_values + block_idx.b_idx, values, tile_values, identity);\n\n            // Store to shared\n            StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, temp_storage.cached_values, values, tile_values);\n\n            // Barrier for smem reuse\n            __syncthreads();\n\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            {\n                values[ITEM] = (value_offsets[ITEM] == -1) ?\n                    identity :\n                    temp_storage.cached_values[value_offsets[ITEM] - block_idx.b_idx];\n            }\n        }\n        else\n        {\n            #pragma unroll\n            for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n            {\n                values[ITEM] = (value_offsets[ITEM] == -1) ?\n                    identity :\n                    d_values[value_offsets[ITEM]];\n            }\n        }\n\n        // Reduce within thread segments\n        KeyValuePair running_total = first_partial;\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            if (segment_ids[ITEM] != -1)\n            {\n                // Consume this segment index\n                d_output[segment_ids[ITEM]] = running_total.value;\n\n//                _CubLog(\"Updating segment %d with value %lld\\n\", segment_ids[ITEM], running_total.value)\n\n                if (first_partial.key == segment_ids[ITEM])\n                    first_partial.value = running_total.value;\n\n                running_total.key    = segment_ids[ITEM];\n                running_total.value  = identity;\n            }\n\n            running_total.value = reduction_op(running_total.value, values[ITEM]);\n        }\n/*\n\n        // Barrier for smem reuse\n        __syncthreads();\n\n        // Use prefix scan to reduce values by segment-id.  The segment-reductions end up in items flagged as segment-tails.\n        KeyValuePair block_aggregate;\n        BlockScan(temp_storage.scan).InclusiveScan(\n            pairs,                          // Scan input\n            pairs,                          // Scan output\n            scan_op,                        // Scan operator\n            block_aggregate,                // Block-wide total (unused)\n            prefix_op);                     // Prefix operator for seeding the block-wide scan with the running total\n*/\n\n/*\n        // Check if first segment end-offset is in range\n        bool valid_segment = (thread_idx.a_idx < next_thread_idx.a_idx);\n\n        // Check if first value offset is in range\n        bool valid_value = (thread_idx.b_idx < next_thread_idx.b_idx);\n\n        // Load first segment end-offset\n        OffsetT segment_end_offset = (valid_segment) ?\n            d_segment_end_offsets[thread_idx.a_idx] :\n            num_values;                                                     // Out of range (the last segment end-offset is one-past the last value offset)\n\n        // Load first value offset\n        OffsetT value_offset = (valid_value) ?\n            d_value_offsets[thread_idx.b_idx] :\n            num_values;                                                     // Out of range (one-past the last value offset)\n\n        // Assemble segment-demarcating tail flags and partial reduction tuples\n        TailFlag        tail_flags[ITEMS_PER_THREAD];\n        KeyValuePair    partial_reductions[ITEMS_PER_THREAD];\n\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            // Default tuple and flag values\n            partial_reductions[ITEM].key    = thread_idx.a_idx;\n            partial_reductions[ITEM].value  = identity;\n            tail_flags[ITEM]                = 0;\n\n            // Whether or not we slide (a) right along the segment path or (b) down the value path\n            if (valid_segment && (!valid_value || (segment_end_offset <= value_offset)))\n            {\n                // Consume this segment index\n\n                // Set tail flag noting the end of the segment\n                tail_flags[ITEM] = 1;\n\n                // Increment segment index\n                thread_idx.a_idx++;\n\n                // Read next segment end-offset (if valid)\n                if ((valid_segment = (thread_idx.a_idx < next_thread_idx.a_idx)))\n                    segment_end_offset = d_segment_end_offsets[thread_idx.a_idx];\n            }\n            else if (valid_value)\n            {\n                // Consume this value index\n\n                // Update the tuple's value with the value at this index.\n                partial_reductions[ITEM].value = d_values[value_offset];\n\n                // Increment value index\n                thread_idx.b_idx++;\n\n                // Read next value offset (if valid)\n                if ((valid_value = (thread_idx.b_idx < next_thread_idx.b_idx)))\n                    value_offset = d_value_offsets[thread_idx.b_idx];\n            }\n        }\n\n        // Use prefix scan to reduce values by segment-id.  The segment-reductions end up in items flagged as segment-tails.\n        KeyValuePair block_aggregate;\n        BlockScan(temp_storage.scan).InclusiveScan(\n            partial_reductions,             // Scan input\n            partial_reductions,             // Scan output\n            scan_op,                        // Scan operator\n            block_aggregate,                // Block-wide total (unused)\n            prefix_op);                     // Prefix operator for seeding the block-wide scan with the running total\n\n        // The first segment index for this region (hoist?)\n        OffsetT first_segment_idx = temp_storage.block_idx.a_idx[0];\n\n        // Scatter an accumulated reduction if it is the head of a valid segment\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if (tail_flags[ITEM])\n            {\n                OffsetT segment_idx = partial_reductions[ITEM].key;\n                Value   value       = partial_reductions[ITEM].value;\n\n                // Write value reduction to corresponding segment id\n                d_output[segment_idx] = value;\n\n                // Save off the first value product that this thread block will scatter\n                if (segment_idx == first_segment_idx)\n                {\n                    temp_storage.first_tuple.value = value;\n                }\n            }\n        }\n*/\n    }\n\n\n\n    /**\n     * Have the thread block process the specified region of the MergePath decision path\n     */\n    __device__ __forceinline__ void ProcessRegion(\n        OffsetT         block_diagonal,\n        OffsetT         next_block_diagonal,\n        KeyValuePair    &first_tuple,       // [Out] Valid in thread-0\n        KeyValuePair    &last_tuple)        // [Out] Valid in thread-0\n    {\n        // Thread block initialization\n        if (threadIdx.x < 2)\n        {\n            // Retrieve block starting and ending indices\n            IndexPair block_idx = {0, 0};\n            if (gridDim.x > 1)\n            {\n                block_idx = d_block_idx[blockIdx.x + threadIdx.x];\n            }\n            else if (threadIdx.x > 0)\n            {\n                block_idx.a_idx = num_segments;\n                block_idx.b_idx = num_values;\n            }\n\n            // Share block starting and ending indices\n            temp_storage.block_region_idx[threadIdx.x] = block_idx;\n\n            // Initialize the block's running prefix\n            if (threadIdx.x == 0)\n            {\n                prefix_op.running_total.key    = block_idx.a_idx;\n                prefix_op.running_total.value  = identity;\n\n                // Initialize the \"first scattered partial reduction tuple\" to the prefix tuple (in case we don't actually scatter one)\n                temp_storage.first_tuple = prefix_op.running_total;\n            }\n        }\n\n        // Ensure coherence of region indices\n        __syncthreads();\n\n        // Read block's starting indices\n        IndexPair block_idx = temp_storage.block_region_idx[0];\n\n        // Have the thread block iterate over the region\n        #pragma unroll 1\n        while (block_diagonal < next_block_diagonal)\n        {\n            // Read block's ending indices (hoist?)\n            IndexPair next_block_idx = temp_storage.block_region_idx[1];\n\n            // Clamp the per-thread search range to within one work-tile of block's current indices\n            IndexPair next_tile_idx;\n            next_tile_idx.a_idx = CUB_MIN(next_block_idx.a_idx, block_idx.a_idx + TILE_ITEMS);\n            next_tile_idx.b_idx = CUB_MIN(next_block_idx.b_idx, block_idx.b_idx + TILE_ITEMS);\n\n            // Have each thread search for the end-indices of its subranges within the segment and value inputs\n            IndexPair next_thread_idx;\n            if (USE_SMEM_SEGMENT_CACHE)\n            {\n                // Search in smem cache\n                OffsetT num_segments = next_tile_idx.a_idx - block_idx.a_idx;\n\n                // Load global\n                SegmentOffset segment_offsets[ITEMS_PER_THREAD];\n                LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_segment_end_offsets + block_idx.a_idx, segment_offsets, num_segments, num_values);\n\n                // Store to shared\n                StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, temp_storage.cached_segment_end_offsets, segment_offsets);\n\n                __syncthreads();\n\n                OffsetT next_thread_diagonal = block_diagonal + ((threadIdx.x + 1) * ITEMS_PER_THREAD);\n\n                MergePathSearch(\n                    next_thread_diagonal,                       // Next thread diagonal\n                    temp_storage.cached_segment_end_offsets - block_idx.a_idx,                      // A (segment end-offsets)\n                    d_value_offsets,                            // B (value offsets)\n                    block_idx,                                  // Start indices into A and B\n                    next_tile_idx,                              // End indices into A and B\n                    next_thread_idx);                           // [out] diagonal intersection indices into A and B\n            }\n            else\n            {\n                // Search in global\n\n                OffsetT next_thread_diagonal = block_diagonal + ((threadIdx.x + 1) * ITEMS_PER_THREAD);\n\n                MergePathSearch(\n                    next_thread_diagonal,                       // Next thread diagonal\n                    d_segment_end_offsets,                      // A (segment end-offsets)\n                    d_value_offsets,                            // B (value offsets)\n                    block_idx,                                  // Start indices into A and B\n                    next_tile_idx,                              // End indices into A and B\n                    next_thread_idx);                           // [out] diagonal intersection indices into A and B\n            }\n\n            // Share thread end-indices to get thread begin-indices and tile end-indices\n            IndexPair thread_idx;\n\n            BlockShift(temp_storage.shift).Up(\n                next_thread_idx,    // Input item\n                thread_idx,         // [out] Output item\n                block_idx,          // Prefix item to be provided to <em>thread</em><sub>0</sub>\n                next_tile_idx);     // [out] Suffix item shifted out by the <em>thread</em><sub><tt>BLOCK_THREADS-1</tt></sub> to be provided to all threads\n\n//            if (block_idx.a_idx == next_tile_idx.a_idx)\n//            {\n//                // There are no segment end-offsets in this tile.  Perform a\n//                // simple block-wide reduction and accumulate the result into\n//                // the running total.\n//                SingleSegmentTile(next_tile_idx, block_idx);\n//            }\n//          else if (block_idx.b_idx == next_tile_idx.b_idx)\n//            {\n//                // There are no values in this tile (only empty segments).\n//                EmptySegmentsTile(next_tile_idx.a_idx, block_idx.a_idx);\n//            }\n//            else\n            if ((next_tile_idx.a_idx < num_segments) && (next_tile_idx.b_idx < num_values))\n            {\n                // Merge the tile's segment and value indices (full tile)\n                MultiSegmentTile<true>(block_idx, thread_idx, next_thread_idx, next_tile_idx);\n            }\n            else\n            {\n                // Merge the tile's segment and value indices (partially full tile)\n                MultiSegmentTile<false>(block_idx, thread_idx, next_thread_idx, next_tile_idx);\n            }\n\n            // Advance the block's indices in preparation for the next tile\n            block_idx = next_tile_idx;\n\n            // Advance to the next region in the decision path\n            block_diagonal += TILE_ITEMS;\n\n            // Barrier for smem reuse\n            __syncthreads();\n        }\n\n        // Get first and last tuples for the region\n        if (threadIdx.x == 0)\n        {\n            first_tuple = temp_storage.first_tuple;\n            last_tuple = prefix_op.running_total;\n        }\n\n    }\n\n\n};\n\n\n\n\n\n\n\n\n/******************************************************************************\n * Tuning policy types\n ******************************************************************************/\n\n/**\n * Parameterizable tuning policy type for BlockSegReduceRegionByKey\n */\ntemplate <\n    int                     _BLOCK_THREADS,             ///< Threads per thread block\n    int                     _ITEMS_PER_THREAD,          ///< Items per thread (per tile of input)\n    BlockLoadAlgorithm      _LOAD_ALGORITHM,            ///< The BlockLoad algorithm to use\n    bool                    _LOAD_WARP_TIME_SLICING,    ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage)\n    CacheLoadModifier       _LOAD_MODIFIER,             ///< Cache load modifier for reading input elements\n    BlockScanAlgorithm      _SCAN_ALGORITHM>            ///< The BlockScan algorithm to use\nstruct BlockSegReduceRegionByKeyPolicy\n{\n    enum\n    {\n        BLOCK_THREADS           = _BLOCK_THREADS,               ///< Threads per thread block\n        ITEMS_PER_THREAD        = _ITEMS_PER_THREAD,            ///< Items per thread (per tile of input)\n        LOAD_WARP_TIME_SLICING  = _LOAD_WARP_TIME_SLICING,      ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage)    };\n    };\n\n    static const BlockLoadAlgorithm     LOAD_ALGORITHM          = _LOAD_ALGORITHM;      ///< The BlockLoad algorithm to use\n    static const CacheLoadModifier      LOAD_MODIFIER           = _LOAD_MODIFIER;       ///< Cache load modifier for reading input elements\n    static const BlockScanAlgorithm     SCAN_ALGORITHM          = _SCAN_ALGORITHM;      ///< The BlockScan algorithm to use\n};\n\n\n/******************************************************************************\n * Persistent thread block types\n ******************************************************************************/\n\n/**\n * \\brief BlockSegReduceRegionByKey implements a stateful abstraction of CUDA thread blocks for participating in device-wide reduce-value-by-key.\n */\ntemplate <\n    typename    BlockSegReduceRegionByKeyPolicy,        ///< Parameterized BlockSegReduceRegionByKeyPolicy tuning policy\n    typename    InputIteratorT,                         ///< Random-access iterator referencing key-value input tuples\n    typename    OutputIteratorT,                        ///< Random-access iterator referencing segment output totals\n    typename    ReductionOp>                            ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\nstruct BlockSegReduceRegionByKey\n{\n    //---------------------------------------------------------------------\n    // Types and constants\n    //---------------------------------------------------------------------\n\n    // Constants\n    enum\n    {\n        BLOCK_THREADS       = BlockSegReduceRegionByKeyPolicy::BLOCK_THREADS,\n        ITEMS_PER_THREAD    = BlockSegReduceRegionByKeyPolicy::ITEMS_PER_THREAD,\n        TILE_ITEMS          = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n    // KeyValuePair input type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type KeyValuePair;\n\n    // Signed integer type for global offsets\n    typedef typename KeyValuePair::Key OffsetT;\n\n    // Value type\n    typedef typename KeyValuePair::Value Value;\n\n    // Head flag type\n    typedef int HeadFlag;\n\n    // Input iterator wrapper type for loading KeyValuePair elements through cache\n    typedef CacheModifiedInputIterator<\n            BlockSegReduceRegionByKeyPolicy::LOAD_MODIFIER,\n            KeyValuePair,\n            OffsetT>\n        WrappedInputIteratorT;\n\n    // Parameterized BlockLoad type\n    typedef BlockLoad<\n            WrappedInputIteratorT,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            BlockSegReduceRegionByKeyPolicy::LOAD_ALGORITHM,\n            BlockSegReduceRegionByKeyPolicy::LOAD_WARP_TIME_SLICING>\n        BlockLoad;\n\n    // BlockScan scan operator for reduction-by-segment\n    typedef ReduceByKeyOp<ReductionOp> ReduceByKeyOp;\n\n    // Stateful BlockScan prefix callback type for managing a running total while scanning consecutive tiles\n    typedef RunningBlockPrefixCallbackOp<\n            KeyValuePair,\n            ReduceByKeyOp>\n        RunningPrefixCallbackOp;\n\n    // Parameterized BlockScan type for block-wide reduce-value-by-key\n    typedef BlockScan<\n            KeyValuePair,\n            BLOCK_THREADS,\n            BlockSegReduceRegionByKeyPolicy::SCAN_ALGORITHM>\n        BlockScan;\n\n    // Parameterized BlockDiscontinuity type for identifying key discontinuities\n    typedef BlockDiscontinuity<\n            OffsetT,\n            BLOCK_THREADS>\n        BlockDiscontinuity;\n\n    // Operator for detecting discontinuities in a list of segment identifiers.\n    struct NewSegmentOp\n    {\n        /// Returns true if row_b is the start of a new row\n        __device__ __forceinline__ bool operator()(const OffsetT& b, const OffsetT& a)\n        {\n            return (a != b);\n        }\n    };\n\n    // Shared memory type for this thread block\n    struct _TempStorage\n    {\n        union\n        {\n            typename BlockLoad::TempStorage                 load;           // Smem needed for tile loading\n            struct {\n                typename BlockScan::TempStorage             scan;           // Smem needed for reduce-value-by-segment scan\n                typename BlockDiscontinuity::TempStorage    discontinuity;  // Smem needed for head-flagging\n            };\n        };\n    };\n\n    // Alias wrapper allowing storage to be unioned\n    struct TempStorage : Uninitialized<_TempStorage> {};\n\n\n    //---------------------------------------------------------------------\n    // Thread fields\n    //---------------------------------------------------------------------\n\n    _TempStorage                &temp_storage;          ///< Reference to shared storage\n    WrappedInputIteratorT       d_tuple_partials;       ///< A sequence of partial reduction tuples to scan\n    OutputIteratorT              d_output;               ///< A sequence of segment totals\n    Value                       identity;               ///< Identity value (for zero-length segments)\n    ReduceByKeyOp               scan_op;                ///< Reduce-by-key scan operator\n    RunningPrefixCallbackOp     prefix_op;              ///< Stateful running total for block-wide prefix scan of partial reduction tuples\n\n\n    //---------------------------------------------------------------------\n    // Operations\n    //---------------------------------------------------------------------\n\n    /**\n     * Constructor\n     */\n    __device__ __forceinline__\n    BlockSegReduceRegionByKey(\n        TempStorage             &temp_storage,          ///< Reference to shared storage\n        InputIteratorT          d_tuple_partials,       ///< A sequence of partial reduction tuples to scan\n        OutputIteratorT          d_output,               ///< A sequence of segment totals\n        Value                   identity,               ///< Identity value (for zero-length segments)\n        ReductionOp             reduction_op)           ///< Reduction operator\n    :\n        temp_storage(temp_storage.Alias()),\n        d_tuple_partials(d_tuple_partials),\n        d_output(d_output),\n        identity(identity),\n        scan_op(reduction_op),\n        prefix_op(scan_op)\n    {}\n\n\n\n    /**\n     * Processes a reduce-value-by-key input tile, outputting reductions for each segment\n     */\n    template <bool FULL_TILE>\n    __device__ __forceinline__\n    void ProcessTile(\n        OffsetT block_offset,\n        OffsetT first_segment_idx,\n        OffsetT last_segment_idx,\n        int guarded_items = TILE_ITEMS)\n    {\n        KeyValuePair    partial_reductions[ITEMS_PER_THREAD];\n        OffsetT         segment_ids[ITEMS_PER_THREAD];\n        HeadFlag        head_flags[ITEMS_PER_THREAD];\n\n        // Load a tile of block partials from previous kernel\n        if (FULL_TILE)\n        {\n            // Full tile\n            BlockLoad(temp_storage.load).Load(d_tuple_partials + block_offset, partial_reductions);\n        }\n        else\n        {\n            KeyValuePair oob_default;\n            oob_default.key    = last_segment_idx;       // The last segment ID to be reduced\n            oob_default.value  = identity;\n\n            // Partially-full tile\n            BlockLoad(temp_storage.load).Load(d_tuple_partials + block_offset, partial_reductions, guarded_items, oob_default);\n        }\n\n        // Barrier for shared memory reuse\n        __syncthreads();\n\n        // Copy the segment IDs for head-flagging\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            segment_ids[ITEM] = partial_reductions[ITEM].key;\n        }\n\n        // FlagT segment heads by looking for discontinuities\n        BlockDiscontinuity(temp_storage.discontinuity).FlagHeads(\n            head_flags,                         // [out] Head flags\n            segment_ids,                        // Segment ids\n            NewSegmentOp(),                     // Functor for detecting start of new rows\n            prefix_op.running_total.key);       // Last segment ID from previous tile to compare with first segment ID in this tile\n\n        // Reduce-value-by-segment across partial_reductions using exclusive prefix scan\n        KeyValuePair block_aggregate;\n        BlockScan(temp_storage.scan).ExclusiveScan(\n            partial_reductions,                   // Scan input\n            partial_reductions,                   // Scan output\n            scan_op,                        // Scan operator\n            block_aggregate,                // Block-wide total (unused)\n            prefix_op);                     // Prefix operator for seeding the block-wide scan with the running total\n\n        // Scatter an accumulated reduction if it is the head of a valid segment\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ITEM++)\n        {\n            if (head_flags[ITEM])\n            {\n                d_output[partial_reductions[ITEM].key] = partial_reductions[ITEM].value;\n            }\n        }\n    }\n\n\n    /**\n     * Iterate over input tiles belonging to this thread block\n     */\n    __device__ __forceinline__\n    void ProcessRegion(\n        OffsetT block_offset,\n        OffsetT block_end,\n        OffsetT first_segment_idx,\n        OffsetT last_segment_idx)\n    {\n        if (threadIdx.x == 0)\n        {\n            // Initialize running prefix to the first segment index paired with identity\n            prefix_op.running_total.key    = first_segment_idx;\n            prefix_op.running_total.value  = identity;\n        }\n\n        // Process full tiles\n        while (block_offset + TILE_ITEMS <= block_end)\n        {\n            ProcessTile<true>(block_offset, first_segment_idx, last_segment_idx);\n            __syncthreads();\n\n            block_offset += TILE_ITEMS;\n        }\n\n        // Process final value tile (if present)\n        int guarded_items = block_end - block_offset;\n        if (guarded_items)\n        {\n            ProcessTile<false>(block_offset, first_segment_idx, last_segment_idx, guarded_items);\n        }\n    }\n};\n\n\n\n/******************************************************************************\n * Kernel entrypoints\n ******************************************************************************/\n\n/**\n * Segmented reduce region kernel entry point (multi-block).\n */\n\ntemplate <\n    typename SegmentOffsetIterator,             ///< Random-access input iterator type for reading segment end-offsets\n    typename OffsetT>                           ///< Signed integer type for global offsets\n__global__ void SegReducePartitionKernel(\n    SegmentOffsetIterator       d_segment_end_offsets,  ///< [in] A sequence of \\p num_segments segment end-offsets\n    IndexPair<OffsetT>          *d_block_idx,\n    int                         num_partition_samples,\n    OffsetT                     num_values,             ///< [in] Number of values to reduce\n    OffsetT                     num_segments,           ///< [in] Number of segments being reduced\n    GridEvenShare<OffsetT>      even_share)             ///< [in] Even-share descriptor for mapping an equal number of tiles onto each thread block\n{\n    // Segment offset type\n    typedef typename std::iterator_traits<SegmentOffsetIterator>::value_type SegmentOffset;\n\n    // Counting iterator type\n    typedef CountingInputIterator<SegmentOffsetT, OffsetT> CountingIterator;\n\n    // Cache-modified iterator for segment end-offsets\n    CacheModifiedInputIterator<LOAD_LDG, SegmentOffsetT, OffsetT> d_wrapped_segment_end_offsets(d_segment_end_offsets);\n\n    // Counting iterator for value offsets\n    CountingIterator d_value_offsets(0);\n\n    // Initialize even-share to tell us where to start and stop our tile-processing\n    int partition_id = (blockDim.x * blockIdx.x) + threadIdx.x;\n    even_share.Init(partition_id);\n\n    // Search for block starting and ending indices\n    IndexPair<OffsetT> start_idx = {0, 0};\n    IndexPair<OffsetT> end_idx   = {num_segments, num_values};\n    IndexPair<OffsetT> block_idx;\n\n    MergePathSearch(\n        even_share.block_offset,            // Next thread diagonal\n        d_wrapped_segment_end_offsets,      // A (segment end-offsets)\n        d_value_offsets,                    // B (value offsets)\n        start_idx,                          // Start indices into A and B\n        end_idx,                            // End indices into A and B\n        block_idx);                         // [out] diagonal intersection indices into A and B\n\n    // Write output\n    if (partition_id < num_partition_samples)\n    {\n        d_block_idx[partition_id] = block_idx;\n    }\n}\n\n\n/**\n * Segmented reduce region kernel entry point (multi-block).\n */\ntemplate <\n    typename BlockSegReduceRegionPolicy,        ///< Parameterized BlockSegReduceRegionPolicy tuning policy\n    typename SegmentOffsetIterator,             ///< Random-access input iterator type for reading segment end-offsets\n    typename ValueIterator,                     ///< Random-access input iterator type for reading values\n    typename OutputIteratorT,                   ///< Random-access output iterator type for writing segment reductions\n    typename ReductionOp,                       ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename OffsetT,                           ///< Signed integer type for global offsets\n    typename Value>                             ///< Value type\n__launch_bounds__ (BlockSegReduceRegionPolicy::BLOCK_THREADS)\n__global__ void SegReduceRegionKernel(\n    SegmentOffsetIterator       d_segment_end_offsets,  ///< [in] A sequence of \\p num_segments segment end-offsets\n    ValueIterator               d_values,               ///< [in] A sequence of \\p num_values values\n    OutputIteratorT              d_output,               ///< [out] A sequence of \\p num_segments segment totals\n    KeyValuePair<OffsetT, Value> *d_tuple_partials,      ///< [out] A sequence of (gridDim.x * 2) partial reduction tuples\n    IndexPair<OffsetT>          *d_block_idx,\n    OffsetT                     num_values,             ///< [in] Number of values to reduce\n    OffsetT                     num_segments,           ///< [in] Number of segments being reduced\n    Value                       identity,               ///< [in] Identity value (for zero-length segments)\n    ReductionOp                 reduction_op,           ///< [in] Reduction operator\n    GridEvenShare<OffsetT>      even_share)             ///< [in] Even-share descriptor for mapping an equal number of tiles onto each thread block\n{\n    typedef KeyValuePair<OffsetT, Value> KeyValuePair;\n\n    // Specialize thread block abstraction type for reducing a range of segmented values\n    typedef BlockSegReduceRegion<\n            BlockSegReduceRegionPolicy,\n            SegmentOffsetIterator,\n            ValueIterator,\n            OutputIteratorT,\n            ReductionOp,\n            OffsetT>\n        BlockSegReduceRegion;\n\n    // Shared memory allocation\n    __shared__ typename BlockSegReduceRegion::TempStorage temp_storage;\n\n    // Initialize thread block even-share to tell us where to start and stop our tile-processing\n    even_share.BlockInit();\n\n    // Construct persistent thread block\n    BlockSegReduceRegion thread_block(\n        temp_storage,\n        d_segment_end_offsets,\n        d_values,\n        d_output,\n        d_block_idx,\n        num_values,\n        num_segments,\n        identity,\n        reduction_op);\n\n    // First and last partial reduction tuples within the range (valid in thread-0)\n    KeyValuePair first_tuple, last_tuple;\n\n    // Consume block's region of work\n    thread_block.ProcessRegion(\n        even_share.block_offset,\n        even_share.block_end,\n        first_tuple,\n        last_tuple);\n\n    if (threadIdx.x == 0)\n    {\n        if (gridDim.x > 1)\n        {\n            // Special case where the first segment written and the carry-out are for the same segment\n            if (first_tuple.key == last_tuple.key)\n            {\n                first_tuple.value = identity;\n            }\n\n            // Write the first and last partial products from this thread block so\n            // that they can be subsequently \"fixed up\" in the next kernel.\n            d_tuple_partials[blockIdx.x * 2]          = first_tuple;\n            d_tuple_partials[(blockIdx.x * 2) + 1]    = last_tuple;\n        }\n    }\n\n}\n\n\n/**\n * Segmented reduce region kernel entry point (single-block).\n */\ntemplate <\n    typename    BlockSegReduceRegionByKeyPolicy,        ///< Parameterized BlockSegReduceRegionByKeyPolicy tuning policy\n    typename    InputIteratorT,                         ///< Random-access iterator referencing key-value input tuples\n    typename    OutputIteratorT,                        ///< Random-access iterator referencing segment output totals\n    typename    ReductionOp,                            ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename    OffsetT,                                ///< Signed integer type for global offsets\n    typename    Value>                                  ///< Value type\n__launch_bounds__ (BlockSegReduceRegionByKeyPolicy::BLOCK_THREADS, 1)\n__global__ void SegReduceRegionByKeyKernel(\n    InputIteratorT          d_tuple_partials,           ///< [in] A sequence of partial reduction tuples\n    OutputIteratorT          d_output,                   ///< [out] A sequence of \\p num_segments segment totals\n    OffsetT                 num_segments,               ///< [in] Number of segments in the \\p d_output sequence\n    int                     num_tuple_partials,         ///< [in] Number of partial reduction tuples being reduced\n    Value                   identity,                   ///< [in] Identity value (for zero-length segments)\n    ReductionOp             reduction_op)               ///< [in] Reduction operator\n{\n    // Specialize thread block abstraction type for reducing a range of values by key\n    typedef BlockSegReduceRegionByKey<\n            BlockSegReduceRegionByKeyPolicy,\n            InputIteratorT,\n            OutputIteratorT,\n            ReductionOp>\n        BlockSegReduceRegionByKey;\n\n    // Shared memory allocation\n    __shared__ typename BlockSegReduceRegionByKey::TempStorage temp_storage;\n\n    // Construct persistent thread block\n    BlockSegReduceRegionByKey thread_block(\n        temp_storage,\n        d_tuple_partials,\n        d_output,\n        identity,\n        reduction_op);\n\n    // Process input tiles\n    thread_block.ProcessRegion(\n        0,                          // Region start\n        num_tuple_partials,         // Region end\n        0,                          // First segment ID\n        num_segments);              // Last segment ID (one-past)\n}\n\n\n\n\n/******************************************************************************\n * Dispatch\n ******************************************************************************/\n\n/**\n * Utility class for dispatching the appropriately-tuned kernels for DeviceReduce\n */\ntemplate <\n    typename ValueIterator,                     ///< Random-access input iterator type for reading values\n    typename SegmentOffsetIterator,             ///< Random-access input iterator type for reading segment end-offsets\n    typename OutputIteratorT,                   ///< Random-access output iterator type for writing segment reductions\n    typename ReductionOp,                       ///< Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n    typename OffsetT>                           ///< Signed integer type for global offsets\nstruct DeviceSegReduceDispatch\n{\n    // Value type\n    typedef typename std::iterator_traits<ValueIterator>::value_type Value;\n\n    // Reduce-by-key data type tuple (segment-ID, value)\n    typedef KeyValuePair<OffsetT, Value> KeyValuePair;\n\n    // Index pair data type\n    typedef IndexPair<OffsetT>IndexPair;\n\n\n    /******************************************************************************\n     * Tuning policies\n     ******************************************************************************/\n\n    /// SM35\n    struct Policy350\n    {\n        // ReduceRegionPolicy\n        typedef BlockSegReduceRegionPolicy<\n                128,                            ///< Threads per thread block\n                6,                              ///< Items per thread (per tile of input)\n                true,                           ///< Whether or not to cache incoming segment offsets in shared memory before reducing each tile\n                false,                          ///< Whether or not to cache incoming values in shared memory before reducing each tile\n                LOAD_DEFAULT,                   ///< Cache load modifier for reading segment offsets\n                LOAD_LDG,                       ///< Cache load modifier for reading values\n                BLOCK_REDUCE_RAKING,            ///< The BlockReduce algorithm to use\n                BLOCK_SCAN_WARP_SCANS>          ///< The BlockScan algorithm to use\n            SegReduceRegionPolicy;\n\n        // ReduceRegionByKeyPolicy\n        typedef BlockSegReduceRegionByKeyPolicy<\n                256,                            ///< Threads per thread block\n                9,                             ///< Items per thread (per tile of input)\n                BLOCK_LOAD_DIRECT,              ///< The BlockLoad algorithm to use\n                false,                          ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage)\n                LOAD_LDG,                       ///< Cache load modifier for reading input elements\n                BLOCK_SCAN_WARP_SCANS>          ///< The BlockScan algorithm to use\n            SegReduceRegionByKeyPolicy;\n    };\n\n\n    /// SM10\n    struct Policy100\n    {\n        // ReduceRegionPolicy\n        typedef BlockSegReduceRegionPolicy<\n                128,                            ///< Threads per thread block\n                3,                              ///< Items per thread (per tile of input)\n                false,                          ///< Whether or not to cache incoming segment offsets in shared memory before reducing each tile\n                false,                          ///< Whether or not to cache incoming values in shared memory before reducing each tile\n                LOAD_DEFAULT,                   ///< Cache load modifier for reading segment offsets\n                LOAD_DEFAULT,                   ///< Cache load modifier for reading values\n                BLOCK_REDUCE_RAKING,            ///< The BlockReduce algorithm to use\n                BLOCK_SCAN_RAKING>              ///< The BlockScan algorithm to use\n            SegReduceRegionPolicy;\n\n        // ReduceRegionByKeyPolicy\n        typedef BlockSegReduceRegionByKeyPolicy<\n                128,                            ///< Threads per thread block\n                3,                              ///< Items per thread (per tile of input)\n                BLOCK_LOAD_WARP_TRANSPOSE,      ///< The BlockLoad algorithm to use\n                false,                          ///< Whether or not only one warp's worth of shared memory should be allocated and time-sliced among block-warps during any load-related data transpositions (versus each warp having its own storage)\n                LOAD_DEFAULT,                   ///< Cache load modifier for reading input elements\n                BLOCK_SCAN_WARP_SCANS>          ///< The BlockScan algorithm to use\n            SegReduceRegionByKeyPolicy;\n    };\n\n\n    /******************************************************************************\n     * Tuning policies of current PTX compiler pass\n     ******************************************************************************/\n\n#if (CUB_PTX_ARCH >= 350)\n    typedef Policy350 PtxPolicy;\n/*\n#elif (CUB_PTX_ARCH >= 300)\n    typedef Policy300 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 200)\n    typedef Policy200 PtxPolicy;\n\n#elif (CUB_PTX_ARCH >= 130)\n    typedef Policy130 PtxPolicy;\n*/\n#else\n    typedef Policy100 PtxPolicy;\n\n#endif\n\n    // \"Opaque\" policies (whose parameterizations aren't reflected in the type signature)\n    struct PtxSegReduceRegionPolicy           : PtxPolicy::SegReduceRegionPolicy {};\n    struct PtxSegReduceRegionByKeyPolicy      : PtxPolicy::SegReduceRegionByKeyPolicy {};\n\n\n    /******************************************************************************\n     * Utilities\n     ******************************************************************************/\n\n    /**\n     * Initialize kernel dispatch configurations with the policies corresponding to the PTX assembly we will use\n     */\n    template <\n        typename SegReduceKernelConfig,\n        typename SegReduceByKeyKernelConfig>\n    __host__ __device__ __forceinline__\n    static void InitConfigs(\n        int                         ptx_version,\n        SegReduceKernelConfig       &seg_reduce_region_config,\n        SegReduceByKeyKernelConfig  &seg_reduce_region_by_key_config)\n    {\n    #if (CUB_PTX_ARCH > 0)\n\n        // We're on the device, so initialize the kernel dispatch configurations with the current PTX policy\n        seg_reduce_region_config.Init<PtxSegReduceRegionPolicy>();\n        seg_reduce_region_by_key_config.Init<PtxSegReduceRegionByKeyPolicy>();\n\n    #else\n\n        // We're on the host, so lookup and initialize the kernel dispatch configurations with the policies that match the device's PTX version\n        if (ptx_version >= 350)\n        {\n            seg_reduce_region_config.template          Init<typename Policy350::SegReduceRegionPolicy>();\n            seg_reduce_region_by_key_config.template   Init<typename Policy350::SegReduceRegionByKeyPolicy>();\n        }\n/*\n        else if (ptx_version >= 300)\n        {\n            seg_reduce_region_config.template          Init<typename Policy300::SegReduceRegionPolicy>();\n            seg_reduce_region_by_key_config.template   Init<typename Policy300::SegReduceRegionByKeyPolicy>();\n        }\n        else if (ptx_version >= 200)\n        {\n            seg_reduce_region_config.template          Init<typename Policy200::SegReduceRegionPolicy>();\n            seg_reduce_region_by_key_config.template   Init<typename Policy200::SegReduceRegionByKeyPolicy>();\n        }\n        else if (ptx_version >= 130)\n        {\n            seg_reduce_region_config.template          Init<typename Policy130::SegReduceRegionPolicy>();\n            seg_reduce_region_by_key_config.template   Init<typename Policy130::SegReduceRegionByKeyPolicy>();\n        }\n*/\n        else\n        {\n            seg_reduce_region_config.template          Init<typename Policy100::SegReduceRegionPolicy>();\n            seg_reduce_region_by_key_config.template   Init<typename Policy100::SegReduceRegionByKeyPolicy>();\n        }\n\n    #endif\n    }\n\n\n    /**\n     * SegReduceRegionKernel kernel dispatch configuration\n     */\n    struct SegReduceKernelConfig\n    {\n        int                     block_threads;\n        int                     items_per_thread;\n        bool                    use_smem_segment_cache;\n        bool                    use_smem_value_cache;\n        CacheLoadModifier       load_modifier_segments;\n        CacheLoadModifier       load_modifier_values;\n        BlockReduceAlgorithm    reduce_algorithm;\n        BlockScanAlgorithm      scan_algorithm;\n\n        template <typename SegReduceRegionPolicy>\n        __host__ __device__ __forceinline__\n        void Init()\n        {\n            block_threads               = SegReduceRegionPolicy::BLOCK_THREADS;\n            items_per_thread            = SegReduceRegionPolicy::ITEMS_PER_THREAD;\n            use_smem_segment_cache      = SegReduceRegionPolicy::USE_SMEM_SEGMENT_CACHE;\n            use_smem_value_cache        = SegReduceRegionPolicy::USE_SMEM_VALUE_CACHE;\n            load_modifier_segments      = SegReduceRegionPolicy::LOAD_MODIFIER_SEGMENTS;\n            load_modifier_values        = SegReduceRegionPolicy::LOAD_MODIFIER_VALUES;\n            reduce_algorithm            = SegReduceRegionPolicy::REDUCE_ALGORITHM;\n            scan_algorithm              = SegReduceRegionPolicy::SCAN_ALGORITHM;\n        }\n    };\n\n    /**\n     * SegReduceRegionByKeyKernel kernel dispatch configuration\n     */\n    struct SegReduceByKeyKernelConfig\n    {\n        int                     block_threads;\n        int                     items_per_thread;\n        BlockLoadAlgorithm      load_algorithm;\n        bool                    load_warp_time_slicing;\n        CacheLoadModifier       load_modifier;\n        BlockScanAlgorithm      scan_algorithm;\n\n        template <typename SegReduceRegionByKeyPolicy>\n        __host__ __device__ __forceinline__\n        void Init()\n        {\n            block_threads               = SegReduceRegionByKeyPolicy::BLOCK_THREADS;\n            items_per_thread            = SegReduceRegionByKeyPolicy::ITEMS_PER_THREAD;\n            load_algorithm              = SegReduceRegionByKeyPolicy::LOAD_ALGORITHM;\n            load_warp_time_slicing      = SegReduceRegionByKeyPolicy::LOAD_WARP_TIME_SLICING;\n            load_modifier               = SegReduceRegionByKeyPolicy::LOAD_MODIFIER;\n            scan_algorithm              = SegReduceRegionByKeyPolicy::SCAN_ALGORITHM;\n        }\n    };\n\n\n    /******************************************************************************\n     * Dispatch entrypoints\n     ******************************************************************************/\n\n    /**\n     * Internal dispatch routine for computing a device-wide segmented reduction.\n     */\n    template <\n        typename                        SegReducePartitionKernelPtr,\n        typename                        SegReduceRegionKernelPtr,               ///< Function type of cub::SegReduceRegionKernel\n        typename                        SegReduceRegionByKeyKernelPtr>          ///< Function type of cub::SegReduceRegionByKeyKernel\n    __host__ __device__ __forceinline__\n    static cudaError_t Dispatch(\n        void*               d_temp_storage,                        ///< [in] %Device allocation of temporary storage.  When NULL, the required allocation size is returned in \\p temp_storage_bytes and no work is done.\n        size_t                          &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation.\n        ValueIterator                   d_values,                               ///< [in] A sequence of \\p num_values data to reduce\n        SegmentOffsetIterator           d_segment_offsets,                      ///< [in] A sequence of (\\p num_segments + 1) segment offsets\n        OutputIteratorT                  d_output,                               ///< [out] A sequence of \\p num_segments segment totals\n        OffsetT                         num_values,                             ///< [in] Total number of values to reduce\n        OffsetT                         num_segments,                           ///< [in] Number of segments being reduced\n        Value                           identity,                               ///< [in] Identity value (for zero-length segments)\n        ReductionOp                     reduction_op,                           ///< [in] Reduction operator\n        cudaStream_t                    stream,                                 ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                            debug_synchronous,                      ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n        int                             sm_version,                             ///< [in] SM version of target device to use when computing SM occupancy\n        SegReducePartitionKernelPtr     seg_reduce_partition_kernel,            ///< [in] Kernel function pointer to parameterization of cub::SegReduceRegionKernel\n        SegReduceRegionKernelPtr        seg_reduce_region_kernel,               ///< [in] Kernel function pointer to parameterization of cub::SegReduceRegionKernel\n        SegReduceRegionByKeyKernelPtr   seg_reduce_region_by_key_kernel,        ///< [in] Kernel function pointer to parameterization of cub::SegReduceRegionByKeyKernel\n        SegReduceKernelConfig           &seg_reduce_region_config,              ///< [in] Dispatch parameters that match the policy that \\p seg_reduce_region_kernel was compiled for\n        SegReduceByKeyKernelConfig      &seg_reduce_region_by_key_config)       ///< [in] Dispatch parameters that match the policy that \\p seg_reduce_region_by_key_kernel was compiled for\n    {\n#ifndef CUB_RUNTIME_ENABLED\n\n        // Kernel launch not supported from this device\n        return CubDebug(cudaErrorNotSupported );\n\n#else\n\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Dispatch two kernels: (1) a multi-block segmented reduction\n            // to reduce regions by block, and (2) a single-block reduce-by-key kernel\n            // to \"fix up\" segments spanning more than one region.\n\n            // Tile size of seg_reduce_region_kernel\n            int tile_size = seg_reduce_region_config.block_threads * seg_reduce_region_config.items_per_thread;\n\n            // Get device ordinal\n            int device_ordinal;\n            if (CubDebug(error = cudaGetDevice(&device_ordinal))) break;\n\n            // Get SM count\n            int sm_count;\n            if (CubDebug(error = cudaDeviceGetAttribute (&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal))) break;\n\n            // Get SM occupancy for histogram_region_kernel\n            int seg_reduce_region_sm_occupancy;\n            if (CubDebug(error = MaxSmOccupancy(\n                seg_reduce_region_sm_occupancy,\n                sm_version,\n                seg_reduce_region_kernel,\n                seg_reduce_region_config.block_threads))) break;\n\n            // Get device occupancy for histogram_region_kernel\n            int seg_reduce_region_occupancy = seg_reduce_region_sm_occupancy * sm_count;\n\n            // Even-share work distribution\n            int num_diagonals = num_values + num_segments;                  // Total number of work items\n            int subscription_factor = seg_reduce_region_sm_occupancy;       // Amount of CTAs to oversubscribe the device beyond actively-resident (heuristic)\n            int max_grid_size = seg_reduce_region_occupancy * subscription_factor;\n            GridEvenShare<OffsetT>even_share(\n                num_diagonals,\n                max_grid_size,\n                tile_size);\n\n            // Get grid size for seg_reduce_region_kernel\n            int seg_reduce_region_grid_size = even_share.grid_size;\n\n            // Number of \"fix-up\" reduce-by-key tuples (2 per thread block)\n            int num_tuple_partials = seg_reduce_region_grid_size * 2;\n            int num_partition_samples = seg_reduce_region_grid_size + 1;\n\n            // Temporary storage allocation requirements\n            void* allocations[2];\n            size_t allocation_sizes[2] =\n            {\n                num_tuple_partials * sizeof(KeyValuePair),  // bytes needed for \"fix-up\" reduce-by-key tuples\n                num_partition_samples * sizeof(IndexPair),  // bytes needed block indices\n            };\n\n            // Alias the temporary allocations from the single storage blob (or set the necessary size of the blob)\n            if (CubDebug(error = AliasTemporaries(d_temp_storage, temp_storage_bytes, allocations, allocation_sizes))) break;\n            if (d_temp_storage == NULL)\n            {\n                // Return if the caller is simply requesting the size of the storage allocation\n                return cudaSuccess;\n            }\n\n            // Alias the allocations\n            KeyValuePair    *d_tuple_partials   = (KeyValuePair*) allocations[0];           // \"fix-up\" tuples\n            IndexPair       *d_block_idx        = (IndexPair *) allocations[1];             // block starting/ending indices\n\n            // Array of segment end-offsets\n            SegmentOffsetIterator d_segment_end_offsets = d_segment_offsets + 1;\n\n            // Grid launch params for seg_reduce_partition_kernel\n            int partition_block_size = 32;\n            int partition_grid_size = (num_partition_samples + partition_block_size - 1) / partition_block_size;\n\n            // Partition work among multiple thread blocks if necessary\n            if (seg_reduce_region_grid_size > 1)\n            {\n                // Log seg_reduce_partition_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking seg_reduce_partition_kernel<<<%d, %d, 0, %lld>>>()\\n\",\n                    partition_grid_size, partition_block_size, (long long) stream);\n\n                // Invoke seg_reduce_partition_kernel\n                seg_reduce_partition_kernel<<<partition_grid_size, partition_block_size, 0, stream>>>(\n                    d_segment_end_offsets,  ///< [in] A sequence of \\p num_segments segment end-offsets\n                    d_block_idx,\n                    num_partition_samples,\n                    num_values,             ///< [in] Number of values to reduce\n                    num_segments,           ///< [in] Number of segments being reduced\n                    even_share);            ///< [in] Even-share descriptor for mapping an equal number of tiles onto each thread block\n\n                // Sync the stream if specified\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n\n            // Log seg_reduce_region_kernel configuration\n            if (debug_synchronous) _CubLog(\"Invoking seg_reduce_region_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread, %d SM occupancy\\n\",\n                seg_reduce_region_grid_size, seg_reduce_region_config.block_threads, (long long) stream, seg_reduce_region_config.items_per_thread, seg_reduce_region_sm_occupancy);\n\n            // Mooch\n            if (CubDebug(error = cudaDeviceSetSharedMemConfig(cudaSharedMemBankSizeEightByte))) break;\n\n            // Invoke seg_reduce_region_kernel\n            seg_reduce_region_kernel<<<seg_reduce_region_grid_size, seg_reduce_region_config.block_threads, 0, stream>>>(\n                d_segment_end_offsets,\n                d_values,\n                d_output,\n                d_tuple_partials,\n                d_block_idx,\n                num_values,\n                num_segments,\n                identity,\n                reduction_op,\n                even_share);\n\n            // Sync the stream if specified\n            if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n/*\n            // Perform \"fix-up\" of region partial reductions if grid size is greater than one thread block\n            if (seg_reduce_region_grid_size > 1)\n            {\n                // Log seg_reduce_region_by_key_kernel configuration\n                if (debug_synchronous) _CubLog(\"Invoking seg_reduce_region_by_key_kernel<<<%d, %d, 0, %lld>>>(), %d items per thread\\n\",\n                    1, seg_reduce_region_by_key_config.block_threads, (long long) stream, seg_reduce_region_by_key_config.items_per_thread);\n\n                // Invoke seg_reduce_region_by_key_kernel\n                seg_reduce_region_by_key_kernel<<<1, seg_reduce_region_by_key_config.block_threads, 0, stream>>>(\n                    d_tuple_partials,\n                    d_output,\n                    num_segments,\n                    num_tuple_partials,\n                    identity,\n                    reduction_op);\n\n                // Sync the stream if specified\n                if (debug_synchronous && (CubDebug(error = SyncStream(stream)))) break;\n            }\n*/\n        }\n\n        while (0);\n\n        return error;\n\n#endif // CUB_RUNTIME_ENABLED\n    }\n\n\n    /**\n     * Internal dispatch routine for computing a device-wide segmented reduction.\n     */\n    __host__ __device__ __forceinline__\n    static cudaError_t Dispatch(\n        void*               d_temp_storage,                        ///< [in] %Device allocation of temporary storage.  When NULL, the required allocation size is returned in \\p temp_storage_bytes and no work is done.\n        size_t                          &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation.\n        ValueIterator                   d_values,                               ///< [in] A sequence of \\p num_values data to reduce\n        SegmentOffsetIterator           d_segment_offsets,                      ///< [in] A sequence of (\\p num_segments + 1) segment offsets\n        OutputIteratorT                  d_output,                               ///< [out] A sequence of \\p num_segments segment totals\n        OffsetT                         num_values,                             ///< [in] Total number of values to reduce\n        OffsetT                         num_segments,                           ///< [in] Number of segments being reduced\n        Value                           identity,                               ///< [in] Identity value (for zero-length segments)\n        ReductionOp                     reduction_op,                           ///< [in] Reduction operator\n        cudaStream_t                    stream,                                 ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                            debug_synchronous)                      ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        cudaError error = cudaSuccess;\n        do\n        {\n            // Get PTX version\n            int ptx_version;\n    #if (CUB_PTX_ARCH == 0)\n            if (CubDebug(error = PtxVersion(ptx_version))) break;\n    #else\n            ptx_version = CUB_PTX_ARCH;\n    #endif\n\n            // Get kernel kernel dispatch configurations\n            SegReduceKernelConfig seg_reduce_region_config;\n            SegReduceByKeyKernelConfig seg_reduce_region_by_key_config;\n\n            InitConfigs(ptx_version, seg_reduce_region_config, seg_reduce_region_by_key_config);\n\n            // Dispatch\n            if (CubDebug(error = Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                d_values,\n                d_segment_offsets,\n                d_output,\n                num_values,\n                num_segments,\n                identity,\n                reduction_op,\n                stream,\n                debug_synchronous,\n                ptx_version,            // Use PTX version instead of SM version because, as a statically known quantity, this improves device-side launch dramatically but at the risk of imprecise occupancy calculation for mismatches\n                SegReducePartitionKernel<SegmentOffsetIterator, OffsetT>,\n                SegReduceRegionKernel<PtxSegReduceRegionPolicy, SegmentOffsetIterator, ValueIterator, OutputIteratorT, ReductionOp, OffsetT, Value>,\n                SegReduceRegionByKeyKernel<PtxSegReduceRegionByKeyPolicy, KeyValuePair*, OutputIteratorT, ReductionOp, OffsetT, Value>,\n                seg_reduce_region_config,\n                seg_reduce_region_by_key_config))) break;\n        }\n        while (0);\n\n        return error;\n\n    }\n};\n\n\n\n\n/******************************************************************************\n * DeviceSegReduce\n *****************************************************************************/\n\n/**\n * \\brief DeviceSegReduce provides operations for computing a device-wide, parallel segmented reduction across a sequence of data items residing within global memory.\n * \\ingroup DeviceModule\n *\n * \\par Overview\n * A <a href=\"http://en.wikipedia.org/wiki/Reduce_(higher-order_function)\"><em>reduction</em></a> (or <em>fold</em>)\n * uses a binary combining operator to compute a single aggregate from a list of input elements.\n *\n * \\par Usage Considerations\n * \\cdp_class{DeviceReduce}\n *\n */\nstruct DeviceSegReduce\n{\n    /**\n     * \\brief Computes a device-wide segmented reduction using the specified binary \\p reduction_op functor.\n     *\n     * \\par\n     * Does not support non-commutative reduction operators.\n     *\n     * \\devicestorage\n     *\n     * \\cdp\n     *\n     * \\iterator\n     *\n     * \\tparam ValueIterator            <b>[inferred]</b> Random-access input iterator type for reading values\n     * \\tparam SegmentOffsetIterator    <b>[inferred]</b> Random-access input iterator type for reading segment end-offsets\n     * \\tparam OutputIteratorT           <b>[inferred]</b> Random-access output iterator type for writing segment reductions\n     * \\tparam Value                    <b>[inferred]</b> Value type\n     * \\tparam ReductionOp              <b>[inferred]</b> Binary reduction operator type having member <tt>T operator()(const T &a, const T &b)</tt>\n     */\n    template <\n        typename                ValueIterator,\n        typename                SegmentOffsetIterator,\n        typename                OutputIteratorT,\n        typename                Value,\n        typename                ReductionOp>\n    __host__ __device__ __forceinline__\n    static cudaError_t Reduce(\n        void*               d_temp_storage,                        ///< [in] %Device allocation of temporary storage.  When NULL, the required allocation size is returned in \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation.\n        ValueIterator           d_values,                               ///< [in] A sequence of \\p num_values data to reduce\n        SegmentOffsetIterator   d_segment_offsets,                      ///< [in] A sequence of (\\p num_segments + 1) segment offsets\n        OutputIteratorT          d_output,                               ///< [out] A sequence of \\p num_segments segment totals\n        int                     num_values,                             ///< [in] Total number of values to reduce\n        int                     num_segments,                           ///< [in] Number of segments being reduced\n        Value                   identity,                               ///< [in] Identity value (for zero-length segments)\n        ReductionOp             reduction_op,                           ///< [in] Reduction operator\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        typedef DeviceSegReduceDispatch<\n                ValueIterator,\n                SegmentOffsetIterator,\n                OutputIteratorT,\n                ReductionOp,\n                OffsetT>\n            DeviceSegReduceDispatch;\n\n        return DeviceSegReduceDispatch::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_values,\n            d_segment_offsets,\n            d_output,\n            num_values,\n            num_segments,\n            identity,\n            reduction_op,\n            stream,\n            debug_synchronous);\n    }\n\n\n    /**\n     * \\brief Computes a device-wide segmented sum using the addition ('+') operator.\n     *\n     * \\par\n     * Does not support non-commutative summation.\n     *\n     * \\devicestorage\n     *\n     * \\cdp\n     *\n     * \\iterator\n     *\n     * \\tparam ValueIterator            <b>[inferred]</b> Random-access input iterator type for reading values\n     * \\tparam SegmentOffsetIterator    <b>[inferred]</b> Random-access input iterator type for reading segment end-offsets\n     * \\tparam OutputIteratorT           <b>[inferred]</b> Random-access output iterator type for writing segment reductions\n     */\n    template <\n        typename                ValueIterator,\n        typename                SegmentOffsetIterator,\n        typename                OutputIteratorT>\n    __host__ __device__ __forceinline__\n    static cudaError_t Sum(\n        void*               d_temp_storage,                        ///< [in] %Device allocation of temporary storage.  When NULL, the required allocation size is returned in \\p temp_storage_bytes and no work is done.\n        size_t                  &temp_storage_bytes,                    ///< [in,out] Reference to size in bytes of \\p d_temp_storage allocation.\n        ValueIterator           d_values,                               ///< [in] A sequence of \\p num_values data to reduce\n        SegmentOffsetIterator   d_segment_offsets,                      ///< [in] A sequence of (\\p num_segments + 1) segment offsets\n        OutputIteratorT          d_output,                               ///< [out] A sequence of \\p num_segments segment totals\n        int                     num_values,                             ///< [in] Total number of values to reduce\n        int                     num_segments,                           ///< [in] Number of segments being reduced\n        cudaStream_t            stream              = 0,                ///< [in] <b>[optional]</b> CUDA stream to launch kernels within.  Default is stream<sub>0</sub>.\n        bool                    debug_synchronous   = false)            ///< [in] <b>[optional]</b> Whether or not to synchronize the stream after every kernel launch to check for errors.  Also causes launch configurations to be printed to the console.  Default is \\p false.\n    {\n        // Signed integer type for global offsets\n        typedef int OffsetT;\n\n        // Value type\n        typedef typename std::iterator_traits<ValueIterator>::value_type Value;\n\n        Value identity = Value();\n        cub::Sum reduction_op;\n\n        typedef DeviceSegReduceDispatch<\n                ValueIterator,\n                SegmentOffsetIterator,\n                OutputIteratorT,\n                cub::Sum,\n                OffsetT>\n            DeviceSegReduceDispatch;\n\n        return DeviceSegReduceDispatch::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_values,\n            d_segment_offsets,\n            d_output,\n            num_values,\n            num_segments,\n            identity,\n            reduction_op,\n            stream,\n            debug_synchronous);\n    }\n};\n\n\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem\n */\ntemplate <typename OffsetT, typename Value>\nvoid Initialize(\n    GenMode         gen_mode,\n    Value           *h_values,\n    vector<OffsetT> &segment_offsets,\n    int             num_values,\n    int             avg_segment_size)\n{\n    // Initialize values\n//    if (g_verbose) printf(\"Values: \");\n    for (int i = 0; i < num_values; ++i)\n    {\n        InitValue(gen_mode, h_values[i], i);\n//        if (g_verbose) std::cout << h_values[i] << \", \";\n    }\n//    if (g_verbose) printf(\"\\n\\n\");\n\n    // Initialize segment lengths\n    const unsigned int  MAX_INTEGER         = -1u;\n    const unsigned int  MAX_SEGMENT_LENGTH  = avg_segment_size * 2;\n    const double        SCALE_FACTOR        = double(MAX_SEGMENT_LENGTH) / double(MAX_INTEGER);\n\n    segment_offsets.push_back(0);\n\n    OffsetT consumed = 0;\n    OffsetT remaining = num_values;\n    while (remaining > 0)\n    {\n        // Randomly sample a 32-bit unsigned int\n        unsigned int segment_length;\n        RandomBits(segment_length);\n\n        // Scale to maximum segment length\n        segment_length = (unsigned int) (double(segment_length) * SCALE_FACTOR);\n        segment_length = CUB_MIN(segment_length, remaining);\n\n        consumed += segment_length;\n        remaining -= segment_length;\n\n        segment_offsets.push_back(consumed);\n    }\n}\n\n\n/**\n * Compute reference answer\n */\ntemplate <typename OffsetT, typename Value>\nvoid ComputeReference(\n    Value       *h_values,\n    OffsetT     *h_segment_offsets,\n    Value       *h_reference,\n    int         num_segments,\n    Value       identity)\n{\n    if (g_verbose) printf(\"%d segment reductions: \", num_segments);\n    for (int segment = 0; segment < num_segments; ++segment)\n    {\n        h_reference[segment] = identity;\n\n        for (int i = h_segment_offsets[segment]; i < h_segment_offsets[segment + 1]; ++i)\n        {\n            h_reference[segment] += h_values[i];\n        }\n        if (g_verbose) std::cout << h_reference[segment] << \", \";\n    }\n    if (g_verbose) printf(\"\\n\\n\");\n}\n\n\n/**\n * Simple test of device\n */\ntemplate <\n    bool            CDP,\n    typename        OffsetT,\n    typename        Value,\n    typename        ReductionOp>\nvoid Test(\n    OffsetT         num_values,\n    int             avg_segment_size,\n    ReductionOp     reduction_op,\n    Value           identity,\n    char*           type_string)\n{\n    Value   *h_values = NULL;\n    Value   *h_reference = NULL;\n    OffsetT *h_segment_offsets = NULL;\n\n    printf(\"%d\\n\", num_values);\n\n    // Initialize problem on host\n    h_values = new Value[num_values];\n    vector<OffsetT> segment_offsets;\n    Initialize(UNIFORM, h_values, segment_offsets, num_values, avg_segment_size);\n\n    // Allocate simple offsets array and copy STL vector into it\n    h_segment_offsets = new OffsetT[segment_offsets.size()];\n    for (int i = 0; i < segment_offsets.size(); ++i)\n        h_segment_offsets[i] = segment_offsets[i];\n\n    OffsetT num_segments = segment_offsets.size() - 1;\n    if (g_verbose)\n    {\n        printf(\"%d segment offsets: \", num_segments);\n        for (int i = 0; i < num_segments; ++i)\n            std::cout << h_segment_offsets[i] << \"(\" << h_segment_offsets[i + 1] - h_segment_offsets[i] << \"), \";\n        if (g_verbose) std::cout << std::endl << std::endl;\n    }\n\n    // Solve problem on host\n    h_reference = new Value[num_segments];\n    ComputeReference(h_values, h_segment_offsets, h_reference, num_segments, identity);\n\n    printf(\"\\n\\n%s cub::DeviceSegReduce::%s %d items (%d-byte %s), %d segments (%d-byte offset indices)\\n\",\n        (CDP) ? \"CDP device invoked\" : \"Host-invoked\",\n        (Equals<ReductionOp, Sum>::VALUE) ? \"Sum\" : \"Reduce\",\n        num_values, (int) sizeof(Value), type_string,\n        num_segments, (int) sizeof(OffsetT));\n    fflush(stdout);\n\n    // Allocate and initialize problem on device\n    Value   *d_values = NULL;\n    OffsetT *d_segment_offsets = NULL;\n    Value   *d_output = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values, sizeof(Value) * num_values));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_segment_offsets, sizeof(OffsetT) * (num_segments + 1)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_output, sizeof(Value) * num_segments));\n    CubDebugExit(cudaMemcpy(d_values, h_values, sizeof(Value) * num_values, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_segment_offsets, h_segment_offsets, sizeof(OffsetT) * (num_segments + 1), cudaMemcpyHostToDevice));\n\n    // Request and allocate temporary storage\n    void    *d_temp_storage = NULL;\n    size_t  temp_storage_bytes = 0;\n    CubDebugExit(DeviceSegReduce::Sum(d_temp_storage, temp_storage_bytes, d_values, d_segment_offsets, d_output, num_values, num_segments, 0, false));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output\n    CubDebugExit(cudaMemset(d_output, 0, sizeof(Value) * num_segments));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(DeviceSegReduce::Sum(d_temp_storage, temp_storage_bytes, d_values, d_segment_offsets, d_output, num_values, num_segments, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_output, num_segments, true, g_verbose);\n    printf(\"\\t%s\", compare ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    for (int i = 0; i < g_timing_iterations; ++i)\n    {\n        CubDebugExit(DeviceSegReduce::Sum(d_temp_storage, temp_storage_bytes, d_values, d_segment_offsets, d_output, num_values, num_segments, 0, false));\n    }\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(num_values) / avg_millis / 1000.0 / 1000.0;\n        float giga_bandwidth = giga_rate *\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s\", avg_millis, giga_rate, giga_bandwidth);\n    }\n\n    // Device cleanup\n    if (d_values) CubDebugExit(g_allocator.DeviceFree(d_values));\n    if (d_segment_offsets) CubDebugExit(g_allocator.DeviceFree(d_segment_offsets));\n    if (d_output) CubDebugExit(g_allocator.DeviceFree(d_output));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Host cleanup\n    if (h_values)           delete[] h_values;\n    if (h_segment_offsets)  delete[] h_segment_offsets;\n    if (h_reference)        delete[] h_reference;\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_values          = 32 * 1024 * 1024;\n    int avg_segment_size    = 500;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_values);\n    args.GetCmdLineArgument(\"ss\", avg_segment_size);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"[--i=<timing iterations>] \"\n            \"[--n=<input samples>]\\n\"\n            \"[--ss=<average segment size>]\\n\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    Test<false>((int) num_values, avg_segment_size, Sum(), (long long) 0, CUB_TYPE_STRING(long long));\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/experimental/histogram/histogram_cub.h",
    "content": "/******************************************************************************\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n#include <cub/device/device_histogram.cuh>\n\nusing namespace cub;\n\ntemplate <\n    int         NUM_CHANNELS,\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\ndouble run_cub_histogram(\n    PixelType *d_image,\n    int width,\n    int height,\n    unsigned int *d_hist, \n    bool is_warmup)\n{\n    enum {\n        is_float = Equals<PixelType, float4>::VALUE,\n    };\n\n    typedef typename If<is_float, float, unsigned char>::Type    SampleT;    // Sample type\n    typedef typename If<is_float, float, unsigned int>::Type     LevelT;     // Level type (uint32 for uchar)\n\n    // Setup data structures\n    unsigned int*       d_histogram[ACTIVE_CHANNELS];\n    int                 num_levels[ACTIVE_CHANNELS];            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              lower_level[ACTIVE_CHANNELS];           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT              upper_level[ACTIVE_CHANNELS];           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n\n    for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n    {\n        d_histogram[CHANNEL] = d_hist + (CHANNEL * NUM_BINS);\n        num_levels[CHANNEL] = NUM_BINS + 1;\n        lower_level[CHANNEL] = 0;\n        upper_level[CHANNEL] = (is_float) ? 1 : 256;\n    }\n\n    // Allocate temporary storage\n    size_t temp_storage_bytes = 0;\n    void *d_temp_storage = NULL;\n\n    SampleT* d_image_samples = (SampleT*) d_image;\n\n    // Get amount of temporary storage needed\n    DeviceHistogram::MultiHistogramEven<NUM_CHANNELS, ACTIVE_CHANNELS>(\n        d_temp_storage,\n        temp_storage_bytes,\n        d_image_samples,\n        d_histogram,\n        num_levels,\n        lower_level,\n        upper_level,\n        width * height, \n        (cudaStream_t) 0,\n        is_warmup);\n\n    cudaMalloc(&d_temp_storage, temp_storage_bytes);\n\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n\n    // Compute histogram\n    DeviceHistogram::MultiHistogramEven<NUM_CHANNELS, ACTIVE_CHANNELS>(\n        d_temp_storage,\n        temp_storage_bytes,\n        d_image_samples,\n        d_histogram,\n        num_levels,\n        lower_level,\n        upper_level,\n        width * height, \n        (cudaStream_t) 0,\n        is_warmup);\n\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    cudaFree(d_temp_storage);\n\n    return elapsed_millis;\n}\n\n"
  },
  {
    "path": "external/cub/experimental/histogram/histogram_gmem_atomics.h",
    "content": "/******************************************************************************\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n#include <test/test_util.h>\n\nnamespace histogram_gmem_atomics\n{\n    // Decode float4 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(float4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        float* samples = reinterpret_cast<float*>(&pixel);\n\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n            bins[CHANNEL] = (unsigned int) (samples[CHANNEL] * float(NUM_BINS));\n    }\n\n    // Decode uchar4 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(uchar4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        unsigned char* samples = reinterpret_cast<unsigned char*>(&pixel);\n\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n            bins[CHANNEL] = (unsigned int) (samples[CHANNEL]);\n    }\n\n    // Decode uchar1 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(uchar1 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        bins[0] = (unsigned int) pixel.x;\n    }\n\n    // First-pass histogram kernel (binning into privatized counters)\n    template <\n        int         NUM_PARTS,\n        int         ACTIVE_CHANNELS,\n        int         NUM_BINS,\n        typename    PixelType>\n    __global__ void histogram_gmem_atomics(\n        const PixelType *in,\n        int width,\n        int height,\n        unsigned int *out)\n    {\n        // global position and size\n        int x = blockIdx.x * blockDim.x + threadIdx.x;\n        int y = blockIdx.y * blockDim.y + threadIdx.y;\n        int nx = blockDim.x * gridDim.x;\n        int ny = blockDim.y * gridDim.y;\n\n        // threads in workgroup\n        int t = threadIdx.x + threadIdx.y * blockDim.x; // thread index in workgroup, linear in 0..nt-1\n        int nt = blockDim.x * blockDim.y; // total threads in workgroup\n\n        // group index in 0..ngroups-1\n        int g = blockIdx.x + blockIdx.y * gridDim.x;\n\n        // initialize smem\n        unsigned int *gmem = out + g * NUM_PARTS;\n        for (int i = t; i < ACTIVE_CHANNELS * NUM_BINS; i += nt)\n            gmem[i] = 0;\n        __syncthreads();\n\n        // process pixels (updates our group's partial histogram in gmem)\n        for (int col = x; col < width; col += nx)\n        {\n            for (int row = y; row < height; row += ny)\n            {\n                PixelType pixel = in[row * width + col];\n\n                unsigned int bins[ACTIVE_CHANNELS];\n                DecodePixel<NUM_BINS>(pixel, bins);\n\n                #pragma unroll\n                for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n                    atomicAdd(&gmem[(NUM_BINS * CHANNEL) + bins[CHANNEL]], 1);\n            }\n        }\n    }\n\n    // Second pass histogram kernel (accumulation)\n    template <\n        int         NUM_PARTS,\n        int         ACTIVE_CHANNELS,\n        int         NUM_BINS>\n    __global__ void histogram_gmem_accum(\n        const unsigned int *in,\n        int n,\n        unsigned int *out)\n    {\n        int i = blockIdx.x * blockDim.x + threadIdx.x;\n        if (i > ACTIVE_CHANNELS * NUM_BINS)\n            return; // out of range\n\n        unsigned int total = 0;\n        for (int j = 0; j < n; j++)\n            total += in[i + NUM_PARTS * j];\n\n        out[i] = total;\n    }\n\n\n}   // namespace histogram_gmem_atomics\n\n\ntemplate <\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\ndouble run_gmem_atomics(\n    PixelType *d_image,\n    int width,\n    int height,\n    unsigned int *d_hist,\n    bool warmup)\n{\n    enum\n    {\n        NUM_PARTS = 1024\n    };\n\n    cudaDeviceProp props;\n    cudaGetDeviceProperties(&props, 0);\n\n    dim3 block(32, 4);\n    dim3 grid(16, 16);\n    int total_blocks = grid.x * grid.y;\n\n    // allocate partial histogram\n    unsigned int *d_part_hist;\n    cudaMalloc(&d_part_hist, total_blocks * NUM_PARTS * sizeof(unsigned int));\n\n    dim3 block2(128);\n    dim3 grid2((3 * NUM_BINS + block.x - 1) / block.x);\n\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n\n    histogram_gmem_atomics::histogram_gmem_atomics<NUM_PARTS, ACTIVE_CHANNELS, NUM_BINS><<<grid, block>>>(\n        d_image,\n        width,\n        height,\n        d_part_hist);\n\n    histogram_gmem_atomics::histogram_gmem_accum<NUM_PARTS, ACTIVE_CHANNELS, NUM_BINS><<<grid2, block2>>>(\n        d_part_hist,\n        total_blocks,\n        d_hist);\n\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    cudaFree(d_part_hist);\n\n    return elapsed_millis;\n}\n\n"
  },
  {
    "path": "external/cub/experimental/histogram/histogram_smem_atomics.h",
    "content": "/******************************************************************************\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n#include <test/test_util.h>\n\nnamespace histogram_smem_atomics\n{\n    // Decode float4 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(float4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        float* samples = reinterpret_cast<float*>(&pixel);\n\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n            bins[CHANNEL] = (unsigned int) (samples[CHANNEL] * float(NUM_BINS));\n    }\n\n    // Decode uchar4 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(uchar4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        unsigned char* samples = reinterpret_cast<unsigned char*>(&pixel);\n\n        #pragma unroll\n        for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n            bins[CHANNEL] = (unsigned int) (samples[CHANNEL]);\n    }\n\n    // Decode uchar1 pixel into bins\n    template <int NUM_BINS, int ACTIVE_CHANNELS>\n    __device__ __forceinline__ void DecodePixel(uchar1 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n    {\n        bins[0] = (unsigned int) pixel.x;\n    }\n\n    // First-pass histogram kernel (binning into privatized counters)\n    template <\n        int         NUM_PARTS,\n        int         ACTIVE_CHANNELS,\n        int         NUM_BINS,\n        typename    PixelType>\n    __global__ void histogram_smem_atomics(\n        const PixelType *in,\n        int width,\n        int height,\n        unsigned int *out)\n    {\n        // global position and size\n        int x = blockIdx.x * blockDim.x + threadIdx.x;\n        int y = blockIdx.y * blockDim.y + threadIdx.y;\n        int nx = blockDim.x * gridDim.x;\n        int ny = blockDim.y * gridDim.y;\n\n        // threads in workgroup\n        int t = threadIdx.x + threadIdx.y * blockDim.x; // thread index in workgroup, linear in 0..nt-1\n        int nt = blockDim.x * blockDim.y; // total threads in workgroup\n\n        // group index in 0..ngroups-1\n        int g = blockIdx.x + blockIdx.y * gridDim.x;\n\n        // initialize smem\n        __shared__ unsigned int smem[ACTIVE_CHANNELS * NUM_BINS + 3];\n        for (int i = t; i < ACTIVE_CHANNELS * NUM_BINS + 3; i += nt)\n            smem[i] = 0;\n        __syncthreads();\n\n        // process pixels\n        // updates our group's partial histogram in smem\n        for (int col = x; col < width; col += nx)\n        {\n            for (int row = y; row < height; row += ny)\n            {\n                PixelType pixel = in[row * width + col];\n\n                unsigned int bins[ACTIVE_CHANNELS];\n                DecodePixel<NUM_BINS>(pixel, bins);\n\n                #pragma unroll\n                for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n                    atomicAdd(&smem[(NUM_BINS * CHANNEL) + bins[CHANNEL] + CHANNEL], 1);\n            }\n        }\n\n        __syncthreads();\n\n        // move to our workgroup's slice of output\n        out += g * NUM_PARTS;\n\n        // store local output to global\n        for (int i = t; i < NUM_BINS; i += nt)\n        {\n            #pragma unroll\n            for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n                out[i + NUM_BINS * CHANNEL] = smem[i + NUM_BINS * CHANNEL + CHANNEL];\n        }\n    }\n\n    // Second pass histogram kernel (accumulation)\n    template <\n        int         NUM_PARTS,\n        int         ACTIVE_CHANNELS,\n        int         NUM_BINS>\n    __global__ void histogram_smem_accum(\n        const unsigned int *in,\n        int n,\n        unsigned int *out)\n    {\n        int i = blockIdx.x * blockDim.x + threadIdx.x;\n        if (i > ACTIVE_CHANNELS * NUM_BINS) return; // out of range\n        unsigned int total = 0;\n        for (int j = 0; j < n; j++)\n            total += in[i + NUM_PARTS * j];\n        out[i] = total;\n    }\n\n}   // namespace histogram_smem_atomics\n\n\ntemplate <\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\ndouble run_smem_atomics(\n    PixelType *d_image,\n    int width,\n    int height,\n    unsigned int *d_hist, \n    bool warmup)\n{\n    enum\n    {\n        NUM_PARTS = 1024\n    };\n\n    cudaDeviceProp props;\n    cudaGetDeviceProperties(&props, 0);\n\n    dim3 block(32, 4);\n    dim3 grid(16, 16);\n    int total_blocks = grid.x * grid.y;\n\n    // allocate partial histogram\n    unsigned int *d_part_hist;\n    cudaMalloc(&d_part_hist, total_blocks * NUM_PARTS * sizeof(unsigned int));\n\n    dim3 block2(128);\n    dim3 grid2((ACTIVE_CHANNELS * NUM_BINS + block.x - 1) / block.x);\n\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n\n    histogram_smem_atomics::histogram_smem_atomics<NUM_PARTS, ACTIVE_CHANNELS, NUM_BINS><<<grid, block>>>(\n        d_image,\n        width,\n        height,\n        d_part_hist);\n\n    histogram_smem_atomics::histogram_smem_accum<NUM_PARTS, ACTIVE_CHANNELS, NUM_BINS><<<grid2, block2>>>(\n        d_part_hist,\n        total_blocks,\n        d_hist);\n\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    cudaFree(d_part_hist);\n\n    return elapsed_millis;\n}\n\n"
  },
  {
    "path": "external/cub/experimental/histogram_compare.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n#include <stdio.h>\n#include <map>\n#include <vector>\n#include <algorithm>\n#include <cstdio>\n#include <fstream>\n\n#include \"histogram/histogram_gmem_atomics.h\"\n#include \"histogram/histogram_smem_atomics.h\"\n#include \"histogram/histogram_cub.h\"\n\n#include <cub/util_allocator.cuh>\n#include <test/test_util.h>\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants, and type declarations\n//---------------------------------------------------------------------\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\nbool                    g_verbose = false;  // Whether to display input/output to console\nbool                    g_report = false;   // Whether to display a full report in CSV format\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\nstruct less_than_value\n{\n    inline bool operator()(\n        const std::pair<std::string, double> &a,\n        const std::pair<std::string, double> &b)\n    {\n        return a.second < b.second;\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Targa (.tga) image file parsing\n//---------------------------------------------------------------------\n\n/**\n * TGA image header info\n */\nstruct TgaHeader\n{\n    char idlength;\n    char colormaptype;\n    char datatypecode;\n    short colormaporigin;\n    short colormaplength;\n    char colormapdepth;\n    short x_origin;\n    short y_origin;\n    short width;\n    short height;\n    char bitsperpixel;\n    char imagedescriptor;\n\n    void Parse (FILE *fptr)\n    {\n        idlength = fgetc(fptr);\n        colormaptype = fgetc(fptr);\n        datatypecode = fgetc(fptr);\n        fread(&colormaporigin, 2, 1, fptr);\n        fread(&colormaplength, 2, 1, fptr);\n        colormapdepth = fgetc(fptr);\n        fread(&x_origin, 2, 1, fptr);\n        fread(&y_origin, 2, 1, fptr);\n        fread(&width, 2, 1, fptr);\n        fread(&height, 2, 1, fptr);\n        bitsperpixel = fgetc(fptr);\n        imagedescriptor = fgetc(fptr);\n    }\n\n    void Display (FILE *fptr)\n    {\n        fprintf(fptr, \"ID length:           %d\\n\", idlength);\n        fprintf(fptr, \"Color map type:      %d\\n\", colormaptype);\n        fprintf(fptr, \"Image type:          %d\\n\", datatypecode);\n        fprintf(fptr, \"Color map offset:    %d\\n\", colormaporigin);\n        fprintf(fptr, \"Color map length:    %d\\n\", colormaplength);\n        fprintf(fptr, \"Color map depth:     %d\\n\", colormapdepth);\n        fprintf(fptr, \"X origin:            %d\\n\", x_origin);\n        fprintf(fptr, \"Y origin:            %d\\n\", y_origin);\n        fprintf(fptr, \"Width:               %d\\n\", width);\n        fprintf(fptr, \"Height:              %d\\n\", height);\n        fprintf(fptr, \"Bits per pixel:      %d\\n\", bitsperpixel);\n        fprintf(fptr, \"Descriptor:          %d\\n\", imagedescriptor);\n    }\n};\n\n\n/**\n * Decode image byte data into pixel\n */\nvoid ParseTgaPixel(uchar4 &pixel, unsigned char *tga_pixel, int bytes)\n{\n    if (bytes == 4)\n    {\n        pixel.x = tga_pixel[2];\n        pixel.y = tga_pixel[1];\n        pixel.z = tga_pixel[0];\n        pixel.w = tga_pixel[3];\n    }\n    else if (bytes == 3)\n    {\n        pixel.x = tga_pixel[2];\n        pixel.y = tga_pixel[1];\n        pixel.z = tga_pixel[0];\n        pixel.w = 0;\n    }\n    else if (bytes == 2)\n    {\n        pixel.x = (tga_pixel[1] & 0x7c) << 1;\n        pixel.y = ((tga_pixel[1] & 0x03) << 6) | ((tga_pixel[0] & 0xe0) >> 2);\n        pixel.z = (tga_pixel[0] & 0x1f) << 3;\n        pixel.w = (tga_pixel[1] & 0x80);\n    }\n}\n\n\n/**\n * Reads a .tga image file\n */\nvoid ReadTga(uchar4* &pixels, int &width, int &height, const char *filename)\n{\n    // Open the file\n    FILE *fptr;\n    if ((fptr = fopen(filename, \"rb\")) == NULL)\n    {\n        fprintf(stderr, \"File open failed\\n\");\n        exit(-1);\n    }\n\n    // Parse header\n    TgaHeader header;\n    header.Parse(fptr);\n//    header.Display(stdout);\n    width = header.width;\n    height = header.height;\n\n    // Verify compatibility\n    if (header.datatypecode != 2 && header.datatypecode != 10)\n    {\n        fprintf(stderr, \"Can only handle image type 2 and 10\\n\");\n        exit(-1);\n    }\n    if (header.bitsperpixel != 16 && header.bitsperpixel != 24 && header.bitsperpixel != 32)\n    {\n        fprintf(stderr, \"Can only handle pixel depths of 16, 24, and 32\\n\");\n        exit(-1);\n    }\n    if (header.colormaptype != 0 && header.colormaptype != 1)\n    {\n        fprintf(stderr, \"Can only handle color map types of 0 and 1\\n\");\n        exit(-1);\n    }\n\n    // Skip unnecessary header info\n    int skip_bytes = header.idlength + (header.colormaptype * header.colormaplength);\n    fseek(fptr, skip_bytes, SEEK_CUR);\n\n    // Read the image\n    int pixel_bytes = header.bitsperpixel / 8;\n\n    // Allocate and initialize pixel data\n    size_t image_bytes = width * height * sizeof(uchar4);\n    if ((pixels == NULL) && ((pixels = (uchar4*) malloc(image_bytes)) == NULL))\n    {\n        fprintf(stderr, \"malloc of image failed\\n\");\n        exit(-1);\n    }\n    memset(pixels, 0, image_bytes);\n\n    // Parse pixels\n    unsigned char   tga_pixel[5];\n    int             current_pixel = 0;\n    while (current_pixel < header.width * header.height)\n    {\n        if (header.datatypecode == 2)\n        {\n            // Uncompressed\n            if (fread(tga_pixel, 1, pixel_bytes, fptr) != pixel_bytes)\n            {\n                fprintf(stderr, \"Unexpected end of file at pixel %d  (uncompressed)\\n\", current_pixel);\n                exit(-1);\n            }\n            ParseTgaPixel(pixels[current_pixel], tga_pixel, pixel_bytes);\n            current_pixel++;\n        }\n        else if (header.datatypecode == 10)\n        {\n            // Compressed\n            if (fread(tga_pixel, 1, pixel_bytes + 1, fptr) != pixel_bytes + 1)\n            {\n                fprintf(stderr, \"Unexpected end of file at pixel %d (compressed)\\n\", current_pixel);\n                exit(-1);\n            }\n            int run_length = tga_pixel[0] & 0x7f;\n            ParseTgaPixel(pixels[current_pixel], &(tga_pixel[1]), pixel_bytes);\n            current_pixel++;\n\n            if (tga_pixel[0] & 0x80)\n            {\n                // RLE chunk\n                for (int i = 0; i < run_length; i++)\n                {\n                    ParseTgaPixel(pixels[current_pixel], &(tga_pixel[1]), pixel_bytes);\n                    current_pixel++;\n                }\n            }\n            else\n            {\n                // Normal chunk\n                for (int i = 0; i < run_length; i++)\n                {\n                    if (fread(tga_pixel, 1, pixel_bytes, fptr) != pixel_bytes)\n                    {\n                        fprintf(stderr, \"Unexpected end of file at pixel %d (normal)\\n\", current_pixel);\n                        exit(-1);\n                    }\n                    ParseTgaPixel(pixels[current_pixel], tga_pixel, pixel_bytes);\n                    current_pixel++;\n                }\n            }\n        }\n    }\n\n    // Close file\n    fclose(fptr);\n}\n\n\n\n//---------------------------------------------------------------------\n// Random image generation\n//---------------------------------------------------------------------\n\n/**\n * Generate a random image with specified entropy\n */\nvoid GenerateRandomImage(uchar4* &pixels, int width, int height, int entropy_reduction)\n{\n    int num_pixels = width * height;\n    size_t image_bytes = num_pixels * sizeof(uchar4);\n    if ((pixels == NULL) && ((pixels = (uchar4*) malloc(image_bytes)) == NULL))\n    {\n        fprintf(stderr, \"malloc of image failed\\n\");\n        exit(-1);\n    }\n\n    for (int i = 0; i < num_pixels; ++i)\n    {\n        RandomBits(pixels[i].x, entropy_reduction);\n        RandomBits(pixels[i].y, entropy_reduction);\n        RandomBits(pixels[i].z, entropy_reduction);\n        RandomBits(pixels[i].w, entropy_reduction);\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Histogram verification\n//---------------------------------------------------------------------\n\n// Decode float4 pixel into bins\ntemplate <int NUM_BINS, int ACTIVE_CHANNELS>\nvoid DecodePixelGold(float4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n{\n    float* samples = reinterpret_cast<float*>(&pixel);\n\n    for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n        bins[CHANNEL] = (unsigned int) (samples[CHANNEL] * float(NUM_BINS));\n}\n\n// Decode uchar4 pixel into bins\ntemplate <int NUM_BINS, int ACTIVE_CHANNELS>\nvoid DecodePixelGold(uchar4 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n{\n    unsigned char* samples = reinterpret_cast<unsigned char*>(&pixel);\n\n    for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n        bins[CHANNEL] = (unsigned int) (samples[CHANNEL]);\n}\n\n// Decode uchar1 pixel into bins\ntemplate <int NUM_BINS, int ACTIVE_CHANNELS>\nvoid DecodePixelGold(uchar1 pixel, unsigned int (&bins)[ACTIVE_CHANNELS])\n{\n    bins[0] = (unsigned int) pixel.x;\n}\n\n\n// Compute reference histogram.  Specialized for uchar4\ntemplate <\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\nvoid HistogramGold(PixelType *image, int width, int height, unsigned int* hist)\n{\n    memset(hist, 0, ACTIVE_CHANNELS * NUM_BINS * sizeof(unsigned int));\n\n    for (int i = 0; i < width; i++)\n    {\n        for (int j = 0; j < height; j++)\n        {\n            PixelType pixel = image[i + j * width];\n\n            unsigned int bins[ACTIVE_CHANNELS];\n            DecodePixelGold<NUM_BINS>(pixel, bins);\n\n            for (int CHANNEL = 0; CHANNEL < ACTIVE_CHANNELS; ++CHANNEL)\n            {\n                hist[(NUM_BINS * CHANNEL) + bins[CHANNEL]]++;\n            }\n        }\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Test execution\n//---------------------------------------------------------------------\n\n/**\n * Run a specific histogram implementation\n */\ntemplate <\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\nvoid RunTest(\n    std::vector<std::pair<std::string, double> >&   timings,\n    PixelType*                                      d_pixels,\n    const int                                       width,\n    const int                                       height,\n    unsigned int *                                  d_hist,\n    unsigned int *                                  h_hist,\n    int                                             timing_iterations,\n    const char *                                    long_name,\n    const char *                                    short_name,\n    double (*f)(PixelType*, int, int, unsigned int*, bool))\n{\n    if (!g_report) printf(\"%s \", long_name); fflush(stdout);\n\n    // Run single test to verify (and code cache)\n    (*f)(d_pixels, width, height, d_hist, !g_report);\n\n    int compare = CompareDeviceResults(h_hist, d_hist, ACTIVE_CHANNELS * NUM_BINS, true, g_verbose);\n    if (!g_report) printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n\n    double elapsed_ms = 0;\n    for (int i = 0; i < timing_iterations; i++)\n    {\n        elapsed_ms += (*f)(d_pixels, width, height, d_hist, false);\n    }\n    double avg_us = (elapsed_ms / timing_iterations) * 1000;    // average in us\n    timings.push_back(std::pair<std::string, double>(short_name, avg_us));\n\n    if (!g_report)\n    {\n        printf(\"Avg time %.3f us (%d iterations)\\n\", avg_us, timing_iterations); fflush(stdout);\n    }\n    else\n    {\n        printf(\"%.3f, \", avg_us); fflush(stdout);\n    }\n\n    AssertEquals(0, compare);\n}\n\n\n/**\n * Evaluate corpus of histogram implementations\n */\ntemplate <\n    int         NUM_CHANNELS,\n    int         ACTIVE_CHANNELS,\n    int         NUM_BINS,\n    typename    PixelType>\nvoid TestMethods(\n    PixelType*  h_pixels,\n    int         height,\n    int         width,\n    int         timing_iterations,\n    double      bandwidth_GBs)\n{\n    // Copy data to gpu\n    PixelType* d_pixels;\n    size_t pixel_bytes = width * height * sizeof(PixelType);\n    CubDebugExit(g_allocator.DeviceAllocate((void**) &d_pixels, pixel_bytes));\n    CubDebugExit(cudaMemcpy(d_pixels, h_pixels, pixel_bytes, cudaMemcpyHostToDevice));\n\n    if (g_report) printf(\"%.3f, \", double(pixel_bytes) / bandwidth_GBs / 1000);\n\n    // Allocate results arrays on cpu/gpu\n    unsigned int *h_hist;\n    unsigned int *d_hist;\n    size_t histogram_bytes = NUM_BINS * ACTIVE_CHANNELS * sizeof(unsigned int);\n    h_hist = (unsigned int *) malloc(histogram_bytes);\n    g_allocator.DeviceAllocate((void **) &d_hist, histogram_bytes);\n\n    // Compute reference cpu histogram\n    HistogramGold<ACTIVE_CHANNELS, NUM_BINS>(h_pixels, width, height, h_hist);\n\n    // Store timings\n    std::vector<std::pair<std::string, double> > timings;\n\n    // Run experiments\n    RunTest<ACTIVE_CHANNELS, NUM_BINS>(timings, d_pixels, width, height, d_hist, h_hist, timing_iterations,\n        \"CUB\", \"CUB\", run_cub_histogram<NUM_CHANNELS, ACTIVE_CHANNELS, NUM_BINS, PixelType>);\n    RunTest<ACTIVE_CHANNELS, NUM_BINS>(timings, d_pixels, width, height, d_hist, h_hist, timing_iterations,\n        \"Shared memory atomics\", \"smem atomics\", run_smem_atomics<ACTIVE_CHANNELS, NUM_BINS, PixelType>);\n    RunTest<ACTIVE_CHANNELS, NUM_BINS>(timings, d_pixels, width, height, d_hist, h_hist, timing_iterations,\n        \"Global memory atomics\", \"gmem atomics\", run_gmem_atomics<ACTIVE_CHANNELS, NUM_BINS, PixelType>);\n\n    // Report timings\n    if (!g_report)\n    {\n        std::sort(timings.begin(), timings.end(), less_than_value());\n        printf(\"Timings (us):\\n\");\n        for (int i = 0; i < timings.size(); i++)\n        {\n            double bandwidth = height * width * sizeof(PixelType) / timings[i].second / 1000;\n            printf(\"\\t %.3f %s (%.3f GB/s, %.3f%% peak)\\n\", timings[i].second, timings[i].first.c_str(), bandwidth, bandwidth / bandwidth_GBs * 100);\n        }\n        printf(\"\\n\");\n    }\n\n    // Free data\n    CubDebugExit(g_allocator.DeviceFree(d_pixels));\n    CubDebugExit(g_allocator.DeviceFree(d_hist));\n    free(h_hist);\n}\n\n\n/**\n * Test different problem genres\n */\nvoid TestGenres(\n    uchar4*     uchar4_pixels,\n    int         height,\n    int         width,\n    int         timing_iterations,\n    double      bandwidth_GBs)\n{\n    int num_pixels = width * height;\n\n    {\n        if (!g_report) printf(\"1 channel uchar1 tests (256-bin):\\n\\n\"); fflush(stdout);\n\n        size_t      image_bytes     = num_pixels * sizeof(uchar1);\n        uchar1*     uchar1_pixels   = (uchar1*) malloc(image_bytes);\n\n        // Convert to 1-channel (averaging first 3 channels)\n        for (int i = 0; i < num_pixels; ++i)\n        {\n            uchar1_pixels[i].x = (unsigned char)\n                (((unsigned int) uchar4_pixels[i].x +\n                  (unsigned int) uchar4_pixels[i].y +\n                  (unsigned int) uchar4_pixels[i].z) / 3);\n        }\n\n        TestMethods<1, 1, 256>(uchar1_pixels, width, height, timing_iterations, bandwidth_GBs);\n        free(uchar1_pixels);\n        if (g_report) printf(\", \");\n    }\n\n    {\n        if (!g_report) printf(\"3/4 channel uchar4 tests (256-bin):\\n\\n\"); fflush(stdout);\n        TestMethods<4, 3, 256>(uchar4_pixels, width, height, timing_iterations, bandwidth_GBs);\n        if (g_report) printf(\", \");\n    }\n\n    {\n        if (!g_report) printf(\"3/4 channel float4 tests (256-bin):\\n\\n\"); fflush(stdout);\n        size_t      image_bytes     = num_pixels * sizeof(float4);\n        float4*     float4_pixels   = (float4*) malloc(image_bytes);\n\n        // Convert to float4 with range [0.0, 1.0)\n        for (int i = 0; i < num_pixels; ++i)\n        {\n            float4_pixels[i].x = float(uchar4_pixels[i].x) / 256;\n            float4_pixels[i].y = float(uchar4_pixels[i].y) / 256;\n            float4_pixels[i].z = float(uchar4_pixels[i].z) / 256;\n            float4_pixels[i].w = float(uchar4_pixels[i].w) / 256;\n        }\n        TestMethods<4, 3, 256>(float4_pixels, width, height, timing_iterations, bandwidth_GBs);\n        free(float4_pixels);\n        if (g_report) printf(\"\\n\");\n    }\n}\n\n\n/**\n * Main\n */\nint main(int argc, char **argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\n            \"%s \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"[--i=<timing iterations>] \"\n            \"\\n\\t\"\n                \"--file=<.tga filename> \"\n            \"\\n\\t\"\n                \"--entropy=<-1 (0%), 0 (100%), 1 (81%), 2 (54%), 3 (34%), 4 (20%), ...\"\n                \"[--height=<default: 1080>] \"\n                \"[--width=<default: 1920>] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    std::string         filename;\n    int                 timing_iterations   = 100;\n    int                 entropy_reduction   = 0;\n    int                 height              = 1080;\n    int                 width               = 1920;\n\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_report = args.CheckCmdLineFlag(\"report\");\n    args.GetCmdLineArgument(\"i\", timing_iterations);\n    args.GetCmdLineArgument(\"file\", filename);\n    args.GetCmdLineArgument(\"height\", height);\n    args.GetCmdLineArgument(\"width\", width);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get GPU device bandwidth (GB/s)\n    int device_ordinal, bus_width, mem_clock_khz;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n    CubDebugExit(cudaDeviceGetAttribute(&bus_width, cudaDevAttrGlobalMemoryBusWidth, device_ordinal));\n    CubDebugExit(cudaDeviceGetAttribute(&mem_clock_khz, cudaDevAttrMemoryClockRate, device_ordinal));\n    double bandwidth_GBs = double(bus_width) * mem_clock_khz * 2 / 8 / 1000 / 1000;\n\n    // Run test(s)\n    uchar4* uchar4_pixels = NULL;\n    if (!g_report)\n    {\n        if (!filename.empty())\n        {\n            // Parse targa file\n            ReadTga(uchar4_pixels, width, height, filename.c_str());\n            printf(\"File %s: width(%d) height(%d)\\n\\n\", filename.c_str(), width, height); fflush(stdout);\n        }\n        else\n        {\n            // Generate image\n            GenerateRandomImage(uchar4_pixels, width, height, entropy_reduction);\n            printf(\"Random image: entropy-reduction(%d) width(%d) height(%d)\\n\\n\", entropy_reduction, width, height); fflush(stdout);\n        }\n\n        TestGenres(uchar4_pixels, height, width, timing_iterations, bandwidth_GBs);\n    }\n    else\n    {\n        // Run test suite\n        printf(\"Test, MIN, RLE CUB, SMEM, GMEM, , MIN, RLE_CUB, SMEM, GMEM, , MIN, RLE_CUB, SMEM, GMEM\\n\");\n\n        // Entropy reduction tests\n        for (entropy_reduction = 0; entropy_reduction < 5; ++entropy_reduction)\n        {\n            printf(\"entropy reduction %d, \", entropy_reduction);\n            GenerateRandomImage(uchar4_pixels, width, height, entropy_reduction);\n            TestGenres(uchar4_pixels, height, width, timing_iterations, bandwidth_GBs);\n        }\n        printf(\"entropy reduction -1, \");\n        GenerateRandomImage(uchar4_pixels, width, height, -1);\n        TestGenres(uchar4_pixels, height, width, timing_iterations, bandwidth_GBs);\n        printf(\"\\n\");\n\n        // File image tests\n        std::vector<std::string> file_tests;\n        file_tests.push_back(\"animals\");\n        file_tests.push_back(\"apples\");\n        file_tests.push_back(\"sunset\");\n        file_tests.push_back(\"cheetah\");\n        file_tests.push_back(\"nature\");\n        file_tests.push_back(\"operahouse\");\n        file_tests.push_back(\"austin\");\n        file_tests.push_back(\"cityscape\");\n\n        for (int i = 0; i < file_tests.size(); ++i)\n        {\n            printf(\"%s, \", file_tests[i].c_str());\n            std::string filename = std::string(\"histogram/benchmark/\") + file_tests[i] + \".tga\";\n            ReadTga(uchar4_pixels, width, height, filename.c_str());\n            TestGenres(uchar4_pixels, height, width, timing_iterations, bandwidth_GBs);\n        }\n    }\n\n    free(uchar4_pixels);\n\n    CubDebugExit(cudaDeviceSynchronize());\n    printf(\"\\n\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "external/cub/experimental/sparse_matrix.h",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Matrix data structures and parsing logic\n ******************************************************************************/\n\n#pragma once\n\n#include <cmath>\n#include <cstring>\n\n#include <iterator>\n#include <string>\n#include <algorithm>\n#include <iostream>\n#include <queue>\n#include <set>\n#include <fstream>\n#include <stdio.h>\n\n#ifdef CUB_MKL\n    #include <numa.h>\n    #include <mkl.h>\n#endif\n\nusing namespace std;\n\n/******************************************************************************\n * COO matrix type\n ******************************************************************************/\n\nstruct GraphStats\n{\n    int         num_rows;\n    int         num_cols;\n    int         num_nonzeros;\n\n    double      diag_dist_mean;         // mean\n    double      diag_dist_std_dev;      // sample std dev\n    double      pearson_r;    // coefficient of variation\n\n    double      row_length_mean;        // mean\n    double      row_length_std_dev;     // sample std_dev\n    double      row_length_variation;   // coefficient of variation\n    double      row_length_skewness;    // skewness\n\n    void Display(bool show_labels = true)\n    {\n        if (show_labels)\n            printf(\"\\n\"\n                \"\\t num_rows: %d\\n\"\n                \"\\t num_cols: %d\\n\"\n                \"\\t num_nonzeros: %d\\n\"\n                \"\\t diag_dist_mean: %.2f\\n\"\n                \"\\t diag_dist_std_dev: %.2f\\n\"\n                \"\\t pearson_r: %f\\n\"\n                \"\\t row_length_mean: %.5f\\n\"\n                \"\\t row_length_std_dev: %.5f\\n\"\n                \"\\t row_length_variation: %.5f\\n\"\n                \"\\t row_length_skewness: %.5f\\n\",\n                    num_rows,\n                    num_cols,\n                    num_nonzeros,\n                    diag_dist_mean,\n                    diag_dist_std_dev,\n                    pearson_r,\n                    row_length_mean,\n                    row_length_std_dev,\n                    row_length_variation,\n                    row_length_skewness);\n        else\n            printf(\n                \"%d, \"\n                \"%d, \"\n                \"%d, \"\n                \"%.2f, \"\n                \"%.2f, \"\n                \"%f, \"\n                \"%.5f, \"\n                \"%.5f, \"\n                \"%.5f, \"\n                \"%.5f, \",\n                    num_rows,\n                    num_cols,\n                    num_nonzeros,\n                    diag_dist_mean,\n                    diag_dist_std_dev,\n                    pearson_r,\n                    row_length_mean,\n                    row_length_std_dev,\n                    row_length_variation,\n                    row_length_skewness);\n    }\n};\n\n\n\n/******************************************************************************\n * COO matrix type\n ******************************************************************************/\n\n\n/**\n * COO matrix type.  A COO matrix is just a vector of edge tuples.  Tuples are sorted\n * first by row, then by column.\n */\ntemplate<typename ValueT, typename OffsetT>\nstruct CooMatrix\n{\n    //---------------------------------------------------------------------\n    // Type definitions and constants\n    //---------------------------------------------------------------------\n\n    // COO edge tuple\n    struct CooTuple\n    {\n        OffsetT            row;\n        OffsetT            col;\n        ValueT             val;\n\n        CooTuple() {}\n        CooTuple(OffsetT row, OffsetT col) : row(row), col(col) {}\n        CooTuple(OffsetT row, OffsetT col, ValueT val) : row(row), col(col), val(val) {}\n\n        /**\n         * Comparator for sorting COO sparse format num_nonzeros\n         */\n        bool operator<(const CooTuple &other) const\n        {\n            if ((row < other.row) || ((row == other.row) && (col < other.col)))\n            {\n                return true;\n            }\n\n            return false;\n        }\n    };\n\n\n    //---------------------------------------------------------------------\n    // Data members\n    //---------------------------------------------------------------------\n\n    // Fields\n    int                 num_rows;\n    int                 num_cols;\n    int                 num_nonzeros;\n    CooTuple*           coo_tuples;\n\n    //---------------------------------------------------------------------\n    // Methods\n    //---------------------------------------------------------------------\n\n    // Constructor\n    CooMatrix() : num_rows(0), num_cols(0), num_nonzeros(0), coo_tuples(NULL) {}\n\n\n    /**\n     * Clear\n     */\n    void Clear()\n    {\n        if (coo_tuples) delete[] coo_tuples;\n        coo_tuples = NULL;\n    }\n\n\n    // Destructor\n    ~CooMatrix()\n    {\n        Clear();\n    }\n\n\n    // Display matrix to stdout\n    void Display()\n    {\n        cout << \"COO Matrix (\" << num_rows << \" rows, \" << num_cols << \" columns, \" << num_nonzeros << \" non-zeros):\\n\";\n        cout << \"Ordinal, Row, Column, Value\\n\";\n        for (int i = 0; i < num_nonzeros; i++)\n        {\n            cout << '\\t' << i << ',' << coo_tuples[i].row << ',' << coo_tuples[i].col << ',' << coo_tuples[i].val << \"\\n\";\n        }\n    }\n\n\n    /**\n     * Builds a symmetric COO sparse from an asymmetric CSR matrix.\n     */\n    template <typename CsrMatrixT>\n    void InitCsrSymmetric(CsrMatrixT &csr_matrix)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        num_rows        = csr_matrix.num_cols;\n        num_cols        = csr_matrix.num_rows;\n        num_nonzeros    = csr_matrix.num_nonzeros * 2;\n        coo_tuples      = new CooTuple[num_nonzeros];\n\n        for (OffsetT row = 0; row < csr_matrix.num_rows; ++row)\n        {\n            for (OffsetT nonzero = csr_matrix.row_offsets[row]; nonzero < csr_matrix.row_offsets[row + 1]; ++nonzero)\n            {\n                coo_tuples[nonzero].row = row;\n                coo_tuples[nonzero].col = csr_matrix.column_indices[nonzero];\n                coo_tuples[nonzero].val = csr_matrix.values[nonzero];\n\n                coo_tuples[csr_matrix.num_nonzeros + nonzero].row = coo_tuples[nonzero].col;\n                coo_tuples[csr_matrix.num_nonzeros + nonzero].col = coo_tuples[nonzero].row;\n                coo_tuples[csr_matrix.num_nonzeros + nonzero].val = csr_matrix.values[nonzero];\n\n            }\n        }\n\n        // Sort by rows, then columns\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n    }\n\n    /**\n     * Builds a COO sparse from a relabeled CSR matrix.\n     */\n    template <typename CsrMatrixT>\n    void InitCsrRelabel(CsrMatrixT &csr_matrix, OffsetT* relabel_indices)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        num_rows        = csr_matrix.num_rows;\n        num_cols        = csr_matrix.num_cols;\n        num_nonzeros    = csr_matrix.num_nonzeros;\n        coo_tuples      = new CooTuple[num_nonzeros];\n\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            for (OffsetT nonzero = csr_matrix.row_offsets[row]; nonzero < csr_matrix.row_offsets[row + 1]; ++nonzero)\n            {\n                coo_tuples[nonzero].row = relabel_indices[row];\n                coo_tuples[nonzero].col = relabel_indices[csr_matrix.column_indices[nonzero]];\n                coo_tuples[nonzero].val = csr_matrix.values[nonzero];\n            }\n        }\n\n        // Sort by rows, then columns\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n    }\n\n\n\n    /**\n     * Builds a METIS COO sparse from the given file.\n     */\n    void InitMetis(const string &metis_filename)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        // TODO\n    }\n\n\n    /**\n     * Builds a MARKET COO sparse from the given file.\n     */\n    void InitMarket(\n        const string&   market_filename,\n        ValueT          default_value       = 1.0,\n        bool            verbose             = false)\n    {\n        if (verbose) {\n            printf(\"Reading... \"); fflush(stdout);\n        }\n\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        std::ifstream ifs;\n        ifs.open(market_filename.c_str(), std::ifstream::in);\n        if (!ifs.good())\n        {\n            fprintf(stderr, \"Error opening file\\n\");\n            exit(1);\n        }\n\n        bool    array = false;\n        bool    symmetric = false;\n        bool    skew = false;\n        int     current_edge = -1;\n        char    line[1024];\n\n        if (verbose) {\n            printf(\"Parsing... \"); fflush(stdout);\n        }\n\n        while (true)\n        {\n            ifs.getline(line, 1024);\n            if (!ifs.good())\n            {\n                // Done\n                break;\n            }\n\n            if (line[0] == '%')\n            {\n                // Comment\n                if (line[1] == '%')\n                {\n                    // Banner\n                    symmetric   = (strstr(line, \"symmetric\") != NULL);\n                    skew        = (strstr(line, \"skew\") != NULL);\n                    array       = (strstr(line, \"array\") != NULL);\n\n                    if (verbose) {\n                        printf(\"(symmetric: %d, skew: %d, array: %d) \", symmetric, skew, array); fflush(stdout);\n                    }\n                }\n            }\n            else if (current_edge == -1)\n            {\n                // Problem description\n                int nparsed = sscanf(line, \"%d %d %d\", &num_rows, &num_cols, &num_nonzeros);\n                if ((!array) && (nparsed == 3))\n                {\n                    if (symmetric)\n                        num_nonzeros *= 2;\n\n                    // Allocate coo matrix\n                    coo_tuples = new CooTuple[num_nonzeros];\n                    current_edge = 0;\n\n                }\n                else if (array && (nparsed == 2))\n                {\n                    // Allocate coo matrix\n                    num_nonzeros = num_rows * num_cols;\n                    coo_tuples = new CooTuple[num_nonzeros];\n                    current_edge = 0;\n                }\n                else\n                {\n                    fprintf(stderr, \"Error parsing MARKET matrix: invalid problem description: %s\\n\", line);\n                    exit(1);\n                }\n\n            }\n            else\n            {\n                // Edge\n                if (current_edge >= num_nonzeros)\n                {\n                    fprintf(stderr, \"Error parsing MARKET matrix: encountered more than %d num_nonzeros\\n\", num_nonzeros);\n                    exit(1);\n                }\n\n                int row, col;\n                double val;\n\n                if (array)\n                {\n                    if (sscanf(line, \"%lf\", &val) != 1)\n                    {\n                        fprintf(stderr, \"Error parsing MARKET matrix: badly formed current_edge: '%s' at edge %d\\n\", line, current_edge);\n                        exit(1);\n                    }\n                    col = (current_edge / num_rows);\n                    row = (current_edge - (num_rows * col));\n\n                    coo_tuples[current_edge] = CooTuple(row, col, val);    // Convert indices to zero-based\n                }\n                else\n                {\n                    // Parse nonzero (note: using strtol and strtod is 2x faster than sscanf or istream parsing)\n                    char *l = line;\n                    char *t = NULL;\n\n                    // parse row\n                    row = strtol(l, &t, 0);\n                    if (t == l)\n                    {\n                        fprintf(stderr, \"Error parsing MARKET matrix: badly formed row at edge %d\\n\", current_edge);\n                        exit(1);\n                    }\n                    l = t;\n\n                    // parse col\n                    col = strtol(l, &t, 0);\n                    if (t == l)\n                    {\n                        fprintf(stderr, \"Error parsing MARKET matrix: badly formed col at edge %d\\n\", current_edge);\n                        exit(1);\n                    }\n                    l = t;\n\n                    // parse val\n                    val = strtod(l, &t);\n                    if (t == l)\n                    {\n                        val = default_value;\n                    }\n/*\n                    int nparsed = sscanf(line, \"%d %d %lf\", &row, &col, &val);\n                    if (nparsed == 2)\n                    {\n                        // No value specified\n                        val = default_value;\n                        \n                    }\n                    else if (nparsed != 3)\n                    {\n                        fprintf(stderr, \"Error parsing MARKET matrix 1: badly formed current_edge: %d parsed at edge %d\\n\", nparsed, current_edge);\n                        exit(1);\n                    }\n*/\n\n                    coo_tuples[current_edge] = CooTuple(row - 1, col - 1, val);    // Convert indices to zero-based\n\n                }\n\n                current_edge++;\n\n                if (symmetric && (row != col))\n                {\n                    coo_tuples[current_edge].row = coo_tuples[current_edge - 1].col;\n                    coo_tuples[current_edge].col = coo_tuples[current_edge - 1].row;\n                    coo_tuples[current_edge].val = coo_tuples[current_edge - 1].val * (skew ? -1 : 1);\n                    current_edge++;\n                }\n            }\n        }\n\n        // Adjust nonzero count (nonzeros along the diagonal aren't reversed)\n        num_nonzeros = current_edge;\n\n        if (verbose) {\n            printf(\"done. Ordering...\"); fflush(stdout);\n        }\n\n        // Sort by rows, then columns\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n\n        if (verbose) {\n            printf(\"done. \"); fflush(stdout);\n        }\n\n        ifs.close();\n    }\n\n\n    /**\n     * Builds a dense matrix\n     */\n    int InitDense(\n        OffsetT     num_rows,\n        OffsetT     num_cols,\n        ValueT      default_value   = 1.0,\n        bool        verbose         = false)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        this->num_rows  = num_rows;\n        this->num_cols  = num_cols;\n\n        num_nonzeros    = num_rows * num_cols;\n        coo_tuples      = new CooTuple[num_nonzeros];\n\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            for (OffsetT col = 0; col < num_cols; ++col)\n            {\n                coo_tuples[(row * num_cols) + col] = CooTuple(row, col, default_value);\n            }\n        }\n\n        // Sort by rows, then columns\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n\n        return 0;\n    }\n\n    /**\n     * Builds a wheel COO sparse matrix having spokes spokes.\n     */\n    int InitWheel(\n        OffsetT     spokes,\n        ValueT      default_value   = 1.0,\n        bool        verbose         = false)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        num_rows        = spokes + 1;\n        num_cols        = num_rows;\n        num_nonzeros    = spokes * 2;\n        coo_tuples      = new CooTuple[num_nonzeros];\n\n        // Add spoke num_nonzeros\n        int current_edge = 0;\n        for (OffsetT i = 0; i < spokes; i++)\n        {\n            coo_tuples[current_edge] = CooTuple(0, i + 1, default_value);\n            current_edge++;\n        }\n\n        // Add rim\n        for (OffsetT i = 0; i < spokes; i++)\n        {\n            OffsetT dest = (i + 1) % spokes;\n            coo_tuples[current_edge] = CooTuple(i + 1, dest + 1, default_value);\n            current_edge++;\n        }\n\n        // Sort by rows, then columns\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n\n        return 0;\n    }\n\n\n    /**\n     * Builds a square 2D grid CSR matrix.  Interior num_vertices have degree 5 when including\n     * a self-loop.\n     *\n     * Returns 0 on success, 1 on failure.\n     */\n    int InitGrid2d(OffsetT width, bool self_loop, ValueT default_value = 1.0)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            exit(1);\n        }\n\n        int     interior_nodes  = (width - 2) * (width - 2);\n        int     edge_nodes      = (width - 2) * 4;\n        int     corner_nodes    = 4;\n        num_rows                       = width * width;\n        num_cols                       = num_rows;\n        num_nonzeros                   = (interior_nodes * 4) + (edge_nodes * 3) + (corner_nodes * 2);\n\n        if (self_loop)\n            num_nonzeros += num_rows;\n\n        coo_tuples          = new CooTuple[num_nonzeros];\n        int current_edge    = 0;\n\n        for (OffsetT j = 0; j < width; j++)\n        {\n            for (OffsetT k = 0; k < width; k++)\n            {\n                OffsetT me = (j * width) + k;\n\n                // West\n                OffsetT neighbor = (j * width) + (k - 1);\n                if (k - 1 >= 0) {\n                    coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                    current_edge++;\n                }\n\n                // East\n                neighbor = (j * width) + (k + 1);\n                if (k + 1 < width) {\n                    coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                    current_edge++;\n                }\n\n                // North\n                neighbor = ((j - 1) * width) + k;\n                if (j - 1 >= 0) {\n                    coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                    current_edge++;\n                }\n\n                // South\n                neighbor = ((j + 1) * width) + k;\n                if (j + 1 < width) {\n                    coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                    current_edge++;\n                }\n\n                if (self_loop)\n                {\n                    neighbor = me;\n                    coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                    current_edge++;\n                }\n            }\n        }\n\n        // Sort by rows, then columns, update dims\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n\n        return 0;\n    }\n\n\n    /**\n     * Builds a square 3D grid COO sparse matrix.  Interior num_vertices have degree 7 when including\n     * a self-loop.  Values are unintialized, coo_tuples are sorted.\n     */\n    int InitGrid3d(OffsetT width, bool self_loop, ValueT default_value = 1.0)\n    {\n        if (coo_tuples)\n        {\n            fprintf(stderr, \"Matrix already constructed\\n\");\n            return -1;\n        }\n\n        OffsetT interior_nodes  = (width - 2) * (width - 2) * (width - 2);\n        OffsetT face_nodes      = (width - 2) * (width - 2) * 6;\n        OffsetT edge_nodes      = (width - 2) * 12;\n        OffsetT corner_nodes    = 8;\n        num_cols                       = width * width * width;\n        num_rows                       = num_cols;\n        num_nonzeros                     = (interior_nodes * 6) + (face_nodes * 5) + (edge_nodes * 4) + (corner_nodes * 3);\n\n        if (self_loop)\n            num_nonzeros += num_rows;\n\n        coo_tuples          = new CooTuple[num_nonzeros];\n        int current_edge    = 0;\n\n        for (OffsetT i = 0; i < width; i++)\n        {\n            for (OffsetT j = 0; j < width; j++)\n            {\n                for (OffsetT k = 0; k < width; k++)\n                {\n\n                    OffsetT me = (i * width * width) + (j * width) + k;\n\n                    // Up\n                    OffsetT neighbor = (i * width * width) + (j * width) + (k - 1);\n                    if (k - 1 >= 0) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    // Down\n                    neighbor = (i * width * width) + (j * width) + (k + 1);\n                    if (k + 1 < width) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    // West\n                    neighbor = (i * width * width) + ((j - 1) * width) + k;\n                    if (j - 1 >= 0) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    // East\n                    neighbor = (i * width * width) + ((j + 1) * width) + k;\n                    if (j + 1 < width) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    // North\n                    neighbor = ((i - 1) * width * width) + (j * width) + k;\n                    if (i - 1 >= 0) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    // South\n                    neighbor = ((i + 1) * width * width) + (j * width) + k;\n                    if (i + 1 < width) {\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n\n                    if (self_loop)\n                    {\n                        neighbor = me;\n                        coo_tuples[current_edge] = CooTuple(me, neighbor, default_value);\n                        current_edge++;\n                    }\n                }\n            }\n        }\n\n        // Sort by rows, then columns, update dims\n        std::stable_sort(coo_tuples, coo_tuples + num_nonzeros);\n\n        return 0;\n    }\n};\n\n\n\n/******************************************************************************\n * COO matrix type\n ******************************************************************************/\n\n\n/**\n * CSR sparse format matrix\n */\ntemplate<\n    typename ValueT,\n    typename OffsetT>\nstruct CsrMatrix\n{\n    int         num_rows;\n    int         num_cols;\n    int         num_nonzeros;\n    OffsetT*    row_offsets;\n    OffsetT*    column_indices;\n    ValueT*     values;\n    bool        numa_malloc;\n\n    /**\n     * Constructor\n     */\n    CsrMatrix() : num_rows(0), num_cols(0), num_nonzeros(0), row_offsets(NULL), column_indices(NULL), values(NULL) \n    {\n#ifdef CUB_MKL\n        numa_malloc = ((numa_available() >= 0) && (numa_num_task_nodes() > 1));\n#else\n        numa_malloc = false;\n#endif\n    }\n\n\n    /**\n     * Clear\n     */\n    void Clear()\n    {\n#ifdef CUB_MKL\n        if (numa_malloc) \n        {\n            numa_free(row_offsets, sizeof(OffsetT) * (num_rows + 1));\n            numa_free(values, sizeof(ValueT) * num_nonzeros);\n            numa_free(column_indices, sizeof(OffsetT) * num_nonzeros);\n        }\n        else\n        {\n            if (row_offsets)    mkl_free(row_offsets);\n            if (column_indices) mkl_free(column_indices);\n            if (values)         mkl_free(values);\n        }\n\n#else\n        if (row_offsets)    delete[] row_offsets;\n        if (column_indices) delete[] column_indices;\n        if (values)         delete[] values;\n#endif\n\n        row_offsets = NULL;\n        column_indices = NULL;\n        values = NULL;\n    }\n\n    /**\n     * Destructor\n     */\n    ~CsrMatrix()\n    {\n        Clear();\n    }\n\n    GraphStats Stats()\n    {\n        GraphStats stats;\n        stats.num_rows = num_rows;\n        stats.num_cols = num_cols;\n        stats.num_nonzeros = num_nonzeros;\n\n        //\n        // Compute diag-distance statistics\n        //\n\n        OffsetT samples     = 0;\n        double  mean        = 0.0;\n        double  ss_tot      = 0.0;\n\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            OffsetT nz_idx_start    = row_offsets[row];\n            OffsetT nz_idx_end      = row_offsets[row + 1];\n\n            for (int nz_idx = nz_idx_start; nz_idx < nz_idx_end; ++nz_idx)\n            {\n                OffsetT col             = column_indices[nz_idx];\n                double x                = (col > row) ? col - row : row - col;\n\n                samples++;\n                double delta            = x - mean;\n                mean                    = mean + (delta / samples);\n                ss_tot                  += delta * (x - mean);\n            }\n        }\n        stats.diag_dist_mean            = mean;\n        double variance                 = ss_tot / samples;\n        stats.diag_dist_std_dev         = sqrt(variance);\n\n\n        //\n        // Compute deming statistics\n        //\n\n        samples         = 0;\n        double mean_x   = 0.0;\n        double mean_y   = 0.0;\n        double ss_x     = 0.0;\n        double ss_y     = 0.0;\n\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            OffsetT nz_idx_start    = row_offsets[row];\n            OffsetT nz_idx_end      = row_offsets[row + 1];\n\n            for (int nz_idx = nz_idx_start; nz_idx < nz_idx_end; ++nz_idx)\n            {\n                OffsetT col             = column_indices[nz_idx];\n\n                samples++;\n                double x                = col;\n                double y                = row;\n                double delta;\n\n                delta                   = x - mean_x;\n                mean_x                  = mean_x + (delta / samples);\n                ss_x                    += delta * (x - mean_x);\n\n                delta                   = y - mean_y;\n                mean_y                  = mean_y + (delta / samples);\n                ss_y                    += delta * (y - mean_y);\n            }\n        }\n\n        samples         = 0;\n        double s_xy     = 0.0;\n        double s_xxy    = 0.0;\n        double s_xyy    = 0.0;\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            OffsetT nz_idx_start    = row_offsets[row];\n            OffsetT nz_idx_end      = row_offsets[row + 1];\n\n            for (int nz_idx = nz_idx_start; nz_idx < nz_idx_end; ++nz_idx)\n            {\n                OffsetT col             = column_indices[nz_idx];\n\n                samples++;\n                double x                = col;\n                double y                = row;\n\n                double xy =             (x - mean_x) * (y - mean_y);\n                double xxy =            (x - mean_x) * (x - mean_x) * (y - mean_y);\n                double xyy =            (x - mean_x) * (y - mean_y) * (y - mean_y);\n                double delta;\n\n                delta                   = xy - s_xy;\n                s_xy                    = s_xy + (delta / samples);\n\n                delta                   = xxy - s_xxy;\n                s_xxy                   = s_xxy + (delta / samples);\n\n                delta                   = xyy - s_xyy;\n                s_xyy                   = s_xyy + (delta / samples);\n            }\n        }\n\n        double s_xx     = ss_x / num_nonzeros;\n        double s_yy     = ss_y / num_nonzeros;\n\n        double deming_slope = (s_yy - s_xx + sqrt(((s_yy - s_xx) * (s_yy - s_xx)) + (4 * s_xy * s_xy))) / (2 * s_xy);\n\n        stats.pearson_r = (num_nonzeros * s_xy) / (sqrt(ss_x) * sqrt(ss_y));\n\n\n        //\n        // Compute row-length statistics\n        //\n\n        // Sample mean\n        stats.row_length_mean       = double(num_nonzeros) / num_rows;\n        variance                    = 0.0;\n        stats.row_length_skewness   = 0.0;\n        for (OffsetT row = 0; row < num_rows; ++row)\n        {\n            OffsetT length              = row_offsets[row + 1] - row_offsets[row];\n            double delta                = double(length) - stats.row_length_mean;\n            variance   += (delta * delta);\n            stats.row_length_skewness   += (delta * delta * delta);\n        }\n        variance                    /= num_rows;\n        stats.row_length_std_dev    = sqrt(variance);\n        stats.row_length_skewness   = (stats.row_length_skewness / num_rows) / pow(stats.row_length_std_dev, 3.0);\n        stats.row_length_variation  = stats.row_length_std_dev / stats.row_length_mean;\n\n        return stats;\n    }\n\n    /**\n     * Build CSR matrix from sorted COO matrix\n     */\n    void FromCoo(const CooMatrix<ValueT, OffsetT> &coo_matrix)\n    {\n        num_rows        = coo_matrix.num_rows;\n        num_cols        = coo_matrix.num_cols;\n        num_nonzeros    = coo_matrix.num_nonzeros;\n\n#ifdef CUB_MKL\n\n        if (numa_malloc)\n        {\n            numa_set_strict(1);\n//            numa_set_bind_policy(1);\n\n//        values          = (ValueT*) numa_alloc_interleaved(sizeof(ValueT) * num_nonzeros);\n//        row_offsets     = (OffsetT*) numa_alloc_interleaved(sizeof(OffsetT) * (num_rows + 1));\n//        column_indices  = (OffsetT*) numa_alloc_interleaved(sizeof(OffsetT) * num_nonzeros);\n\n            row_offsets     = (OffsetT*) numa_alloc_onnode(sizeof(OffsetT) * (num_rows + 1), 0);\n            column_indices  = (OffsetT*) numa_alloc_onnode(sizeof(OffsetT) * num_nonzeros, 0);\n            values          = (ValueT*) numa_alloc_onnode(sizeof(ValueT) * num_nonzeros, 1);\n        }\n        else\n        {\n            values          = (ValueT*) mkl_malloc(sizeof(ValueT) * num_nonzeros, 4096);\n            row_offsets     = (OffsetT*) mkl_malloc(sizeof(OffsetT) * (num_rows + 1), 4096);\n            column_indices  = (OffsetT*) mkl_malloc(sizeof(OffsetT) * num_nonzeros, 4096);\n\n        }\n\n#else\n        row_offsets     = new OffsetT[num_rows + 1];\n        column_indices  = new OffsetT[num_nonzeros];\n        values          = new ValueT[num_nonzeros];\n#endif\n\n        OffsetT prev_row = -1;\n        for (OffsetT current_edge = 0; current_edge < num_nonzeros; current_edge++)\n        {\n            OffsetT current_row = coo_matrix.coo_tuples[current_edge].row;\n\n            // Fill in rows up to and including the current row\n            for (OffsetT row = prev_row + 1; row <= current_row; row++)\n            {\n                row_offsets[row] = current_edge;\n            }\n            prev_row = current_row;\n\n            column_indices[current_edge]    = coo_matrix.coo_tuples[current_edge].col;\n            values[current_edge]            = coo_matrix.coo_tuples[current_edge].val;\n        }\n\n        // Fill out any trailing edgeless vertices (and the end-of-list element)\n        for (OffsetT row = prev_row + 1; row <= num_rows; row++)\n        {\n            row_offsets[row] = num_nonzeros;\n        }\n    }\n\n\n    /**\n     * Display log-histogram to stdout\n     */\n    void DisplayHistogram()\n    {\n        // Initialize\n        int log_counts[9];\n        for (int i = 0; i < 9; i++)\n        {\n            log_counts[i] = 0;\n        }\n\n        // Scan\n        int max_log_length = -1;\n        for (OffsetT row = 0; row < num_rows; row++)\n        {\n            OffsetT length = row_offsets[row + 1] - row_offsets[row];\n\n            int log_length = -1;\n            while (length > 0)\n            {\n                length /= 10;\n                log_length++;\n            }\n            if (log_length > max_log_length)\n            {\n                max_log_length = log_length;\n            }\n\n            log_counts[log_length + 1]++;\n        }\n        printf(\"CSR matrix (%d rows, %d columns, %d non-zeros):\\n\", (int) num_rows, (int) num_cols, (int) num_nonzeros);\n        for (int i = -1; i < max_log_length + 1; i++)\n        {\n            printf(\"\\tDegree 1e%d: \\t%d (%.2f%%)\\n\", i, log_counts[i + 1], (float) log_counts[i + 1] * 100.0 / num_cols);\n        }\n        fflush(stdout);\n    }\n\n\n    /**\n     * Display matrix to stdout\n     */\n    void Display()\n    {\n        printf(\"Input Matrix:\\n\");\n        for (OffsetT row = 0; row < num_rows; row++)\n        {\n            printf(\"%d [@%d, #%d]: \", row, row_offsets[row], row_offsets[row + 1] - row_offsets[row]);\n            for (OffsetT current_edge = row_offsets[row]; current_edge < row_offsets[row + 1]; current_edge++)\n            {\n                printf(\"%d (%f), \", column_indices[current_edge], values[current_edge]);\n            }\n            printf(\"\\n\");\n        }\n        fflush(stdout);\n    }\n\n\n};\n\n\n\n/******************************************************************************\n * Matrix transformations\n ******************************************************************************/\n\n// Comparator for ordering rows by degree (lowest first), then by row-id (lowest first)\ntemplate <typename OffsetT>\nstruct OrderByLow\n{\n    OffsetT* row_degrees;\n    OrderByLow(OffsetT* row_degrees) : row_degrees(row_degrees) {}\n\n    bool operator()(const OffsetT &a, const OffsetT &b)\n    {\n        if (row_degrees[a] < row_degrees[b])\n            return true;\n        else if (row_degrees[a] > row_degrees[b])\n            return false;\n        else\n            return (a < b);\n    }\n};\n\n// Comparator for ordering rows by degree (highest first), then by row-id (lowest first)\ntemplate <typename OffsetT>\nstruct OrderByHigh\n{\n    OffsetT* row_degrees;\n    OrderByHigh(OffsetT* row_degrees) : row_degrees(row_degrees) {}\n\n    bool operator()(const OffsetT &a, const OffsetT &b)\n    {\n        if (row_degrees[a] > row_degrees[b])\n            return true;\n        else if (row_degrees[a] < row_degrees[b])\n            return false;\n        else\n            return (a < b);\n    }\n};\n\n\n\n/**\n * Reverse Cuthill-McKee\n */\ntemplate <typename ValueT, typename OffsetT>\nvoid RcmRelabel(\n    CsrMatrix<ValueT, OffsetT>&     matrix,\n    OffsetT*                        relabel_indices)\n{\n    // Initialize row degrees\n    OffsetT* row_degrees_in     = new OffsetT[matrix.num_rows];\n    OffsetT* row_degrees_out    = new OffsetT[matrix.num_rows];\n    for (OffsetT row = 0; row < matrix.num_rows; ++row)\n    {\n        row_degrees_in[row]         = 0;\n        row_degrees_out[row]        = matrix.row_offsets[row + 1] - matrix.row_offsets[row];\n    }\n    for (OffsetT nonzero = 0; nonzero < matrix.num_nonzeros; ++nonzero)\n    {\n        row_degrees_in[matrix.column_indices[nonzero]]++;\n    }\n\n    // Initialize unlabeled set \n    typedef std::set<OffsetT, OrderByLow<OffsetT> > UnlabeledSet;\n    typename UnlabeledSet::key_compare  unlabeled_comp(row_degrees_in);\n    UnlabeledSet                        unlabeled(unlabeled_comp);\n    for (OffsetT row = 0; row < matrix.num_rows; ++row)\n    {\n        relabel_indices[row]    = -1;\n        unlabeled.insert(row);\n    }\n\n    // Initialize queue set\n    std::deque<OffsetT> q;\n\n    // Process unlabeled vertices (traverse connected components)\n    OffsetT relabel_idx = 0;\n    while (!unlabeled.empty())\n    {\n        // Seed the unvisited frontier queue with the unlabeled vertex of lowest-degree\n        OffsetT vertex = *unlabeled.begin();\n        q.push_back(vertex);\n\n        while (!q.empty())\n        {\n            vertex = q.front();\n            q.pop_front();\n\n            if (relabel_indices[vertex] == -1)\n            {\n                // Update this vertex\n                unlabeled.erase(vertex);\n                relabel_indices[vertex] = relabel_idx;\n                relabel_idx++;\n\n                // Sort neighbors by degree\n                OrderByLow<OffsetT> neighbor_comp(row_degrees_in);\n                std::sort(\n                    matrix.column_indices + matrix.row_offsets[vertex],\n                    matrix.column_indices + matrix.row_offsets[vertex + 1],\n                    neighbor_comp);\n\n                // Inspect neighbors, adding to the out frontier if unlabeled\n                for (OffsetT neighbor_idx = matrix.row_offsets[vertex];\n                    neighbor_idx < matrix.row_offsets[vertex + 1];\n                    ++neighbor_idx)\n                {\n                    OffsetT neighbor = matrix.column_indices[neighbor_idx];\n                    q.push_back(neighbor);\n                }\n            }\n        }\n    }\n\n/*\n    // Reverse labels\n    for (int row = 0; row < matrix.num_rows; ++row)\n    {\n        relabel_indices[row] = matrix.num_rows - relabel_indices[row] - 1;\n    }\n*/\n\n    // Cleanup\n    if (row_degrees_in) delete[] row_degrees_in;\n    if (row_degrees_out) delete[] row_degrees_out;\n}\n\n\n/**\n * Reverse Cuthill-McKee\n */\ntemplate <typename ValueT, typename OffsetT>\nvoid RcmRelabel(\n    CsrMatrix<ValueT, OffsetT>&     matrix,\n    bool                            verbose = false)\n{\n    // Do not process if not square\n    if (matrix.num_cols != matrix.num_rows)\n    {\n        if (verbose) {\n            printf(\"RCM transformation ignored (not square)\\n\"); fflush(stdout);\n        }\n        return;\n    }\n\n    // Initialize relabel indices\n    OffsetT* relabel_indices = new OffsetT[matrix.num_rows];\n\n    if (verbose) {\n        printf(\"RCM relabeling... \"); fflush(stdout);\n    }\n\n    RcmRelabel(matrix, relabel_indices);\n\n    if (verbose) {\n        printf(\"done. Reconstituting... \"); fflush(stdout);\n    }\n\n    // Create a COO matrix from the relabel indices\n    CooMatrix<ValueT, OffsetT> coo_matrix;\n    coo_matrix.InitCsrRelabel(matrix, relabel_indices);\n\n    // Reconstitute the CSR matrix from the sorted COO tuples\n    if (relabel_indices) delete[] relabel_indices;\n    matrix.Clear();\n    matrix.FromCoo(coo_matrix);\n\n    if (verbose) {\n        printf(\"done. \"); fflush(stdout);\n    }\n}\n\n\n\n\n"
  },
  {
    "path": "external/cub/experimental/spmv_compare.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIAeBILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n//---------------------------------------------------------------------\n// SpMV comparison tool\n//---------------------------------------------------------------------\n\n#include <stdio.h>\n#include <map>\n#include <vector>\n#include <algorithm>\n#include <cstdio>\n#include <fstream>\n\n#include <cusparse.h>\n\n#include \"sparse_matrix.h\"\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <cub/device/device_spmv.cuh>\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/tex_ref_input_iterator.cuh>\n#include <test/test_util.h>\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants, and type declarations\n//---------------------------------------------------------------------\n\nbool                    g_quiet     = false;        // Whether to display stats in CSV format\nbool                    g_verbose   = false;        // Whether to display output to console\nbool                    g_verbose2  = false;        // Whether to display input to console\nCachingDeviceAllocator  g_allocator(true);          // Caching allocator for device memory\n\n\n//---------------------------------------------------------------------\n// SpMV verification\n//---------------------------------------------------------------------\n\n// Compute reference SpMV y = Ax\ntemplate <\n    typename ValueT,\n    typename OffsetT>\nvoid SpmvGold(\n    CsrMatrix<ValueT, OffsetT>&     a,\n    ValueT*                         vector_x,\n    ValueT*                         vector_y_in,\n    ValueT*                         vector_y_out,\n    ValueT                          alpha,\n    ValueT                          beta)\n{\n    for (OffsetT row = 0; row < a.num_rows; ++row)\n    {\n        ValueT partial = beta * vector_y_in[row];\n        for (\n            OffsetT offset = a.row_offsets[row];\n            offset < a.row_offsets[row + 1];\n            ++offset)\n        {\n            partial += alpha * a.values[offset] * vector_x[a.column_indices[offset]];\n        }\n        vector_y_out[row] = partial;\n    }\n}\n\n\n//---------------------------------------------------------------------\n// GPU I/O proxy\n//---------------------------------------------------------------------\n\n/**\n * Read every matrix nonzero value, read every corresponding vector value\n */\ntemplate <\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD,\n    typename    ValueT,\n    typename    OffsetT,\n    typename    VectorItr>\n__launch_bounds__ (int(BLOCK_THREADS))\n__global__ void NonZeroIoKernel(\n    SpmvParams<ValueT, OffsetT> params,\n    VectorItr                   d_vector_x)\n{\n    enum\n    {\n        TILE_ITEMS      = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n\n    ValueT nonzero = 0.0;\n\n    int tile_idx = blockIdx.x;\n\n    OffsetT block_offset = tile_idx * TILE_ITEMS;\n\n    OffsetT column_indices[ITEMS_PER_THREAD];\n    ValueT values[ITEMS_PER_THREAD];\n\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n    {\n        OffsetT nonzero_idx = block_offset + (ITEM * BLOCK_THREADS) + threadIdx.x;\n\n        OffsetT* ci = params.d_column_indices + nonzero_idx;\n        ValueT*a = params.d_values + nonzero_idx;\n\n        column_indices[ITEM]    = (nonzero_idx < params.num_nonzeros) ? *ci : 0;\n        values[ITEM]            = (nonzero_idx < params.num_nonzeros) ? *a : 0.0;\n    }\n\n    __syncthreads();\n\n    // Read vector\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n    {\n        ValueT vector_value    = ThreadLoad<LOAD_LDG>(params.d_vector_x + column_indices[ITEM]);\n        nonzero                += vector_value * values[ITEM];\n    }\n\n    __syncthreads();\n\n    if (block_offset < params.num_rows)\n    {\n        #pragma unroll\n        for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        {\n            OffsetT row_idx = block_offset + (ITEM * BLOCK_THREADS) + threadIdx.x;\n            if (row_idx < params.num_rows)\n            {\n                OffsetT row_end_offset = ThreadLoad<LOAD_DEFAULT>(params.d_row_end_offsets + row_idx);\n\n                if ((row_end_offset >= 0) && (nonzero == nonzero))\n                    params.d_vector_y[row_idx] = nonzero;\n            }\n        }\n    }\n\n}\n\n\n/**\n * Run GPU I/O proxy\n */\ntemplate <\n    typename ValueT,\n    typename OffsetT>\nfloat TestGpuCsrIoProxy(\n    SpmvParams<ValueT, OffsetT>&    params,\n    int                             timing_iterations)\n{\n    enum {\n        BLOCK_THREADS       = 128,\n        ITEMS_PER_THREAD    = 7,\n        TILE_SIZE           = BLOCK_THREADS * ITEMS_PER_THREAD,\n    };\n\n//    size_t smem = 1024 * 16;\n    size_t smem = 1024 * 0;\n\n    unsigned int nonzero_blocks = (params.num_nonzeros + TILE_SIZE - 1) / TILE_SIZE;\n    unsigned int row_blocks = (params.num_rows + TILE_SIZE - 1) / TILE_SIZE;\n    unsigned int blocks = std::max(nonzero_blocks, row_blocks);\n\n    typedef TexRefInputIterator<ValueT, 1234, int> TexItr;\n    TexItr x_itr;\n    CubDebugExit(x_itr.BindTexture(params.d_vector_x));\n\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get device SM version\n    int sm_version;\n    CubDebugExit(SmVersion(sm_version, device_ordinal));\n\n    void (*kernel)(SpmvParams<ValueT, OffsetT>, TexItr) = NonZeroIoKernel<BLOCK_THREADS, ITEMS_PER_THREAD>;\n\n\n    int spmv_sm_occupancy;\n    CubDebugExit(MaxSmOccupancy(spmv_sm_occupancy, kernel, BLOCK_THREADS, smem));\n\n    if (!g_quiet)\n        printf(\"NonZeroIoKernel<%d,%d><<<%d, %d>>>, sm occupancy %d\\n\", BLOCK_THREADS, ITEMS_PER_THREAD, blocks, BLOCK_THREADS, spmv_sm_occupancy);\n\n    // Warmup\n    NonZeroIoKernel<BLOCK_THREADS, ITEMS_PER_THREAD><<<blocks, BLOCK_THREADS, smem>>>(params, x_itr);\n\n    // Check for failures\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(SyncStream(0));\n\n    // Timing\n    GpuTimer timer;\n    float elapsed_millis = 0.0;\n    timer.Start();\n    for (int it = 0; it < timing_iterations; ++it)\n    {\n        NonZeroIoKernel<BLOCK_THREADS, ITEMS_PER_THREAD><<<blocks, BLOCK_THREADS, smem>>>(params, x_itr);\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    CubDebugExit(x_itr.UnbindTexture());\n\n    return elapsed_millis / timing_iterations;\n}\n\n\n\n//---------------------------------------------------------------------\n// cuSparse HybMV\n//---------------------------------------------------------------------\n\n/**\n * Run cuSparse HYB SpMV (specialized for fp32)\n */\ntemplate <\n    typename OffsetT>\nfloat TestCusparseHybmv(\n    float*                          vector_y_in,\n    float*                          reference_vector_y_out,\n    SpmvParams<float, OffsetT>&     params,\n    int                             timing_iterations,\n    cusparseHandle_t                cusparse)\n{\n    CpuTimer cpu_timer;\n    cpu_timer.Start();\n\n    // Construct Hyb matrix\n    cusparseMatDescr_t mat_desc;\n    cusparseHybMat_t hyb_desc;\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateMatDescr(&mat_desc));\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateHybMat(&hyb_desc));\n    cusparseStatus_t status = cusparseScsr2hyb(\n        cusparse,\n        params.num_rows, params.num_cols,\n        mat_desc,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        hyb_desc,\n        0,\n        CUSPARSE_HYB_PARTITION_AUTO);\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, status);\n\n    cudaDeviceSynchronize();\n    cpu_timer.Stop();\n    float elapsed_millis = cpu_timer.ElapsedMillis();\n    printf(\"HYB setup ms, %.5f, \", elapsed_millis);\n\n    // Reset input/output vector y\n    CubDebugExit(cudaMemcpy(params.d_vector_y, vector_y_in, sizeof(float) * params.num_rows, cudaMemcpyHostToDevice));\n\n    // Warmup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseShybmv(\n        cusparse,\n        CUSPARSE_OPERATION_NON_TRANSPOSE,\n        &params.alpha, mat_desc,\n        hyb_desc,\n        params.d_vector_x, &params.beta, params.d_vector_y));\n\n    if (!g_quiet)\n    {\n        int compare = CompareDeviceResults(reference_vector_y_out, params.d_vector_y, params.num_rows, true, g_verbose);\n        printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Timing\n    elapsed_millis    = 0.0;\n    GpuTimer timer;\n\n    timer.Start();\n    for(int it = 0; it < timing_iterations; ++it)\n    {\n        AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseShybmv(\n            cusparse,\n            CUSPARSE_OPERATION_NON_TRANSPOSE,\n            &params.alpha, mat_desc,\n            hyb_desc,\n            params.d_vector_x, &params.beta, params.d_vector_y));\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    // Cleanup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyHybMat(hyb_desc));\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyMatDescr(mat_desc));\n\n    return elapsed_millis / timing_iterations;\n}\n\n\n/**\n * Run cuSparse HYB SpMV (specialized for fp64)\n */\ntemplate <\n    typename OffsetT>\nfloat TestCusparseHybmv(\n    double*                         vector_y_in,\n    double*                         reference_vector_y_out,\n    SpmvParams<double, OffsetT>&    params,\n    int                             timing_iterations,\n    cusparseHandle_t                cusparse)\n{\n    CpuTimer cpu_timer;\n    cpu_timer.Start();\n\n    // Construct Hyb matrix\n    cusparseMatDescr_t mat_desc;\n    cusparseHybMat_t hyb_desc;\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateMatDescr(&mat_desc));\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateHybMat(&hyb_desc));\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDcsr2hyb(\n        cusparse,\n        params.num_rows, params.num_cols,\n        mat_desc,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        hyb_desc,\n        0,\n        CUSPARSE_HYB_PARTITION_AUTO));\n\n    cudaDeviceSynchronize();\n    cpu_timer.Stop();\n    float elapsed_millis = cpu_timer.ElapsedMillis();\n    printf(\"HYB setup ms, %.5f, \", elapsed_millis);\n\n    // Reset input/output vector y\n    CubDebugExit(cudaMemcpy(params.d_vector_y, vector_y_in, sizeof(float) * params.num_rows, cudaMemcpyHostToDevice));\n\n    // Warmup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDhybmv(\n        cusparse,\n        CUSPARSE_OPERATION_NON_TRANSPOSE,\n        &params.alpha, mat_desc,\n        hyb_desc,\n        params.d_vector_x, &params.beta, params.d_vector_y));\n\n    if (!g_quiet)\n    {\n        int compare = CompareDeviceResults(reference_vector_y_out, params.d_vector_y, params.num_rows, true, g_verbose);\n        printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Timing\n    elapsed_millis    = 0.0;\n    GpuTimer timer;\n\n    timer.Start();\n    for(int it = 0; it < timing_iterations; ++it)\n    {\n        AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDhybmv(\n            cusparse,\n            CUSPARSE_OPERATION_NON_TRANSPOSE,\n            &params.alpha, mat_desc,\n            hyb_desc,\n            params.d_vector_x, &params.beta, params.d_vector_y));\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    // Cleanup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyHybMat(hyb_desc));\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyMatDescr(mat_desc));\n\n    return elapsed_millis / timing_iterations;\n}\n\n\n\n//---------------------------------------------------------------------\n// cuSparse CsrMV\n//---------------------------------------------------------------------\n\n/**\n * Run cuSparse SpMV (specialized for fp32)\n */\ntemplate <\n    typename OffsetT>\nfloat TestCusparseCsrmv(\n    float*                          vector_y_in,\n    float*                          reference_vector_y_out,\n    SpmvParams<float, OffsetT>&     params,\n    int                             timing_iterations,\n    cusparseHandle_t                cusparse)\n{\n    cusparseMatDescr_t desc;\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateMatDescr(&desc));\n\n    // Reset input/output vector y\n    CubDebugExit(cudaMemcpy(params.d_vector_y, vector_y_in, sizeof(float) * params.num_rows, cudaMemcpyHostToDevice));\n\n    // Warmup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseScsrmv(\n        cusparse, CUSPARSE_OPERATION_NON_TRANSPOSE,\n        params.num_rows, params.num_cols, params.num_nonzeros, &params.alpha, desc,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        params.d_vector_x, &params.beta, params.d_vector_y));\n\n    if (!g_quiet)\n    {\n        int compare = CompareDeviceResults(reference_vector_y_out, params.d_vector_y, params.num_rows, true, g_verbose);\n        printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Timing\n    float elapsed_millis    = 0.0;\n    GpuTimer timer;\n\n    timer.Start();\n    for(int it = 0; it < timing_iterations; ++it)\n    {\n        AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseScsrmv(\n            cusparse, CUSPARSE_OPERATION_NON_TRANSPOSE,\n            params.num_rows, params.num_cols, params.num_nonzeros, &params.alpha, desc,\n            params.d_values, params.d_row_end_offsets, params.d_column_indices,\n            params.d_vector_x, &params.beta, params.d_vector_y));\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyMatDescr(desc));\n    return elapsed_millis / timing_iterations;\n}\n\n\n/**\n * Run cuSparse SpMV (specialized for fp64)\n */\ntemplate <\n    typename OffsetT>\nfloat TestCusparseCsrmv(\n    double*                         vector_y_in,\n    double*                         reference_vector_y_out,\n    SpmvParams<double, OffsetT>&    params,\n    int                             timing_iterations,\n    cusparseHandle_t                cusparse)\n{\n    cusparseMatDescr_t desc;\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreateMatDescr(&desc));\n\n    // Reset input/output vector y\n    CubDebugExit(cudaMemcpy(params.d_vector_y, vector_y_in, sizeof(float) * params.num_rows, cudaMemcpyHostToDevice));\n\n    // Warmup\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDcsrmv(\n        cusparse, CUSPARSE_OPERATION_NON_TRANSPOSE,\n        params.num_rows, params.num_cols, params.num_nonzeros, &params.alpha, desc,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        params.d_vector_x, &params.beta, params.d_vector_y));\n\n    if (!g_quiet)\n    {\n        int compare = CompareDeviceResults(reference_vector_y_out, params.d_vector_y, params.num_rows, true, g_verbose);\n        printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Timing\n    float elapsed_millis = 0.0;\n    GpuTimer timer;\n    timer.Start();\n    for(int it = 0; it < timing_iterations; ++it)\n    {\n        AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDcsrmv(\n            cusparse, CUSPARSE_OPERATION_NON_TRANSPOSE,\n            params.num_rows, params.num_cols, params.num_nonzeros, &params.alpha, desc,\n            params.d_values, params.d_row_end_offsets, params.d_column_indices,\n            params.d_vector_x, &params.beta, params.d_vector_y));\n\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseDestroyMatDescr(desc));\n    return elapsed_millis / timing_iterations;\n}\n\n//---------------------------------------------------------------------\n// GPU Merge-based SpMV\n//---------------------------------------------------------------------\n\n/**\n * Run CUB SpMV\n */\ntemplate <\n    typename ValueT,\n    typename OffsetT>\nfloat TestGpuMergeCsrmv(\n    ValueT*                         vector_y_in,\n    ValueT*                         reference_vector_y_out,\n    SpmvParams<ValueT, OffsetT>&    params,\n    int                             timing_iterations)\n{\n    // Allocate temporary storage\n    size_t temp_storage_bytes = 0;\n    void *d_temp_storage = NULL;\n\n    // Get amount of temporary storage needed\n    CubDebugExit(DeviceSpmv::CsrMV(\n        d_temp_storage, temp_storage_bytes,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        params.d_vector_x, params.d_vector_y,\n        params.num_rows, params.num_cols, params.num_nonzeros,\n// params.alpha, params.beta,\n        (cudaStream_t) 0, false));\n\n    // Allocate\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Reset input/output vector y\n    CubDebugExit(cudaMemcpy(params.d_vector_y, vector_y_in, sizeof(ValueT) * params.num_rows, cudaMemcpyHostToDevice));\n\n    // Warmup\n    CubDebugExit(DeviceSpmv::CsrMV(\n        d_temp_storage, temp_storage_bytes,\n        params.d_values, params.d_row_end_offsets, params.d_column_indices,\n        params.d_vector_x, params.d_vector_y,\n        params.num_rows, params.num_cols, params.num_nonzeros, \n// params.alpha, params.beta,\n        (cudaStream_t) 0, !g_quiet));\n\n    if (!g_quiet)\n    {\n        int compare = CompareDeviceResults(reference_vector_y_out, params.d_vector_y, params.num_rows, true, g_verbose);\n        printf(\"\\t%s\\n\", compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Timing\n    GpuTimer timer;\n    float elapsed_millis = 0.0;\n\n    timer.Start();\n    for(int it = 0; it < timing_iterations; ++it)\n    {\n        CubDebugExit(DeviceSpmv::CsrMV(\n            d_temp_storage, temp_storage_bytes,\n            params.d_values, params.d_row_end_offsets, params.d_column_indices,\n            params.d_vector_x, params.d_vector_y,\n            params.num_rows, params.num_cols, params.num_nonzeros, \n// params.alpha, params.beta,\n            (cudaStream_t) 0, false));\n    }\n    timer.Stop();\n    elapsed_millis += timer.ElapsedMillis();\n\n    return elapsed_millis / timing_iterations;\n}\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n/**\n * Display perf\n */\ntemplate <typename ValueT, typename OffsetT>\nvoid DisplayPerf(\n    float                           device_giga_bandwidth,\n    double                          avg_millis,\n    CsrMatrix<ValueT, OffsetT>&     csr_matrix)\n{\n    double nz_throughput, effective_bandwidth;\n    size_t total_bytes = (csr_matrix.num_nonzeros * (sizeof(ValueT) * 2 + sizeof(OffsetT))) +\n        (csr_matrix.num_rows) * (sizeof(OffsetT) + sizeof(ValueT));\n\n    nz_throughput       = double(csr_matrix.num_nonzeros) / avg_millis / 1.0e6;\n    effective_bandwidth = double(total_bytes) / avg_millis / 1.0e6;\n\n    if (!g_quiet)\n        printf(\"fp%d: %.4f avg ms, %.5f gflops, %.3lf effective GB/s (%.2f%% peak)\\n\",\n            sizeof(ValueT) * 8,\n            avg_millis,\n            2 * nz_throughput,\n            effective_bandwidth,\n            effective_bandwidth / device_giga_bandwidth * 100);\n    else\n        printf(\"%.5f, %.6f, %.3lf, %.2f%%, \",\n            avg_millis,\n            2 * nz_throughput,\n            effective_bandwidth,\n            effective_bandwidth / device_giga_bandwidth * 100);\n\n    fflush(stdout);\n}\n\n\n\n/**\n * Run tests\n */\ntemplate <\n    typename ValueT,\n    typename OffsetT>\nvoid RunTest(\n    bool                        rcm_relabel,\n    ValueT                      alpha,\n    ValueT                      beta,\n    CooMatrix<ValueT, OffsetT>& coo_matrix,\n    int                         timing_iterations,\n    CommandLineArgs&            args)\n{\n    // Adaptive timing iterations: run 16 billion nonzeros through\n    if (timing_iterations == -1)\n        timing_iterations = std::min(50000ull, std::max(100ull, ((16ull << 30) / coo_matrix.num_nonzeros)));\n\n    if (!g_quiet)\n        printf(\"\\t%d timing iterations\\n\", timing_iterations);\n\n    // Convert to CSR\n    CsrMatrix<ValueT, OffsetT> csr_matrix;\n    csr_matrix.FromCoo(coo_matrix);\n    if (!args.CheckCmdLineFlag(\"csrmv\"))\n        coo_matrix.Clear();\n\n    // Relabel\n    if (rcm_relabel)\n    {\n        if (!g_quiet)\n        {\n            csr_matrix.Stats().Display();\n            printf(\"\\n\");\n            csr_matrix.DisplayHistogram();\n            printf(\"\\n\");\n            if (g_verbose2)\n                csr_matrix.Display();\n            printf(\"\\n\");\n        }\n\n        RcmRelabel(csr_matrix, !g_quiet);\n\n        if (!g_quiet) printf(\"\\n\");\n    }\n\n    // Display matrix info\n    csr_matrix.Stats().Display(!g_quiet);\n    if (!g_quiet)\n    {\n        printf(\"\\n\");\n        csr_matrix.DisplayHistogram();\n        printf(\"\\n\");\n        if (g_verbose2)\n            csr_matrix.Display();\n        printf(\"\\n\");\n    }\n    fflush(stdout);\n\n    // Allocate input and output vectors\n    ValueT* vector_x        = new ValueT[csr_matrix.num_cols];\n    ValueT* vector_y_in     = new ValueT[csr_matrix.num_rows];\n    ValueT* vector_y_out    = new ValueT[csr_matrix.num_rows];\n\n    for (int col = 0; col < csr_matrix.num_cols; ++col)\n        vector_x[col] = 1.0;\n\n    for (int row = 0; row < csr_matrix.num_rows; ++row)\n        vector_y_in[row] = 1.0;\n\n    // Compute reference answer\n    SpmvGold(csr_matrix, vector_x, vector_y_in, vector_y_out, alpha, beta);\n\n    float avg_millis;\n\n    if (g_quiet) {\n        printf(\"%s, %s, \", args.deviceProp.name, (sizeof(ValueT) > 4) ? \"fp64\" : \"fp32\"); fflush(stdout);\n    }\n\n    // Get GPU device bandwidth (GB/s)\n    float device_giga_bandwidth = args.device_giga_bandwidth;\n\n    // Allocate and initialize GPU problem\n    SpmvParams<ValueT, OffsetT> params;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void **) &params.d_values,          sizeof(ValueT) * csr_matrix.num_nonzeros));\n    CubDebugExit(g_allocator.DeviceAllocate((void **) &params.d_row_end_offsets, sizeof(OffsetT) * (csr_matrix.num_rows + 1)));\n    CubDebugExit(g_allocator.DeviceAllocate((void **) &params.d_column_indices,  sizeof(OffsetT) * csr_matrix.num_nonzeros));\n    CubDebugExit(g_allocator.DeviceAllocate((void **) &params.d_vector_x,        sizeof(ValueT) * csr_matrix.num_cols));\n    CubDebugExit(g_allocator.DeviceAllocate((void **) &params.d_vector_y,        sizeof(ValueT) * csr_matrix.num_rows));\n    params.num_rows         = csr_matrix.num_rows;\n    params.num_cols         = csr_matrix.num_cols;\n    params.num_nonzeros     = csr_matrix.num_nonzeros;\n    params.alpha            = alpha;\n    params.beta             = beta;\n\n    CubDebugExit(cudaMemcpy(params.d_values,            csr_matrix.values,          sizeof(ValueT) * csr_matrix.num_nonzeros, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(params.d_row_end_offsets,   csr_matrix.row_offsets,     sizeof(OffsetT) * (csr_matrix.num_rows + 1), cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(params.d_column_indices,    csr_matrix.column_indices,  sizeof(OffsetT) * csr_matrix.num_nonzeros, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(params.d_vector_x,          vector_x,                   sizeof(ValueT) * csr_matrix.num_cols, cudaMemcpyHostToDevice));\n\n    if (!g_quiet) printf(\"\\n\\n\");\n    printf(\"GPU CSR I/O Prox, \"); fflush(stdout);\n    avg_millis = TestGpuCsrIoProxy(params, timing_iterations);\n    DisplayPerf(device_giga_bandwidth, avg_millis, csr_matrix);\n\n    if (args.CheckCmdLineFlag(\"csrmv\"))\n    {\n        if (!g_quiet) printf(\"\\n\\n\");\n        printf(\"CUB, \"); fflush(stdout);\n        avg_millis = TestGpuMergeCsrmv(vector_y_in, vector_y_out, params, timing_iterations);\n        DisplayPerf(device_giga_bandwidth, avg_millis, csr_matrix);\n    }\n\n    // Initialize cuSparse\n    cusparseHandle_t cusparse;\n    AssertEquals(CUSPARSE_STATUS_SUCCESS, cusparseCreate(&cusparse));\n\n    if (args.CheckCmdLineFlag(\"csrmv\"))\n    {\n        if (!g_quiet) printf(\"\\n\\n\");\n        printf(\"Cusparse CsrMV, \"); fflush(stdout);\n        avg_millis = TestCusparseCsrmv(vector_y_in, vector_y_out, params, timing_iterations, cusparse);\n        DisplayPerf(device_giga_bandwidth, avg_millis, csr_matrix);\n    }\n\n    if (args.CheckCmdLineFlag(\"hybmv\"))\n    {\n        if (!g_quiet) printf(\"\\n\\n\");\n        printf(\"Cusparse HybMV, \"); fflush(stdout);\n\n        avg_millis = TestCusparseHybmv(vector_y_in, vector_y_out, params, timing_iterations, cusparse);\n        DisplayPerf(device_giga_bandwidth, avg_millis, csr_matrix);\n    }\n\n\n    // Cleanup\n    if (params.d_values)            CubDebugExit(g_allocator.DeviceFree(params.d_values));\n    if (params.d_row_end_offsets)   CubDebugExit(g_allocator.DeviceFree(params.d_row_end_offsets));\n    if (params.d_column_indices)    CubDebugExit(g_allocator.DeviceFree(params.d_column_indices));\n    if (params.d_vector_x)          CubDebugExit(g_allocator.DeviceFree(params.d_vector_x));\n    if (params.d_vector_y)          CubDebugExit(g_allocator.DeviceFree(params.d_vector_y));\n\n    if (vector_x)                   delete[] vector_x;\n    if (vector_y_in)                delete[] vector_y_in;\n    if (vector_y_out)               delete[] vector_y_out;\n}\n\n/**\n * Run tests\n */\ntemplate <\n    typename ValueT,\n    typename OffsetT>\nvoid RunTests(\n    bool                rcm_relabel,\n    ValueT              alpha,\n    ValueT              beta,\n    const std::string&  mtx_filename,\n    int                 grid2d,\n    int                 grid3d,\n    int                 wheel,\n    int                 dense,\n    int                 timing_iterations,\n    CommandLineArgs&    args)\n{\n    // Initialize matrix in COO form\n    CooMatrix<ValueT, OffsetT> coo_matrix;\n\n    if (!mtx_filename.empty())\n    {\n        // Parse matrix market file\n        printf(\"%s, \", mtx_filename.c_str()); fflush(stdout);\n        coo_matrix.InitMarket(mtx_filename, 1.0, !g_quiet);\n\n        if ((coo_matrix.num_rows == 1) || (coo_matrix.num_cols == 1) || (coo_matrix.num_nonzeros == 1))\n        {\n            if (!g_quiet) printf(\"Trivial dataset\\n\");\n            exit(0);\n        }\n    }\n    else if (grid2d > 0)\n    {\n        // Generate 2D lattice\n        printf(\"grid2d_%d, \", grid2d); fflush(stdout);\n        coo_matrix.InitGrid2d(grid2d, false);\n    }\n    else if (grid3d > 0)\n    {\n        // Generate 3D lattice\n        printf(\"grid3d_%d, \", grid3d); fflush(stdout);\n        coo_matrix.InitGrid3d(grid3d, false);\n    }\n    else if (wheel > 0)\n    {\n        // Generate wheel graph\n        printf(\"wheel_%d, \", grid2d); fflush(stdout);\n        coo_matrix.InitWheel(wheel);\n    }\n    else if (dense > 0)\n    {\n        // Generate dense graph\n        OffsetT size = 1 << 24; // 16M nnz\n        args.GetCmdLineArgument(\"size\", size);\n\n        OffsetT rows = size / dense;\n        printf(\"dense_%d_x_%d, \", rows, dense); fflush(stdout);\n        coo_matrix.InitDense(rows, dense);\n    }\n    else\n    {\n        fprintf(stderr, \"No graph type specified.\\n\");\n        exit(1);\n    }\n\n    RunTest(\n        rcm_relabel,\n        alpha,\n        beta,\n        coo_matrix,\n        timing_iterations,\n        args);\n}\n\n\n\n/**\n * Main\n */\nint main(int argc, char **argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\n            \"%s \"\n            \"[--csrmv | --hybmv | --bsrmv ] \"\n            \"[--device=<device-id>] \"\n            \"[--quiet] \"\n            \"[--v] \"\n            \"[--i=<timing iterations>] \"\n            \"[--fp64] \"\n            \"[--rcm] \"\n            \"[--alpha=<alpha scalar (default: 1.0)>] \"\n            \"[--beta=<beta scalar (default: 0.0)>] \"\n            \"\\n\\t\"\n                \"--mtx=<matrix market file> \"\n            \"\\n\\t\"\n                \"--dense=<cols>\"\n            \"\\n\\t\"\n                \"--grid2d=<width>\"\n            \"\\n\\t\"\n                \"--grid3d=<width>\"\n            \"\\n\\t\"\n                \"--wheel=<spokes>\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    bool                fp64;\n    bool                rcm_relabel;\n    std::string         mtx_filename;\n    int                 grid2d              = -1;\n    int                 grid3d              = -1;\n    int                 wheel               = -1;\n    int                 dense               = -1;\n    int                 timing_iterations   = -1;\n    float               alpha               = 1.0;\n    float               beta                = 0.0;\n\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_verbose2 = args.CheckCmdLineFlag(\"v2\");\n    g_quiet = args.CheckCmdLineFlag(\"quiet\");\n    fp64 = args.CheckCmdLineFlag(\"fp64\");\n    rcm_relabel = args.CheckCmdLineFlag(\"rcm\");\n    args.GetCmdLineArgument(\"i\", timing_iterations);\n    args.GetCmdLineArgument(\"mtx\", mtx_filename);\n    args.GetCmdLineArgument(\"grid2d\", grid2d);\n    args.GetCmdLineArgument(\"grid3d\", grid3d);\n    args.GetCmdLineArgument(\"wheel\", wheel);\n    args.GetCmdLineArgument(\"dense\", dense);\n    args.GetCmdLineArgument(\"alpha\", alpha);\n    args.GetCmdLineArgument(\"beta\", beta);\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Run test(s)\n    if (fp64)\n    {\n        RunTests<double, int>(rcm_relabel, alpha, beta, mtx_filename, grid2d, grid3d, wheel, dense, timing_iterations, args);\n    }\n    else\n    {\n        RunTests<float, int>(rcm_relabel, alpha, beta, mtx_filename, grid2d, grid3d, wheel, dense, timing_iterations, args);\n    }\n\n    CubDebugExit(cudaDeviceSynchronize());\n    printf(\"\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "external/cub/experimental/spmv_script.sh",
    "content": "#!/bin/bash\n\nfor i in 1 2 4 8 16 32 64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 524288 1048576 2097152 4194304 8388608 16777216\ndo\n\techo `date`, `$1 --dense=$i $2 $3 $4 $5 $6 $7`\ndone\n\necho\necho\n\nfor i in `ls /home/dumerrill/graphs/spmv/*.mtx`\ndo\n    if [[ ( \"`head -n 50 $i | grep complex`\" = \"\" ) && ( \"`head -n 50 $i | grep array`\" = \"\" ) ]] \n    then\n    \techo `date`, `$1 --mtx=$i $2 $3 $4 $5 $6 $7 2>/dev/null`\n    fi\ndone\n\necho\necho\n\nfor i in `ls /scratch/dumerrill/graphs/mtx/*.mtx`\n#for i in `ls /cygdrive/w/Dev/UFget/mtx/*.mtx`\ndo \n    if [[ ( \"`head -n 50 $i | grep complex`\" = \"\" ) && ( \"`head -n 50 $i | grep array`\" = \"\" ) ]] \n    then\n    \techo `date`, `$1 --mtx=$i $2 $3 $4 $5 $6 $7 2>/dev/null`\n    fi\ndone \n\n"
  },
  {
    "path": "external/cub/test/.gitignore",
    "content": "/bin\n/link_main.obj\n/dummy/\n"
  },
  {
    "path": "external/cub/test/Makefile",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n\n\n#-------------------------------------------------------------------------------\n#\n# Makefile usage\n#\n# make <target> [sm=<XXX,...>] [cdp=<0|1>] [force32=<0|1>] [abi=<0|1>] [open64=<0|1>] [verbose=<0|1>] [keep=<0|1>] [quicktest=<0|1>] [quickertest=<0|1>]\n#\n#-------------------------------------------------------------------------------\n\ninclude ../common.mk \n \n#-------------------------------------------------------------------------------\n# Commandline Options\n#-------------------------------------------------------------------------------\n\n# Testing mode option (quick/thorough)\nifeq ($(quickertest), 1)\n\tNVCCFLAGS += -DQUICKER_TEST\n\tTEST_SUFFIX = quicker\nelse ifeq ($(quicktest), 1)\n\tNVCCFLAGS += -DQUICK_TEST\n\tTEST_SUFFIX = quick\nelse \n\tTEST_SUFFIX = thorough\n\tNPPI = \nendif\n\n\n# CUDA memcheck (enabled by default) \nifeq ($(memcheck), 0)\n\tMEMCHECK = \nelse \n\tMEMCHECK = cuda-memcheck\nendif\n\n\n#-------------------------------------------------------------------------------\n# Compiler and compilation platform\n#-------------------------------------------------------------------------------\n\n# Includes\nINC += -I$(CUB_DIR) -I$(CUB_DIR)test \n\n# Suffix to append to each binary\nSUFFIX = $(BIN_SUFFIX)_$(TEST_SUFFIX)\n\n# Define test arch\nDEFINES += -DTEST_ARCH=$(TEST_ARCH)\n\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nrwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nDEPS =\t\t\t\t$(CUB_DEPS) \\\n\t\t\t\t\t$(CUB_DIR)test/Makefile \\\n\t\t\t\t\t$(CUB_DIR)test/test_util.h \\\n\t\t\t\t\t$(CUB_DIR)test/mersenne.h \\\n\nBLOCK_REDUCE = \t\ttest_block_reduce_raking \\\n\t \t\t\t\ttest_block_reduce_warp_reductions\t\t\n\n\nBLOCK_SCAN = \t\ttest_block_scan_raking \\\n\t \t\t\t\ttest_block_scan_raking_memoize \\\n\t \t\t\t\ttest_block_scan_warp_scans\t\t\n\n\nBLOCK_RADIX_SORT = \ttest_block_radix_sort_keys \\\n\t \t\t\t\ttest_block_radix_sort_pairs\t\n\n\t\t\nALL = \t\t\t\tlink \\\n\t \t\t\t\ttest_iterator \\\n\t \t\t\t\ttest_allocator \\\n\t \t\t\t\ttest_warp_scan \\\n\t \t\t\t\ttest_warp_reduce \\\n\t \t\t\t\t$(BLOCK_REDUCE) \\\n\t \t\t\t\t$(BLOCK_SCAN) \\\n\t \t\t\t\t$(BLOCK_RADIX_SORT) \\\n\t \t\t\t\ttest_block_load_store \\\n\t \t\t\t\ttest_block_histogram \\\n\t\t\t\t \ttest_device_reduce \\\n\t\t\t \t\ttest_device_histogram \\\n\t\t\t \t\ttest_device_scan \\\n\t\t\t \t\ttest_device_radix_sort \\\n\t\t\t\t\ttest_device_reduce_by_key\\\n\t\t\t\t\ttest_device_run_length_encode\\\n\t\t \t\t\ttest_device_select_unique \\\n\t\t\t\t\ttest_device_select_if \n\t\t\n#\t \ttest_grid_barrier \\\t\tfails on sm110\n#\t \ttest_device_seg_reduce\n\t\t\n\n\n#-------------------------------------------------------------------------------\n# make default\n#-------------------------------------------------------------------------------\n\ndefault:\n\n\n#-------------------------------------------------------------------------------\n# make clean\n#-------------------------------------------------------------------------------\n\nclean :\n\trm -f bin/*$(CPU_ARCH_SUFFIX)* \n\trm -f *.i* *.cubin *.cu.c *.cudafe* *.fatbin.c *.ptx *.hash *.cu.cpp *.o\n\n\n#-------------------------------------------------------------------------------\n# make all\n#-------------------------------------------------------------------------------\n\nall : $(ALL)\n\n\n#-------------------------------------------------------------------------------\n# make run\n#-------------------------------------------------------------------------------\n\nrun : \n\tfor i in $(ALL); do $(MEMCHECK) ./bin/$${i}_$(SUFFIX) --device=$(device) || exit 1; done\n\nrun_block_reduce : \n\tfor i in $(BLOCK_REDUCE); do $(MEMCHECK) ./bin/$${i}_$(SUFFIX) --device=$(device) || exit 1; done\n\nrun_block_scan : \n\tfor i in $(BLOCK_SCAN); do $(MEMCHECK) ./bin/$${i}_$(SUFFIX) --device=$(device) || exit 1; done\n\nrun_block_radix_sort : \n\tfor i in $(BLOCK_RADIX_SORT); do $(MEMCHECK) ./bin/$${i}_$(SUFFIX) --device=$(device) || exit 1; done\n\n\n\n#-------------------------------------------------------------------------------\n# make link\n#-------------------------------------------------------------------------------\n\nlink : bin/link_$(SUFFIX)\n\nbin/link_$(SUFFIX) : link_a.cu link_b.cu link_main.cpp $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(DEFINES) $(SM_TARGETS) link_a.cu -c -o bin/link_a.obj\n\t$(NVCC) $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(DEFINES) $(SM_TARGETS) link_b.cu -c -o bin/link_b.obj\n\t$(NVCC) $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(DEFINES) $(SM_TARGETS) link_main.cpp bin/link_a.obj bin/link_b.obj -o bin/link_$(SUFFIX)\n\n\n#-------------------------------------------------------------------------------\n# make test_iterator \n#-------------------------------------------------------------------------------\n\ntest_iterator: bin/test_iterator_$(SUFFIX)\n\nbin/test_iterator_$(SUFFIX) : test_iterator.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_iterator_$(SUFFIX) test_iterator.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_allocator \n#-------------------------------------------------------------------------------\n\ntest_allocator: bin/test_allocator_$(SUFFIX)\n\nbin/test_allocator_$(SUFFIX) : test_allocator.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_allocator_$(SUFFIX) test_allocator.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\t\n\t\n#-------------------------------------------------------------------------------\n# make test_grid_barrier \n#-------------------------------------------------------------------------------\n\ntest_grid_barrier: bin/test_grid_barrier_$(SUFFIX)\n\nbin/test_grid_barrier_$(SUFFIX) : test_grid_barrier.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_grid_barrier_$(SUFFIX) test_grid_barrier.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\t\n\n#-------------------------------------------------------------------------------\n# make test_warp_scan \n#-------------------------------------------------------------------------------\n\ntest_warp_scan: bin/test_warp_scan_$(SUFFIX)\n\nbin/test_warp_scan_$(SUFFIX) : test_warp_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_warp_scan_$(SUFFIX) test_warp_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_warp_reduce \n#-------------------------------------------------------------------------------\n\ntest_warp_reduce: bin/test_warp_reduce_$(SUFFIX)\n\nbin/test_warp_reduce_$(SUFFIX) : test_warp_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_warp_reduce_$(SUFFIX) test_warp_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_reduce_raking\n#-------------------------------------------------------------------------------\n\ntest_block_reduce_raking: bin/test_block_reduce_raking_$(SUFFIX)\n\nbin/test_block_reduce_raking_$(SUFFIX) : test_block_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_RAKING $(SM_TARGETS) -o bin/test_block_reduce_raking_$(SUFFIX) test_block_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_reduce_warp_reductions \n#-------------------------------------------------------------------------------\n\ntest_block_reduce_warp_reductions: bin/test_block_reduce_warp_reductions_$(SUFFIX)\n\nbin/test_block_reduce_warp_reductions_$(SUFFIX) : test_block_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_WARP_REDUCTIONS $(SM_TARGETS) -o bin/test_block_reduce_warp_reductions_$(SUFFIX) test_block_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_reduce \n#-------------------------------------------------------------------------------\n\ntest_block_reduce: $(BLOCK_REDUCE)\n\n\n#-------------------------------------------------------------------------------\n# make test_block_scan_raking\n#-------------------------------------------------------------------------------\n\ntest_block_scan_raking: bin/test_block_scan_raking_$(SUFFIX)\n\nbin/test_block_scan_raking_$(SUFFIX) : test_block_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_RAKING $(SM_TARGETS) -o bin/test_block_scan_raking_$(SUFFIX) test_block_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_scan_raking_memoize\n#-------------------------------------------------------------------------------\n\ntest_block_scan_raking_memoize: bin/test_block_scan_raking_memoize_$(SUFFIX)\n\nbin/test_block_scan_raking_memoize_$(SUFFIX) : test_block_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_RAKING_MEMOIZE $(SM_TARGETS) -o bin/test_block_scan_raking_memoize_$(SUFFIX) test_block_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_scan_warp_scans\n#-------------------------------------------------------------------------------\n\ntest_block_scan_warp_scans: bin/test_block_scan_warp_scans_$(SUFFIX)\n\nbin/test_block_scan_warp_scans_$(SUFFIX) : test_block_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_WARP_SCANS $(SM_TARGETS) -o bin/test_block_scan_warp_scans_$(SUFFIX) test_block_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3  \n\n\n#-------------------------------------------------------------------------------\n# make test_block_scan \n#-------------------------------------------------------------------------------\n\ntest_block_scan: $(BLOCK_SCAN)\n\n\n#-------------------------------------------------------------------------------\n# make test_block_load_store \n#-------------------------------------------------------------------------------\n\ntest_block_load_store: bin/test_block_load_store_$(SUFFIX)\n\nbin/test_block_load_store_$(SUFFIX) : test_block_load_store.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_block_load_store_$(SUFFIX) test_block_load_store.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\t\n\t\n#-------------------------------------------------------------------------------\n# make test_block_radix_sort_keys \n#-------------------------------------------------------------------------------\n\ntest_block_radix_sort_keys: bin/test_block_radix_sort_keys_$(SUFFIX)\n\nbin/test_block_radix_sort_keys_$(SUFFIX) : test_block_radix_sort.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) -DTEST_KEYS_ONLY $(SM_TARGETS) -o bin/test_block_radix_sort_keys_$(SUFFIX) test_block_radix_sort.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make test_block_radix_sort_pairs \n#-------------------------------------------------------------------------------\n\ntest_block_radix_sort_pairs: bin/test_block_radix_sort_pairs_$(SUFFIX)\n\nbin/test_block_radix_sort_pairs_$(SUFFIX) : test_block_radix_sort.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_block_radix_sort_pairs_$(SUFFIX) test_block_radix_sort.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_block_radix_sort\n#-------------------------------------------------------------------------------\n\ntest_block_radix_sort : $(BLOCK_RADIX_SORT)\n\n\n#-------------------------------------------------------------------------------\n# make test_block_histogram \n#-------------------------------------------------------------------------------\n\ntest_block_histogram: bin/test_block_histogram_$(SUFFIX)\n\nbin/test_block_histogram_$(SUFFIX) : test_block_histogram.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_block_histogram_$(SUFFIX) test_block_histogram.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_reduce\n#-------------------------------------------------------------------------------\n\ntest_device_reduce: bin/test_device_reduce_$(SUFFIX)\n\nbin/test_device_reduce_$(SUFFIX) : test_device_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_reduce_$(SUFFIX) test_device_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_histogram\n#-------------------------------------------------------------------------------\n\ntest_device_histogram: bin/test_device_histogram_$(SUFFIX)\n\nbin/test_device_histogram_$(SUFFIX) : test_device_histogram.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_histogram_$(SUFFIX) test_device_histogram.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) $(NPPI) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_scan\n#-------------------------------------------------------------------------------\n\ntest_device_scan: bin/test_device_scan_$(SUFFIX)\n\nbin/test_device_scan_$(SUFFIX) : test_device_scan.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_scan_$(SUFFIX) test_device_scan.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_radix_sort\n#-------------------------------------------------------------------------------\n\ntest_device_radix_sort: bin/test_device_radix_sort_$(SUFFIX)\n\nbin/test_device_radix_sort_$(SUFFIX) : test_device_radix_sort.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_radix_sort_$(SUFFIX) test_device_radix_sort.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_select_unique\n#-------------------------------------------------------------------------------\n\ntest_device_select_unique: bin/test_device_select_unique_$(SUFFIX)\n\nbin/test_device_select_unique_$(SUFFIX) : test_device_select_unique.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_select_unique_$(SUFFIX) test_device_select_unique.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n#-------------------------------------------------------------------------------\n# make test_device_select_if\n#-------------------------------------------------------------------------------\n\ntest_device_select_if: bin/test_device_select_if_$(SUFFIX)\n\nbin/test_device_select_if_$(SUFFIX) : test_device_select_if.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_select_if_$(SUFFIX) test_device_select_if.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make test_device_reduce_by_key\n#-------------------------------------------------------------------------------\n\ntest_device_reduce_by_key: bin/test_device_reduce_by_key_$(SUFFIX)\n\nbin/test_device_reduce_by_key_$(SUFFIX) : test_device_reduce_by_key.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_reduce_by_key_$(SUFFIX) test_device_reduce_by_key.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n#-------------------------------------------------------------------------------\n# make test_device_run_length_encode\n#-------------------------------------------------------------------------------\n\ntest_device_run_length_encode: bin/test_device_run_length_encode_$(SUFFIX)\n\nbin/test_device_run_length_encode_$(SUFFIX) : test_device_run_length_encode.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_run_length_encode_$(SUFFIX) test_device_run_length_encode.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n\n\n#-------------------------------------------------------------------------------\n# make test_device_seg_reduce\n#-------------------------------------------------------------------------------\n#\n#test_device_seg_reduce: bin/test_device_seg_reduce_$(SUFFIX)\n#\n#bin/test_device_seg_reduce_$(SUFFIX) : test_device_seg_reduce.cu $(DEPS)\n#\tmkdir -p bin\n#\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/test_device_seg_reduce_$(SUFFIX) test_device_seg_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3\n\n\n"
  },
  {
    "path": "external/cub/test/link_a.cu",
    "content": "#include <cub/cub.cuh>\n\nvoid a()\n{\n    printf(\"a() called\\n\");\n\n    cub::DoubleBuffer<unsigned int>     d_keys;\n    cub::DoubleBuffer<cub::NullType>    d_values;\n    size_t                              temp_storage_bytes = 0;\n    cub::DeviceRadixSort::SortPairs(NULL, temp_storage_bytes, d_keys, d_values, 1024);\n}\n"
  },
  {
    "path": "external/cub/test/link_b.cu",
    "content": "#include <cub/cub.cuh>\n\nvoid b()\n{\n    printf(\"b() called\\n\");\n\n    cub::DoubleBuffer<unsigned int>     d_keys;\n    cub::DoubleBuffer<cub::NullType>    d_values;\n    size_t                              temp_storage_bytes = 0;\n    cub::DeviceRadixSort::SortPairs(NULL, temp_storage_bytes, d_keys, d_values, 1024);\n}\n"
  },
  {
    "path": "external/cub/test/link_main.cpp",
    "content": "#include <stdio.h>\n\nextern void a();\nextern void b();\n\nint main()\n{\n    printf(\"hello world\\n\");\n    return 0;\n}\n"
  },
  {
    "path": "external/cub/test/mersenne.h",
    "content": "/*\n A C-program for MT19937, with initialization improved 2002/1/26.\n Coded by Takuji Nishimura and Makoto Matsumoto.\n\n Before using, initialize the state by using init_genrand(seed)\n or init_by_array(init_key, key_length).\n\n Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n\n 1. Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n 2. Redistributions in binary form must reproduce the above copyright\n notice, this list of conditions and the following disclaimer in the\n documentation and/or other materials provided with the distribution.\n\n 3. The names of its contributors may not be used to endorse or promote\n products derived from this software without specific prior written\n permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n A PARTICAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n Any feedback is very welcome.\n http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html\n email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)\n */\n\n#include <stdio.h>\n\nnamespace mersenne {\n\n/* Period parameters */\nconst unsigned int N          = 624;\nconst unsigned int M          = 397;\nconst unsigned int MATRIX_A   = 0x9908b0df; /* constant vector a */\nconst unsigned int UPPER_MASK = 0x80000000; /* most significant w-r bits */\nconst unsigned int LOWER_MASK = 0x7fffffff; /* least significant r bits */\n\nstatic unsigned int mt[N];  /* the array for the state vector  */\nstatic int mti = N + 1;     /* mti==N+1 means mt[N] is not initialized */\n\n/* initializes mt[N] with a seed */\nvoid init_genrand(unsigned int s)\n{\n    mt[0] = s & 0xffffffff;\n    for (mti = 1; mti < N; mti++)\n    {\n        mt[mti] = (1812433253 * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);\n\n        /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for mtiplier. */\n        /* In the previous versions, MSBs of the seed affect   */\n        /* only MSBs of the array mt[].                        */\n        /* 2002/01/09 modified by Makoto Matsumoto             */\n\n        mt[mti] &= 0xffffffff;\n        /* for >32 bit machines */\n    }\n}\n\n/* initialize by an array with array-length */\n/* init_key is the array for initializing keys */\n/* key_length is its length */\n/* slight change for C++, 2004/2/26 */\nvoid init_by_array(unsigned int init_key[], int key_length)\n{\n    int i, j, k;\n    init_genrand(19650218);\n    i = 1;\n    j = 0;\n    k = (N > key_length ? N : key_length);\n    for (; k; k--)\n    {\n        mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525))\n            + init_key[j] + j;  /* non linear */\n        mt[i] &= 0xffffffff;    /* for WORDSIZE > 32 machines */\n        i++;\n        j++;\n        if (i >= N)\n        {\n            mt[0] = mt[N - 1];\n            i = 1;\n        }\n        if (j >= key_length) j = 0;\n    }\n    for (k = N - 1; k; k--)\n    {\n        mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941)) - i; /* non linear */\n        mt[i] &= 0xffffffff; /* for WORDSIZE > 32 machines */\n        i++;\n        if (i >= N)\n        {\n            mt[0] = mt[N - 1];\n            i = 1;\n        }\n    }\n\n    mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */\n}\n\n/* generates a random number on [0,0xffffffff]-interval */\nunsigned int genrand_int32(void)\n{\n    unsigned int y;\n    static unsigned int mag01[2] = { 0x0, MATRIX_A };\n\n    /* mag01[x] = x * MATRIX_A  for x=0,1 */\n\n    if (mti >= N)\n    { /* generate N words at one time */\n        int kk;\n\n        if (mti == N + 1) /* if init_genrand() has not been called, */\n        init_genrand(5489); /* a defat initial seed is used */\n\n        for (kk = 0; kk < N - M; kk++)\n        {\n            y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);\n            mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1];\n        }\n        for (; kk < N - 1; kk++)\n        {\n            y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);\n            mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1];\n        }\n        y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);\n        mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1];\n\n        mti = 0;\n    }\n\n    y = mt[mti++];\n\n    /* Tempering */\n    y ^= (y >> 11);\n    y ^= (y << 7) & 0x9d2c5680;\n    y ^= (y << 15) & 0xefc60000;\n    y ^= (y >> 18);\n\n    return y;\n}\n\n\n\n} // namespace mersenne\n"
  },
  {
    "path": "external/cub/test/test_allocator.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test evaluation for caching allocator of device memory\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/util_allocator.cuh>\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>]\"\n            \"[--bytes=<timing bytes>]\"\n            \"[--i=<timing iterations>]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n#if (CUB_PTX_ARCH == 0)\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get number of GPUs and current GPU\n    int num_gpus;\n    int initial_gpu;\n    int timing_iterations           = 10000;\n    int timing_bytes                = 1024 * 1024;\n\n    if (CubDebug(cudaGetDeviceCount(&num_gpus))) exit(1);\n    if (CubDebug(cudaGetDevice(&initial_gpu))) exit(1);\n    args.GetCmdLineArgument(\"i\", timing_iterations);\n    args.GetCmdLineArgument(\"bytes\", timing_bytes);\n\n    // Create default allocator (caches up to 6MB in device allocations per GPU)\n    CachingDeviceAllocator allocator;\n    allocator.debug = true;\n\n    printf(\"Running single-gpu tests...\\n\"); fflush(stdout);\n\n    //\n    // Test0\n    //\n\n    // Create a new stream\n    cudaStream_t other_stream;\n    CubDebugExit(cudaStreamCreate(&other_stream));\n\n    // Allocate 999 bytes on the current gpu in stream0\n    char *d_999B_stream0_a;\n    char *d_999B_stream0_b;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));\n\n    // Run some big kernel in stream 0\n    EmptyKernel<void><<<32000, 512, 1024 * 8, 0>>>();\n\n    // Free d_999B_stream0_a\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_a));\n\n    // Allocate another 999 bytes in stream 0\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_b, 999, 0));\n\n    // Check that that we have 1 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    // Check that that we have no cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 0);\n\n    // Run some big kernel in stream 0\n    EmptyKernel<void><<<32000, 512, 1024 * 8, 0>>>();\n\n    // Free d_999B_stream0_b\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_b));\n\n    // Allocate 999 bytes on the current gpu in other_stream\n    char *d_999B_stream_other_a;\n    char *d_999B_stream_other_b;\n    allocator.DeviceAllocate((void **) &d_999B_stream_other_a, 999, other_stream);\n\n    // Check that that we have 1 live blocks on the initial GPU (that we allocated a new one because d_999B_stream0_b is only available for stream 0 until it becomes idle)\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    // Check that that we have one cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 1);\n\n    // Run some big kernel in other_stream\n    EmptyKernel<void><<<32000, 512, 1024 * 8, other_stream>>>();\n\n    // Free d_999B_stream_other\n    CubDebugExit(allocator.DeviceFree(d_999B_stream_other_a));\n\n    // Check that we can now use both allocations in stream 0 after synchronizing the device\n    CubDebugExit(cudaDeviceSynchronize());\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_b, 999, 0));\n\n    // Check that that we have 2 live blocks on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 2);\n\n    // Check that that we have no cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 0);\n\n    // Free d_999B_stream0_a and d_999B_stream0_b\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_a));\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_b));\n\n    // Check that we can now use both allocations in other_stream\n    CubDebugExit(cudaDeviceSynchronize());\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream_other_a, 999, other_stream));\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream_other_b, 999, other_stream));\n\n    // Check that that we have 2 live blocks on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 2);\n\n    // Check that that we have no cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 0);\n\n    // Run some big kernel in other_stream\n    EmptyKernel<void><<<32000, 512, 1024 * 8, other_stream>>>();\n\n    // Free d_999B_stream_other_a and d_999B_stream_other_b\n    CubDebugExit(allocator.DeviceFree(d_999B_stream_other_a));\n    CubDebugExit(allocator.DeviceFree(d_999B_stream_other_b));\n\n    // Check that we can now use both allocations in stream 0 after synchronizing the device and destroying the other stream\n    CubDebugExit(cudaDeviceSynchronize());\n    CubDebugExit(cudaStreamDestroy(other_stream));\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_a, 999, 0));\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_999B_stream0_b, 999, 0));\n\n    // Check that that we have 2 live blocks on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 2);\n\n    // Check that that we have no cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 0);\n\n    // Free d_999B_stream0_a and d_999B_stream0_b\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_a));\n    CubDebugExit(allocator.DeviceFree(d_999B_stream0_b));\n\n    // Free all cached\n    CubDebugExit(allocator.FreeAllCached());\n\n    //\n    // Test1\n    //\n\n    // Allocate 5 bytes on the current gpu\n    char *d_5B;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_5B, 5));\n\n    // Check that that we have zero free bytes cached on the initial GPU\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, 0);\n\n    // Check that that we have 1 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    //\n    // Test2\n    //\n\n    // Allocate 4096 bytes on the current gpu\n    char *d_4096B;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_4096B, 4096));\n\n    // Check that that we have 2 live blocks on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 2);\n\n    //\n    // Test3\n    //\n\n    // DeviceFree d_5B\n    CubDebugExit(allocator.DeviceFree(d_5B));\n\n    // Check that that we have min_bin_bytes free bytes cached on the initial gpu\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, allocator.min_bin_bytes);\n\n    // Check that that we have 1 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    // Check that that we have 1 cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 1);\n\n    //\n    // Test4\n    //\n\n    // DeviceFree d_4096B\n    CubDebugExit(allocator.DeviceFree(d_4096B));\n\n    // Check that that we have the 4096 + min_bin free bytes cached on the initial gpu\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, allocator.min_bin_bytes + 4096);\n\n    // Check that that we have 0 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 0);\n\n    // Check that that we have 2 cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 2);\n\n    //\n    // Test5\n    //\n\n    // Allocate 768 bytes on the current gpu\n    char *d_768B;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_768B, 768));\n\n    // Check that that we have the min_bin free bytes cached on the initial gpu (4096 was reused)\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, allocator.min_bin_bytes);\n\n    // Check that that we have 1 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    // Check that that we have 1 cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 1);\n\n    //\n    // Test6\n    //\n\n    // Allocate max_cached_bytes on the current gpu\n    char *d_max_cached;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_max_cached, allocator.max_cached_bytes));\n\n    // DeviceFree d_max_cached\n    CubDebugExit(allocator.DeviceFree(d_max_cached));\n\n    // Check that that we have the min_bin free bytes cached on the initial gpu (max cached was not returned because we went over)\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, allocator.min_bin_bytes);\n\n    // Check that that we have 1 live block on the initial GPU\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    // Check that that we still have 1 cached block on the initial GPU\n    AssertEquals(allocator.cached_blocks.size(), 1);\n\n    //\n    // Test7\n    //\n\n    // Free all cached blocks on all GPUs\n    CubDebugExit(allocator.FreeAllCached());\n\n    // Check that that we have 0 bytes cached on the initial GPU\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, 0);\n\n    // Check that that we have 0 cached blocks across all GPUs\n    AssertEquals(allocator.cached_blocks.size(), 0);\n\n    // Check that that still we have 1 live block across all GPUs\n    AssertEquals(allocator.live_blocks.size(), 1);\n\n    //\n    // Test8\n    //\n\n    // Allocate max cached bytes + 1 on the current gpu\n    char *d_max_cached_plus;\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_max_cached_plus, allocator.max_cached_bytes + 1));\n\n    // DeviceFree max cached bytes\n    CubDebugExit(allocator.DeviceFree(d_max_cached_plus));\n\n    // DeviceFree d_768B\n    CubDebugExit(allocator.DeviceFree(d_768B));\n\n    unsigned int power;\n    size_t rounded_bytes;\n    allocator.NearestPowerOf(power, rounded_bytes, allocator.bin_growth, 768);\n\n    // Check that that we have 4096 free bytes cached on the initial gpu\n    AssertEquals(allocator.cached_bytes[initial_gpu].free, rounded_bytes);\n\n    // Check that that we have 1 cached blocks across all GPUs\n    AssertEquals(allocator.cached_blocks.size(), 1);\n\n    // Check that that still we have 0 live block across all GPUs\n    AssertEquals(allocator.live_blocks.size(), 0);\n\n#ifndef CUB_CDP\n    // BUG: find out why these tests fail when one GPU is CDP compliant and the other is not\n\n    if (num_gpus > 1)\n    {\n        printf(\"\\nRunning multi-gpu tests...\\n\"); fflush(stdout);\n\n        //\n        // Test9\n        //\n\n        // Allocate 768 bytes on the next gpu\n        int next_gpu = (initial_gpu + 1) % num_gpus;\n        char *d_768B_2;\n        CubDebugExit(allocator.DeviceAllocate(next_gpu, (void **) &d_768B_2, 768));\n\n        // DeviceFree d_768B on the next gpu\n        CubDebugExit(allocator.DeviceFree(next_gpu, d_768B_2));\n\n        // Re-allocate 768 bytes on the next gpu\n        CubDebugExit(allocator.DeviceAllocate(next_gpu, (void **) &d_768B_2, 768));\n\n        // Re-free d_768B on the next gpu\n        CubDebugExit(allocator.DeviceFree(next_gpu, d_768B_2));\n\n        // Check that that we have 4096 free bytes cached on the initial gpu\n        AssertEquals(allocator.cached_bytes[initial_gpu].free, rounded_bytes);\n\n        // Check that that we have 4096 free bytes cached on the second gpu\n        AssertEquals(allocator.cached_bytes[next_gpu].free, rounded_bytes);\n\n        // Check that that we have 2 cached blocks across all GPUs\n        AssertEquals(allocator.cached_blocks.size(), 2);\n\n        // Check that that still we have 0 live block across all GPUs\n        AssertEquals(allocator.live_blocks.size(), 0);\n    }\n#endif  // CUB_CDP\n\n    //\n    // Performance\n    //\n\n    printf(\"\\nCPU Performance (%d timing iterations, %d bytes):\\n\", timing_iterations, timing_bytes);\n    fflush(stdout); fflush(stderr);\n\n    // CPU performance comparisons vs cached.  Allocate and free a 1MB block 2000 times\n    CpuTimer    cpu_timer;\n    char        *d_1024MB                       = NULL;\n    allocator.debug                             = false;\n\n    // Prime the caching allocator and the kernel\n    CubDebugExit(allocator.DeviceAllocate((void **) &d_1024MB, timing_bytes));\n    CubDebugExit(allocator.DeviceFree(d_1024MB));\n    cub::EmptyKernel<void><<<1, 32>>>();\n\n    // CUDA\n    cpu_timer.Start();\n    for (int i = 0; i < timing_iterations; ++i)\n    {\n        CubDebugExit(cudaMalloc((void **) &d_1024MB, timing_bytes));\n        CubDebugExit(cudaFree(d_1024MB));\n    }\n    cpu_timer.Stop();\n    float cuda_malloc_elapsed_millis = cpu_timer.ElapsedMillis();\n\n    // CUB\n    cpu_timer.Start();\n    for (int i = 0; i < timing_iterations; ++i)\n    {\n        CubDebugExit(allocator.DeviceAllocate((void **) &d_1024MB, timing_bytes));\n        CubDebugExit(allocator.DeviceFree(d_1024MB));\n    }\n    cpu_timer.Stop();\n    float cub_calloc_elapsed_millis = cpu_timer.ElapsedMillis();\n\n    printf(\"\\t CUB CachingDeviceAllocator allocation CPU speedup: %.2f (avg cudaMalloc %.4f ms vs. avg DeviceAllocate %.4f ms)\\n\",\n        cuda_malloc_elapsed_millis / cub_calloc_elapsed_millis,\n        cuda_malloc_elapsed_millis / timing_iterations,\n        cub_calloc_elapsed_millis / timing_iterations);\n\n    // GPU performance comparisons.  Allocate and free a 1MB block 2000 times\n    GpuTimer gpu_timer;\n\n    printf(\"\\nGPU Performance (%d timing iterations, %d bytes):\\n\", timing_iterations, timing_bytes);\n    fflush(stdout); fflush(stderr);\n\n    // Kernel-only\n    gpu_timer.Start();\n    for (int i = 0; i < timing_iterations; ++i)\n    {\n        cub::EmptyKernel<void><<<1, 32>>>();\n    }\n    gpu_timer.Stop();\n    float cuda_empty_elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // CUDA\n    gpu_timer.Start();\n    for (int i = 0; i < timing_iterations; ++i)\n    {\n        CubDebugExit(cudaMalloc((void **) &d_1024MB, timing_bytes));\n        cub::EmptyKernel<void><<<1, 32>>>();\n        CubDebugExit(cudaFree(d_1024MB));\n    }\n    gpu_timer.Stop();\n    cuda_malloc_elapsed_millis = gpu_timer.ElapsedMillis() - cuda_empty_elapsed_millis;\n\n    // CUB\n    gpu_timer.Start();\n    for (int i = 0; i < timing_iterations; ++i)\n    {\n        CubDebugExit(allocator.DeviceAllocate((void **) &d_1024MB, timing_bytes));\n        cub::EmptyKernel<void><<<1, 32>>>();\n        CubDebugExit(allocator.DeviceFree(d_1024MB));\n    }\n    gpu_timer.Stop();\n    cub_calloc_elapsed_millis = gpu_timer.ElapsedMillis() - cuda_empty_elapsed_millis;\n\n    printf(\"\\t CUB CachingDeviceAllocator allocation GPU speedup: %.2f (avg cudaMalloc %.4f ms vs. avg DeviceAllocate %.4f ms)\\n\",\n        cuda_malloc_elapsed_millis / cub_calloc_elapsed_millis,\n        cuda_malloc_elapsed_millis / timing_iterations,\n        cub_calloc_elapsed_millis / timing_iterations);\n\n\n#endif\n\n    printf(\"Success\\n\");\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/test/test_block_histogram.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of BlockHistogram utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <limits>\n#include <string>\n#include <typeinfo>\n\n#include <cub/block/block_histogram.cuh>\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/**\n * BlockHistogram test kernel.\n */\ntemplate <\n    int                     BINS,\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockHistogramAlgorithm ALGORITHM,\n    typename                T,\n    typename                HistoCounter>\n__global__ void BlockHistogramKernel(\n    T                       *d_samples,\n    HistoCounter            *d_histogram)\n{\n    // Parameterize BlockHistogram type for our thread block\n    typedef BlockHistogram<T, BLOCK_THREADS, ITEMS_PER_THREAD, BINS, ALGORITHM> BlockHistogram;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename BlockHistogram::TempStorage temp_storage;\n\n    // Per-thread tile data\n    T data[ITEMS_PER_THREAD];\n    LoadDirectStriped<BLOCK_THREADS>(threadIdx.x, d_samples, data);\n\n    // Test histo (writing directly to histogram buffer in global)\n    BlockHistogram(temp_storage).Histogram(data, d_histogram);\n}\n\n\n/**\n * Initialize problem (and solution)\n */\ntemplate <\n    int             BINS,\n    typename        SampleT>\nvoid Initialize(\n    GenMode         gen_mode,\n    SampleT         *h_samples,\n    int             *h_histograms_linear,\n    int             num_samples)\n{\n    // Init bins\n    for (int bin = 0; bin < BINS; ++bin)\n    {\n        h_histograms_linear[bin] = 0;\n    }\n\n    if (g_verbose) printf(\"Samples: \\n\");\n\n    // Initialize interleaved channel samples and histogram them correspondingly\n    for (int i = 0; i < num_samples; ++i)\n    {\n        InitValue(gen_mode, h_samples[i], i);\n        h_samples[i] %= BINS;\n\n        if (g_verbose) std::cout << CoutCast(h_samples[i]) << \", \";\n\n        h_histograms_linear[h_samples[i]]++;\n    }\n\n    if (g_verbose) printf(\"\\n\\n\");\n}\n\n\n/**\n * Test BlockHistogram\n */\ntemplate <\n    typename                    SampleT,\n    int                         BINS,\n    int                         BLOCK_THREADS,\n    int                         ITEMS_PER_THREAD,\n    BlockHistogramAlgorithm     ALGORITHM>\nvoid Test(\n    GenMode                     gen_mode)\n{\n    int num_samples = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    printf(\"cub::BlockHistogram %s %d %s samples (%dB), %d bins, %d threads, gen-mode %s\\n\",\n        (ALGORITHM == BLOCK_HISTO_SORT) ? \"BLOCK_HISTO_SORT\" : \"BLOCK_HISTO_ATOMIC\",\n        num_samples,\n        typeid(SampleT).name(),\n        (int) sizeof(SampleT),\n        BINS,\n        BLOCK_THREADS,\n        (gen_mode == RANDOM) ? \"RANDOM\" : (gen_mode == INTEGER_SEED) ? \"SEQUENTIAL\" : \"HOMOGENOUS\");\n    fflush(stdout);\n\n    // Allocate host arrays\n    SampleT         *h_samples          = new SampleT[num_samples];\n    int   *h_reference = new int[BINS];\n\n    // Initialize problem\n    Initialize<BINS>(gen_mode, h_samples, h_reference, num_samples);\n\n    // Allocate problem device arrays\n    SampleT         *d_samples = NULL;\n    int             *d_histogram = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_samples,             sizeof(SampleT) * num_samples));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_histogram,   sizeof(int) * BINS));\n\n    // Initialize/clear device arrays\n    CubDebugExit(cudaMemcpy(d_samples, h_samples, sizeof(SampleT) * num_samples, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_histogram, 0, sizeof(int) * BINS));\n\n    // Run kernel\n    BlockHistogramKernel<BINS, BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM><<<1, BLOCK_THREADS>>>(\n        d_samples,\n        d_histogram);\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults((int*) h_reference, d_histogram, BINS, g_verbose, g_verbose);\n    printf(\"\\t%s\\n\\n\", compare ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n    fflush(stdout);\n    fflush(stderr);\n\n    // Cleanup\n    if (h_samples) delete[] h_samples;\n    if (h_reference) delete[] h_reference;\n    if (d_samples) CubDebugExit(g_allocator.DeviceFree(d_samples));\n    if (d_histogram) CubDebugExit(g_allocator.DeviceFree(d_histogram));\n\n    // Correctness asserts\n    AssertEquals(0, compare);\n}\n\n\n/**\n * Test different sample distributions\n */\ntemplate <\n    typename                    SampleT,\n    int                         BINS,\n    int                         BLOCK_THREADS,\n    int                         ITEMS_PER_THREAD,\n    BlockHistogramAlgorithm     ALGORITHM>\nvoid Test()\n{\n    Test<SampleT, BINS, BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM>(UNIFORM);\n    Test<SampleT, BINS, BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM>(INTEGER_SEED);\n    Test<SampleT, BINS, BLOCK_THREADS, ITEMS_PER_THREAD, ALGORITHM>(RANDOM);\n}\n\n\n/**\n * Test different ALGORITHM\n */\ntemplate <\n    typename                    SampleT,\n    int                         BINS,\n    int                         BLOCK_THREADS,\n    int                         ITEMS_PER_THREAD>\nvoid Test()\n{\n    Test<SampleT, BINS, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_HISTO_SORT>();\n    Test<SampleT, BINS, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_HISTO_ATOMIC>();\n}\n\n\n/**\n * Test different ITEMS_PER_THREAD\n */\ntemplate <\n    typename                    SampleT,\n    int                         BINS,\n    int                         BLOCK_THREADS>\nvoid Test()\n{\n    Test<SampleT, BINS, BLOCK_THREADS, 1>();\n    Test<SampleT, BINS, BLOCK_THREADS, 5>();\n}\n\n\n/**\n * Test different BLOCK_THREADS\n */\ntemplate <\n    typename                    SampleT,\n    int                         BINS>\nvoid Test()\n{\n    Test<SampleT, BINS, 32>();\n    Test<SampleT, BINS, 96>();\n    Test<SampleT, BINS, 128>();\n}\n\n\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<total input samples across all channels> \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#ifdef QUICK_TEST\n\n    // Compile/run quick tests\n    Test<unsigned char, 256, 128, 4, BLOCK_HISTO_SORT>(RANDOM);\n    Test<unsigned char, 256, 128, 4, BLOCK_HISTO_ATOMIC>(RANDOM);\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        Test<unsigned char, 32>();\n        Test<unsigned char, 256>();\n        Test<unsigned short, 1024>();\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_block_load_store.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of BlockLoad and BlockStore utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <iterator>\n#include <stdio.h>\n\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/iterator/cache_modified_input_iterator.cuh>\n#include <cub/iterator/cache_modified_output_iterator.cuh>\n#include <cub/iterator/discard_output_iterator.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;\nCachingDeviceAllocator  g_allocator(true);\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n\n/**\n * Test load/store kernel.\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM,\n    typename            InputIteratorT,\n    typename            OutputIteratorT>\n__launch_bounds__ (BLOCK_THREADS, 1)\n__global__ void Kernel(\n    InputIteratorT    d_in,\n    OutputIteratorT    d_out_unguarded,\n    OutputIteratorT    d_out_guarded,\n    int               num_items)\n{\n    enum\n    {\n        TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD\n    };\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Threadblock load/store abstraction types\n    typedef BlockLoad<InputT, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM> BlockLoad;\n    typedef BlockStore<OutputT, BLOCK_THREADS, ITEMS_PER_THREAD, STORE_ALGORITHM> BlockStore;\n\n    // Shared memory type for this thread block\n    union TempStorage\n    {\n        typename BlockLoad::TempStorage     load;\n        typename BlockStore::TempStorage    store;\n    };\n\n    // Allocate temp storage in shared memory\n    __shared__ TempStorage temp_storage;\n\n    // Threadblock work bounds\n    int block_offset = blockIdx.x * TILE_SIZE;\n    int guarded_elements = num_items - block_offset;\n\n    // Tile of items\n    OutputT data[ITEMS_PER_THREAD];\n\n    // Load data\n    BlockLoad(temp_storage.load).Load(d_in + block_offset, data);\n\n    __syncthreads();\n\n    // Store data\n    BlockStore(temp_storage.store).Store(d_out_unguarded + block_offset, data);\n\n    __syncthreads();\n\n    // reset data\n    #pragma unroll\n    for (int ITEM = 0; ITEM < ITEMS_PER_THREAD; ++ITEM)\n        data[ITEM] = OutputT();\n\n    __syncthreads();\n\n    // Load data\n    BlockLoad(temp_storage.load).Load(d_in + block_offset, data, guarded_elements);\n\n    __syncthreads();\n\n    // Store data\n    BlockStore(temp_storage.store).Store(d_out_guarded + block_offset, data, guarded_elements);\n}\n\n\n//---------------------------------------------------------------------\n// Host testing subroutines\n//---------------------------------------------------------------------\n\n\n/**\n * Test load/store variants\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM,\n    typename            InputIteratorT,\n    typename            OutputIteratorT>\nvoid TestKernel(\n    T                   *h_in,\n    InputIteratorT      d_in,\n    OutputIteratorT      d_out_unguarded_itr,\n    OutputIteratorT      d_out_guarded_itr,\n    T                   *d_out_unguarded_ptr,\n    T                   *d_out_guarded_ptr,\n    int                 grid_size,\n    int                 guarded_elements)\n{\n    int compare;\n\n    int unguarded_elements = grid_size * BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Test with discard output iterator\n    typedef typename std::iterator_traits<InputIteratorT>::difference_type OffsetT;\n    DiscardOutputIterator<OffsetT> discard_itr;\n\n    Kernel<BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM>\n        <<<grid_size, BLOCK_THREADS>>>(\n            d_in,\n            discard_itr,\n            discard_itr,\n            guarded_elements);\n\n    // Test with regular output iterator\n    Kernel<BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM>\n        <<<grid_size, BLOCK_THREADS>>>(\n            d_in,\n            d_out_unguarded_itr,\n            d_out_guarded_itr,\n            guarded_elements);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Check results\n    compare = CompareDeviceResults(h_in, d_out_guarded_ptr, guarded_elements, g_verbose, g_verbose);\n    printf(\"\\tGuarded: %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Check results\n    compare = CompareDeviceResults(h_in, d_out_unguarded_ptr, unguarded_elements, g_verbose, g_verbose);\n    printf(\"\\tUnguarded: %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n}\n\n\n/**\n * Test native pointer.  Specialized for sufficient resources\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM>\nvoid TestNative(\n    int                 grid_size,\n    float               fraction_valid,\n    Int2Type<true>      sufficient_resources)\n{\n    int unguarded_elements = grid_size * BLOCK_THREADS * ITEMS_PER_THREAD;\n    int guarded_elements = int(fraction_valid * float(unguarded_elements));\n\n    // Allocate host arrays\n    T *h_in = (T*) malloc(unguarded_elements * sizeof(T));\n\n    // Allocate device arrays\n    T *d_in = NULL;\n    T *d_out_unguarded = NULL;\n    T *d_out_guarded = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * unguarded_elements));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out_unguarded, sizeof(T) * unguarded_elements));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out_guarded, sizeof(T) * guarded_elements));\n    CubDebugExit(cudaMemset(d_out_unguarded, 0, sizeof(T) * unguarded_elements));\n    CubDebugExit(cudaMemset(d_out_guarded, 0, sizeof(T) * guarded_elements));\n\n    // Initialize problem on host and device\n    for (int i = 0; i < unguarded_elements; ++i)\n    {\n        InitValue(INTEGER_SEED, h_in[i], i);\n    }\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * unguarded_elements, cudaMemcpyHostToDevice));\n\n    printf(\"TestNative \"\n        \"grid_size(%d) \"\n        \"guarded_elements(%d) \"\n        \"unguarded_elements(%d) \"\n        \"BLOCK_THREADS(%d) \"\n        \"ITEMS_PER_THREAD(%d) \"\n        \"LOAD_ALGORITHM(%d) \"\n        \"STORE_ALGORITHM(%d) \"\n        \"sizeof(T)(%d)\\n\",\n            grid_size, guarded_elements, unguarded_elements, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM, (int) sizeof(T));\n\n    TestKernel<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM>(\n        h_in,\n        (T const *) d_in,   // Test const\n        d_out_unguarded,\n        d_out_guarded,\n        d_out_unguarded,\n        d_out_guarded,\n        grid_size,\n        guarded_elements);\n\n    // Cleanup\n    if (h_in) free(h_in);\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out_unguarded) CubDebugExit(g_allocator.DeviceFree(d_out_unguarded));\n    if (d_out_guarded) CubDebugExit(g_allocator.DeviceFree(d_out_guarded));\n}\n\n\n/**\n * Test native pointer.  Specialized for insufficient resources\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM>\nvoid TestNative(\n    int                 grid_size,\n    float               fraction_valid,\n    Int2Type<false>      sufficient_resources)\n{}\n\n\n/**\n * Test iterator.  Specialized for sufficient resources.\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM,\n    CacheLoadModifier   LOAD_MODIFIER,\n    CacheStoreModifier  STORE_MODIFIER>\nvoid TestIterator(\n    int                 grid_size,\n    float               fraction_valid,\n    Int2Type<true>      sufficient_resources)\n{\n    int unguarded_elements = grid_size * BLOCK_THREADS * ITEMS_PER_THREAD;\n    int guarded_elements = int(fraction_valid * float(unguarded_elements));\n\n    // Allocate host arrays\n    T *h_in = (T*) malloc(unguarded_elements * sizeof(T));\n\n    // Allocate device arrays\n    T *d_in = NULL;\n    T *d_out_unguarded = NULL;\n    T *d_out_guarded = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * unguarded_elements));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out_unguarded, sizeof(T) * unguarded_elements));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out_guarded, sizeof(T) * guarded_elements));\n    CubDebugExit(cudaMemset(d_out_unguarded, 0, sizeof(T) * unguarded_elements));\n    CubDebugExit(cudaMemset(d_out_guarded, 0, sizeof(T) * guarded_elements));\n\n    // Initialize problem on host and device\n    for (int i = 0; i < unguarded_elements; ++i)\n    {\n        InitValue(INTEGER_SEED, h_in[i], i);\n    }\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * unguarded_elements, cudaMemcpyHostToDevice));\n\n    printf(\"TestIterator \"\n        \"grid_size(%d) \"\n        \"guarded_elements(%d) \"\n        \"unguarded_elements(%d) \"\n        \"BLOCK_THREADS(%d) \"\n        \"ITEMS_PER_THREAD(%d) \"\n        \"LOAD_ALGORITHM(%d) \"\n        \"STORE_ALGORITHM(%d) \"\n        \"LOAD_MODIFIER(%d) \"\n        \"STORE_MODIFIER(%d) \"\n        \"sizeof(T)(%d)\\n\",\n            grid_size, guarded_elements, unguarded_elements, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM, LOAD_MODIFIER, STORE_MODIFIER, (int) sizeof(T));\n\n    TestKernel<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM>(\n        h_in,\n        CacheModifiedInputIterator<LOAD_MODIFIER, T>(d_in),\n        CacheModifiedOutputIterator<STORE_MODIFIER, T>(d_out_unguarded),\n        CacheModifiedOutputIterator<STORE_MODIFIER, T>(d_out_guarded),\n        d_out_unguarded,\n        d_out_guarded,\n        grid_size,\n        guarded_elements);\n\n    // Cleanup\n    if (h_in) free(h_in);\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out_unguarded) CubDebugExit(g_allocator.DeviceFree(d_out_unguarded));\n    if (d_out_guarded) CubDebugExit(g_allocator.DeviceFree(d_out_guarded));\n}\n\n/**\n * Test iterator.  Specialized for insufficient resources.\n */\ntemplate <\n    typename            T,\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    BlockLoadAlgorithm  LOAD_ALGORITHM,\n    BlockStoreAlgorithm STORE_ALGORITHM,\n    CacheLoadModifier   LOAD_MODIFIER,\n    CacheStoreModifier  STORE_MODIFIER>\nvoid TestIterator(\n    int                 grid_size,\n    float               fraction_valid,\n    Int2Type<false>     sufficient_resources)\n{}\n\n\n/**\n * Evaluate different pointer access types\n */\ntemplate <\n    typename                T,\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockLoadAlgorithm      LOAD_ALGORITHM,\n    BlockStoreAlgorithm     STORE_ALGORITHM>\nvoid TestPointerType(\n    int             grid_size,\n    float           fraction_valid)\n{\n    // Threadblock load/store abstraction types\n    typedef BlockLoad<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM> BlockLoad;\n    typedef BlockStore<T, BLOCK_THREADS, ITEMS_PER_THREAD, STORE_ALGORITHM> BlockStore;\n\n#if defined(SM100) || defined(SM110) || defined(SM130)\n    static const bool sufficient_load_smem  = sizeof(typename BlockLoad::TempStorage)   <= 1024 * 16;\n    static const bool sufficient_store_smem = sizeof(typename BlockStore::TempStorage)  <= 1024 * 16;\n    static const bool sufficient_threads    = BLOCK_THREADS <= 512;\n#else\n    static const bool sufficient_load_smem  = sizeof(typename BlockLoad::TempStorage)   <= 1024 * 48;\n    static const bool sufficient_store_smem = sizeof(typename BlockStore::TempStorage)  <= 1024 * 48;\n    static const bool sufficient_threads    = BLOCK_THREADS <= 1024;\n#endif\n\n    static const bool sufficient_resources  = sufficient_load_smem && sufficient_store_smem && sufficient_threads;\n\n    TestNative<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM>(grid_size, fraction_valid, Int2Type<sufficient_resources>());\n    TestIterator<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM, LOAD_DEFAULT, STORE_DEFAULT>(grid_size, fraction_valid, Int2Type<sufficient_resources>());\n}\n\n\n/**\n * Evaluate different time-slicing strategies\n */\ntemplate <\n    typename                T,\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    BlockLoadAlgorithm      LOAD_ALGORITHM,\n    BlockStoreAlgorithm     STORE_ALGORITHM>\nvoid TestSlicedStrategy(\n    int             grid_size,\n    float           fraction_valid)\n{\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM, true>(grid_size, fraction_valid);\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, LOAD_ALGORITHM, STORE_ALGORITHM, false>(grid_size, fraction_valid);\n}\n\n\n\n/**\n * Evaluate different load/store strategies (specialized for block sizes that are not a multiple of 32)\n */\ntemplate <\n    typename        T,\n    int             BLOCK_THREADS,\n    int             ITEMS_PER_THREAD>\nvoid TestStrategy(\n    int             grid_size,\n    float           fraction_valid,\n    Int2Type<false> is_warp_multiple)\n{\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_DIRECT, BLOCK_STORE_DIRECT>(grid_size, fraction_valid);\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_TRANSPOSE, BLOCK_STORE_TRANSPOSE>(grid_size, fraction_valid);\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_VECTORIZE, BLOCK_STORE_VECTORIZE>(grid_size, fraction_valid);\n}\n\n\n/**\n * Evaluate different load/store strategies (specialized for block sizes that are a multiple of 32)\n */\ntemplate <\n    typename        T,\n    int             BLOCK_THREADS,\n    int             ITEMS_PER_THREAD>\nvoid TestStrategy(\n    int             grid_size,\n    float           fraction_valid,\n    Int2Type<true>  is_warp_multiple)\n{\n    TestStrategy<T, BLOCK_THREADS, ITEMS_PER_THREAD>(grid_size, fraction_valid, Int2Type<false>());\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_WARP_TRANSPOSE, BLOCK_STORE_WARP_TRANSPOSE>(grid_size, fraction_valid);\n    TestPointerType<T, BLOCK_THREADS, ITEMS_PER_THREAD, BLOCK_LOAD_WARP_TRANSPOSE_TIMESLICED, BLOCK_STORE_WARP_TRANSPOSE_TIMESLICED>(grid_size, fraction_valid);\n}\n\n\n/**\n * Evaluate different register blocking\n */\ntemplate <\n    typename T,\n    int BLOCK_THREADS>\nvoid TestItemsPerThread(\n    int grid_size,\n    float fraction_valid)\n{\n    Int2Type<BLOCK_THREADS % 32 == 0> is_warp_multiple;\n\n    TestStrategy<T, BLOCK_THREADS, 1>(grid_size, fraction_valid, is_warp_multiple);\n    TestStrategy<T, BLOCK_THREADS, 3>(grid_size, fraction_valid, is_warp_multiple);\n    TestStrategy<T, BLOCK_THREADS, 4>(grid_size, fraction_valid, is_warp_multiple);\n    TestStrategy<T, BLOCK_THREADS, 11>(grid_size, fraction_valid, is_warp_multiple);\n}\n\n\n/**\n * Evaluate different thread block sizes\n */\ntemplate <typename T>\nvoid TestThreads(\n    int grid_size,\n    float fraction_valid)\n{\n    TestItemsPerThread<T, 15>(grid_size, fraction_valid);\n    TestItemsPerThread<T, 32>(grid_size, fraction_valid);\n    TestItemsPerThread<T, 72>(grid_size, fraction_valid);\n    TestItemsPerThread<T, 96>(grid_size, fraction_valid);\n    TestItemsPerThread<T, 128>(grid_size, fraction_valid);\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef QUICK_TEST\n\n    // Compile/run quick tests\n    TestNative<     int, 64, 2, BLOCK_LOAD_WARP_TRANSPOSE, BLOCK_STORE_WARP_TRANSPOSE>(1, 0.8f, Int2Type<true>());\n    TestIterator<   int, 64, 2, BLOCK_LOAD_WARP_TRANSPOSE, BLOCK_STORE_WARP_TRANSPOSE, LOAD_DEFAULT, STORE_DEFAULT>(1, 0.8f, Int2Type<true>());\n\n#else\n\n    // Compile/run thorough tests\n    TestThreads<char>(2, 0.8f);\n    TestThreads<int>(2, 0.8f);\n    TestThreads<long>(2, 0.8f);\n    TestThreads<long2>(2, 0.8f);\n\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        TestThreads<double2>(2, 0.8f);\n    TestThreads<TestFoo>(2, 0.8f);\n    TestThreads<TestBar>(2, 0.8f);\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_block_radix_sort.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of BlockRadixSort utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <algorithm>\n#include <iostream>\n\n#include <cub/block/block_radix_sort.cuh>\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;\nCachingDeviceAllocator  g_allocator(true);\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n\n/// Specialized descending, blocked -> blocked\ntemplate <int BLOCK_THREADS, typename BlockRadixSort, int ITEMS_PER_THREAD, typename Key, typename Value>\n__device__ __forceinline__ void TestBlockSort(\n    typename BlockRadixSort::TempStorage &temp_storage,\n    Key                         (&keys)[ITEMS_PER_THREAD],\n    Value                       (&values)[ITEMS_PER_THREAD],\n    Key                         *d_keys,\n    Value                       *d_values,\n    int                         begin_bit,\n    int                         end_bit,\n    clock_t                     &stop,\n    Int2Type<true>              is_descending,\n    Int2Type<true>              is_blocked_output)\n{\n    BlockRadixSort(temp_storage).SortDescending(keys, values, begin_bit, end_bit);\n    stop = clock();\n    StoreDirectBlocked(threadIdx.x, d_keys, keys);\n    StoreDirectBlocked(threadIdx.x, d_values, values);\n}\n\n/// Specialized descending, blocked -> striped\ntemplate <int BLOCK_THREADS, typename BlockRadixSort, int ITEMS_PER_THREAD, typename Key, typename Value>\n__device__ __forceinline__ void TestBlockSort(\n    typename BlockRadixSort::TempStorage &temp_storage,\n    Key                         (&keys)[ITEMS_PER_THREAD],\n    Value                       (&values)[ITEMS_PER_THREAD],\n    Key                         *d_keys,\n    Value                       *d_values,\n    int                         begin_bit,\n    int                         end_bit,\n    clock_t                     &stop,\n    Int2Type<true>              is_descending,\n    Int2Type<false>             is_blocked_output)\n{\n    BlockRadixSort(temp_storage).SortDescendingBlockedToStriped(keys, values, begin_bit, end_bit);\n    stop = clock();\n    StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_keys, keys);\n    StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_values, values);\n}\n\n/// Specialized ascending, blocked -> blocked\ntemplate <int BLOCK_THREADS, typename BlockRadixSort, int ITEMS_PER_THREAD, typename Key, typename Value>\n__device__ __forceinline__ void TestBlockSort(\n    typename BlockRadixSort::TempStorage &temp_storage,\n    Key                         (&keys)[ITEMS_PER_THREAD],\n    Value                       (&values)[ITEMS_PER_THREAD],\n    Key                         *d_keys,\n    Value                       *d_values,\n    int                         begin_bit,\n    int                         end_bit,\n    clock_t                     &stop,\n    Int2Type<false>             is_descending,\n    Int2Type<true>              is_blocked_output)\n{\n    BlockRadixSort(temp_storage).Sort(keys, values, begin_bit, end_bit);\n    stop = clock();\n    StoreDirectBlocked(threadIdx.x, d_keys, keys);\n    StoreDirectBlocked(threadIdx.x, d_values, values);\n}\n\n/// Specialized ascending, blocked -> striped\ntemplate <int BLOCK_THREADS, typename BlockRadixSort, int ITEMS_PER_THREAD, typename Key, typename Value>\n__device__ __forceinline__ void TestBlockSort(\n    typename BlockRadixSort::TempStorage &temp_storage,\n    Key                         (&keys)[ITEMS_PER_THREAD],\n    Value                       (&values)[ITEMS_PER_THREAD],\n    Key                         *d_keys,\n    Value                       *d_values,\n    int                         begin_bit,\n    int                         end_bit,\n    clock_t                     &stop,\n    Int2Type<false>             is_descending,\n    Int2Type<false>             is_blocked_output)\n{\n    BlockRadixSort(temp_storage).SortBlockedToStriped(keys, values, begin_bit, end_bit);\n    stop = clock();\n    StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_keys, keys);\n    StoreDirectStriped<BLOCK_THREADS>(threadIdx.x, d_values, values);\n}\n\n\n\n/**\n * BlockRadixSort kernel\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    int                 RADIX_BITS,\n    bool                MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm  INNER_SCAN_ALGORITHM,\n    cudaSharedMemConfig SMEM_CONFIG,\n    int                 DESCENDING,\n    int                 BLOCKED_OUTPUT,\n    typename            Key,\n    typename            Value>\n__launch_bounds__ (BLOCK_THREADS, 1)\n__global__ void Kernel(\n    Key                         *d_keys,\n    Value                       *d_values,\n    int                         begin_bit,\n    int                         end_bit,\n    clock_t                     *d_elapsed)\n{\n    // Threadblock load/store abstraction types\n    typedef BlockRadixSort<\n            Key,\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            Value,\n            RADIX_BITS,\n            MEMOIZE_OUTER_SCAN,\n            INNER_SCAN_ALGORITHM,\n            SMEM_CONFIG>\n        BlockRadixSortT;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename BlockRadixSortT::TempStorage temp_storage;\n\n    // Items per thread\n    Key     keys[ITEMS_PER_THREAD];\n    Value   values[ITEMS_PER_THREAD];\n\n    LoadDirectBlocked(threadIdx.x, d_keys, keys);\n    LoadDirectBlocked(threadIdx.x, d_values, values);\n\n    // Start cycle timer\n    clock_t stop;\n    clock_t start = clock();\n\n    TestBlockSort<BLOCK_THREADS, BlockRadixSortT>(\n        temp_storage, keys, values, d_keys, d_values, begin_bit, end_bit, stop, Int2Type<DESCENDING>(), Int2Type<BLOCKED_OUTPUT>());\n\n    // Store time\n    if (threadIdx.x == 0)\n        *d_elapsed = (start > stop) ? start - stop : stop - start;\n}\n\n\n\n//---------------------------------------------------------------------\n// Host testing subroutines\n//---------------------------------------------------------------------\n\n\n/**\n * Simple key-value pairing\n */\ntemplate <\n    typename Key,\n    typename Value,\n    bool IS_FLOAT = (Traits<Key>::CATEGORY == FLOATING_POINT)>\nstruct Pair\n{\n    Key     key;\n    Value   value;\n\n    bool operator<(const Pair &b) const\n    {\n        return (key < b.key);\n    }\n};\n\n/**\n * Simple key-value pairing (specialized for floating point types)\n */\ntemplate <typename Key, typename Value>\nstruct Pair<Key, Value, true>\n{\n    Key     key;\n    Value   value;\n\n    bool operator<(const Pair &b) const\n    {\n        if (key < b.key)\n            return true;\n\n        if (key > b.key)\n            return false;\n\n        // Key in unsigned bits\n        typedef typename Traits<Key>::UnsignedBits UnsignedBits;\n\n        // Return true if key is negative zero and b.key is positive zero\n        UnsignedBits key_bits   = *reinterpret_cast<UnsignedBits*>(const_cast<Key*>(&key));\n        UnsignedBits b_key_bits = *reinterpret_cast<UnsignedBits*>(const_cast<Key*>(&b.key));\n        UnsignedBits HIGH_BIT   = Traits<Key>::HIGH_BIT;\n\n        return ((key_bits & HIGH_BIT) != 0) && ((b_key_bits & HIGH_BIT) == 0);\n    }\n};\n\n\n/**\n * Initialize key-value sorting problem.\n */\ntemplate <bool DESCENDING, typename Key, typename Value>\nvoid Initialize(\n    GenMode         gen_mode,\n    Key             *h_keys,\n    Value           *h_values,\n    Key             *h_reference_keys,\n    Value           *h_reference_values,\n    int             num_items,\n    int             entropy_reduction,\n    int             begin_bit,\n    int             end_bit)\n{\n    Pair<Key, Value> *h_pairs = new Pair<Key, Value>[num_items];\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_keys[i], i);\n\n        RandomBits(h_values[i]);\n\n        // Mask off unwanted portions\n        int num_bits = end_bit - begin_bit;\n        if ((begin_bit > 0) || (end_bit < sizeof(Key) * 8))\n        {\n            unsigned long long base = 0;\n            memcpy(&base, &h_keys[i], sizeof(Key));\n            base &= ((1ull << num_bits) - 1) << begin_bit;\n            memcpy(&h_keys[i], &base, sizeof(Key));\n        }\n\n        h_pairs[i].key    = h_keys[i];\n        h_pairs[i].value  = h_values[i];\n    }\n\n    if (DESCENDING) std::reverse(h_pairs, h_pairs + num_items);\n    std::stable_sort(h_pairs, h_pairs + num_items);\n    if (DESCENDING) std::reverse(h_pairs, h_pairs + num_items);\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_reference_keys[i]     = h_pairs[i].key;\n        h_reference_values[i]   = h_pairs[i].value;\n    }\n\n    delete[] h_pairs;\n}\n\n\n\n\n/**\n * Test BlockRadixSort kernel\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    cudaSharedMemConfig     SMEM_CONFIG,\n    bool                    DESCENDING,\n    bool                    BLOCKED_OUTPUT,\n    typename                Key,\n    typename                Value>\nvoid TestDriver(\n    GenMode                 gen_mode,\n    int                     entropy_reduction,\n    int                     begin_bit,\n    int                     end_bit)\n{\n    enum\n    {\n        TILE_SIZE = BLOCK_THREADS * ITEMS_PER_THREAD,\n        KEYS_ONLY = Equals<Value, NullType>::VALUE,\n    };\n\n    // Allocate host arrays\n    Key     *h_keys             = new Key[TILE_SIZE];\n    Key     *h_reference_keys   = new Key[TILE_SIZE];\n    Value   *h_values           = new Value[TILE_SIZE];\n    Value   *h_reference_values = new Value[TILE_SIZE];\n\n    // Allocate device arrays\n    Key     *d_keys     = NULL;\n    Value   *d_values   = NULL;\n    clock_t *d_elapsed  = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys, sizeof(Key) * TILE_SIZE));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values, sizeof(Value) * TILE_SIZE));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(clock_t)));\n\n    // Initialize problem and solution on host\n    Initialize<DESCENDING>(gen_mode, h_keys, h_values, h_reference_keys, h_reference_values,\n        TILE_SIZE, entropy_reduction, begin_bit, end_bit);\n\n    // Copy problem to device\n    CubDebugExit(cudaMemcpy(d_keys, h_keys, sizeof(Key) * TILE_SIZE, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_values, h_values, sizeof(Value) * TILE_SIZE, cudaMemcpyHostToDevice));\n\n    printf(\"%s \"\n        \"BLOCK_THREADS(%d) \"\n        \"ITEMS_PER_THREAD(%d) \"\n        \"RADIX_BITS(%d) \"\n        \"MEMOIZE_OUTER_SCAN(%d) \"\n        \"INNER_SCAN_ALGORITHM(%d) \"\n        \"SMEM_CONFIG(%d) \"\n        \"DESCENDING(%d) \"\n        \"BLOCKED_OUTPUT(%d) \"\n        \"sizeof(Key)(%d) \"\n        \"sizeof(Value)(%d) \"\n        \"gen_mode(%d), \"\n        \"entropy_reduction(%d) \"\n        \"begin_bit(%d) \"\n        \"end_bit(%d), \"\n        \"samples(%d)\\n\",\n            ((KEYS_ONLY) ? \"Keys-only\" : \"Key-value\"),\n            BLOCK_THREADS,\n            ITEMS_PER_THREAD,\n            RADIX_BITS,\n            MEMOIZE_OUTER_SCAN,\n            INNER_SCAN_ALGORITHM,\n            SMEM_CONFIG,\n            DESCENDING,\n            BLOCKED_OUTPUT,\n            (int) sizeof(Key),\n            (int) sizeof(Value),\n            gen_mode,\n            entropy_reduction,\n            begin_bit,\n            end_bit,\n            g_num_rand_samples);\n\n    // Set shared memory config\n    cudaDeviceSetSharedMemConfig(SMEM_CONFIG);\n\n    // Run kernel\n    Kernel<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, DESCENDING, BLOCKED_OUTPUT><<<1, BLOCK_THREADS>>>(\n        d_keys, d_values, begin_bit, end_bit, d_elapsed);\n\n    // Flush kernel output / errors\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Check keys results\n    printf(\"\\tKeys: \");\n    int compare = CompareDeviceResults(h_reference_keys, d_keys, TILE_SIZE, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Check value results\n    if (!KEYS_ONLY)\n    {\n        printf(\"\\tValues: \");\n        int compare = CompareDeviceResults(h_reference_values, d_values, TILE_SIZE, g_verbose, g_verbose);\n        printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n        AssertEquals(0, compare);\n    }\n    printf(\"\\n\");\n\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n    printf(\"\\n\");\n\n    // Cleanup\n    if (h_keys)             delete[] h_keys;\n    if (h_reference_keys)   delete[] h_reference_keys;\n    if (h_values)           delete[] h_values;\n    if (h_reference_values) delete[] h_reference_values;\n    if (d_keys)             CubDebugExit(g_allocator.DeviceFree(d_keys));\n    if (d_values)           CubDebugExit(g_allocator.DeviceFree(d_values));\n    if (d_elapsed)          CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Test driver (valid tile size <= MAX_SMEM_BYTES)\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    cudaSharedMemConfig     SMEM_CONFIG,\n    bool                    DESCENDING,\n    bool                    BLOCKED_OUTPUT,\n    typename                Key,\n    typename                Value>\nvoid TestValid(Int2Type<true> fits_smem_capacity)\n{\n    // Iterate begin_bit\n    for (int begin_bit = 0; begin_bit <= 1; begin_bit++)\n    {\n        // Iterate end bit\n        for (int end_bit = begin_bit + 1; end_bit <= sizeof(Key) * 8; end_bit = end_bit * 2 + begin_bit)\n        {\n            // Uniform key distribution\n            TestDriver<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, DESCENDING, BLOCKED_OUTPUT, Key, Value>(\n                UNIFORM, 0, begin_bit, end_bit);\n\n            // Sequential key distribution\n            TestDriver<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, DESCENDING, BLOCKED_OUTPUT, Key, Value>(\n                INTEGER_SEED, 0, begin_bit, end_bit);\n\n            // Iterate random with entropy_reduction\n            for (int entropy_reduction = 0; entropy_reduction <= 9; entropy_reduction += 3)\n            {\n                TestDriver<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, DESCENDING, BLOCKED_OUTPUT, Key, Value>(\n                    RANDOM, entropy_reduction, begin_bit, end_bit);\n            }\n        }\n    }\n}\n\n\n/**\n * Test driver (invalid tile size)\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    cudaSharedMemConfig     SMEM_CONFIG,\n    bool                    DESCENDING,\n    bool                    BLOCKED_OUTPUT,\n    typename                Key,\n    typename                Value>\nvoid TestValid(Int2Type<false> fits_smem_capacity)\n{}\n\n\n/**\n * Test ascending/descending and to-blocked/to-striped\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    cudaSharedMemConfig     SMEM_CONFIG,\n    typename                Key,\n    typename                Value>\nvoid Test()\n{\n    // Check size of smem storage for the target arch to make sure it will fit\n    typedef BlockRadixSort<Key, BLOCK_THREADS, ITEMS_PER_THREAD, Value, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG> BlockRadixSortT;\n\n#if defined(SM100) || defined(SM110) || defined(SM130)\n    Int2Type<sizeof(typename BlockRadixSortT::TempStorage) <= 16 * 1024> fits_smem_capacity;\n#else\n    Int2Type<(sizeof(typename BlockRadixSortT::TempStorage) <= 48 * 1024)> fits_smem_capacity;\n#endif\n\n    // Sort-ascending, to-striped\n    TestValid<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, true, false, Key, Value>(fits_smem_capacity);\n\n    // Sort-descending, to-blocked\n    TestValid<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, false, true, Key, Value>(fits_smem_capacity);\n\n    // Not necessary\n//    TestValid<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, false, false, Key, Value>(fits_smem_capacity);\n//    TestValid<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, SMEM_CONFIG, true, true, Key, Value>(fits_smem_capacity);\n}\n\n\n/**\n * Test value type and smem config\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    typename                Key>\nvoid TestKeys()\n{\n    // Test keys-only sorting with both smem configs\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, cudaSharedMemBankSizeFourByte, Key, NullType>();    // Keys-only (4-byte smem bank config)\n#if !defined(SM100) && !defined(SM110) && !defined(SM130) && !defined(SM200)\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, cudaSharedMemBankSizeEightByte, Key, NullType>();   // Keys-only (8-byte smem bank config)\n#endif\n}\n\n\n/**\n * Test value type and smem config\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM,\n    typename                Key>\nvoid TestKeysAndPairs()\n{\n    // Test pairs sorting with only 4-byte configs\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, cudaSharedMemBankSizeFourByte, Key, char>();        // With small-values\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, cudaSharedMemBankSizeFourByte, Key, Key>();         // With same-values\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, cudaSharedMemBankSizeFourByte, Key, TestFoo>();     // With large values\n}\n\n\n/**\n * Test key type\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN,\n    BlockScanAlgorithm      INNER_SCAN_ALGORITHM>\nvoid Test()\n{\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef TEST_KEYS_ONLY\n\n    // Test unsigned types with keys-only\n    TestKeys<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, unsigned char>();\n    TestKeys<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, unsigned short>();\n    TestKeys<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, unsigned int>();\n    TestKeys<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, unsigned long>();\n    TestKeys<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, unsigned long long>();\n\n#else\n\n    // Test signed and fp types with paired values\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, char>();\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, short>();\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, int>();\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, long>();\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, long long>();\n    TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, float>();\n    if (ptx_version > 120)\n    {\n        // Don't check doubles on PTX120 or below because they're down-converted\n        TestKeysAndPairs<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, INNER_SCAN_ALGORITHM, double>();\n    }\n\n#endif\n}\n\n\n/**\n * Test inner scan algorithm\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS,\n    bool                    MEMOIZE_OUTER_SCAN>\nvoid Test()\n{\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, BLOCK_SCAN_RAKING>();\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, MEMOIZE_OUTER_SCAN, BLOCK_SCAN_WARP_SCANS>();\n}\n\n\n/**\n * Test outer scan algorithm\n */\ntemplate <\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    int                     RADIX_BITS>\nvoid Test()\n{\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, true>();\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, RADIX_BITS, false>();\n}\n\n\n/**\n * Test radix bits\n */\ntemplate <\n    int BLOCK_THREADS,\n    int ITEMS_PER_THREAD>\nvoid Test()\n{\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, 1>();\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, 2>();\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, 5>();\n}\n\n\n/**\n * Test items per thread\n */\ntemplate <int BLOCK_THREADS>\nvoid Test()\n{\n    Test<BLOCK_THREADS, 1>();\n#if defined(SM100) || defined(SM110) || defined(SM130)\n    // Open64 compiler can't handle the number of test cases\n#else\n    Test<BLOCK_THREADS, 4>();\n#endif\n    Test<BLOCK_THREADS, 11>();\n}\n\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#ifdef QUICK_TEST\n\n    {\n        typedef float T;\n        TestDriver<32, 4, 4, true, BLOCK_SCAN_WARP_SCANS, cudaSharedMemBankSizeFourByte, false, false, T, NullType>(INTEGER_SEED, 0, 0, sizeof(T) * 8);\n    }\n/*\n    // Compile/run quick tests\n    typedef unsigned int T;\n    TestDriver<64, 17, 4, true, BLOCK_SCAN_WARP_SCANS, cudaSharedMemBankSizeFourByte, false, false, T, NullType>(RANDOM, 0, 0, sizeof(T) * 8);\n    TestDriver<96, 8, 4, true, BLOCK_SCAN_WARP_SCANS, cudaSharedMemBankSizeFourByte, false, false, T, NullType>(RANDOM, 0, 0, sizeof(T) * 8);\n    TestDriver<128, 2, 4, true, BLOCK_SCAN_WARP_SCANS, cudaSharedMemBankSizeFourByte, false, false, T, NullType>(RANDOM, 0, 0, sizeof(T) * 8);\n*/\n\n#else\n\n    // Compile/run thorough tests\n    Test<32>();\n    Test<64>();\n    Test<160>();\n\n\n#endif  // QUICK_TEST\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_block_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of BlockReduce utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <device_functions.h>\n#include <typeinfo>\n\n#include <cub/block/block_reduce.cuh>\n#include <cub/block/block_load.cuh>\n#include <cub/util_ptx.cuh>\n#include <cub/util_allocator.cuh>\n#include <cub/util_debug.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose       = false;\nint                     g_repeat        = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n\n/// Generic reduction (full, 1)\ntemplate <typename BlockReduceT, typename T, typename ReductionOp>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T (&data)[1], ReductionOp &reduction_op)\n{\n    return block_reduce.Reduce(data[0], reduction_op);\n}\n\n/// Generic reduction (full, ITEMS_PER_THREAD)\ntemplate <typename BlockReduceT, typename T, int ITEMS_PER_THREAD, typename ReductionOp>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T (&data)[ITEMS_PER_THREAD], ReductionOp &reduction_op)\n{\n    return block_reduce.Reduce(data, reduction_op);\n}\n\n/// Generic reduction (partial, 1)\ntemplate <typename BlockReduceT, typename T, typename ReductionOp>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T &data, ReductionOp &reduction_op, int valid_threads)\n{\n    return block_reduce.Reduce(data, reduction_op, valid_threads);\n}\n\n/// Sum reduction (full, 1)\ntemplate <typename BlockReduceT, typename T>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T (&data)[1], Sum &reduction_op)\n{\n    return block_reduce.Sum(data[0]);\n}\n\n/// Sum reduction (full, ITEMS_PER_THREAD)\ntemplate <typename BlockReduceT, typename T, int ITEMS_PER_THREAD>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T (&data)[ITEMS_PER_THREAD], Sum &reduction_op)\n{\n    return block_reduce.Sum(data);\n}\n\n/// Sum reduction (partial, 1)\ntemplate <typename BlockReduceT, typename T>\n__device__ __forceinline__ T DeviceTest(\n    BlockReduceT &block_reduce, T &data, Sum &reduction_op, int valid_threads)\n{\n    return block_reduce.Sum(data, valid_threads);\n}\n\n\n/**\n * Test full-tile reduction kernel (where num_items is an even\n * multiple of BLOCK_THREADS)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    int                     ITEMS_PER_THREAD,\n    typename                T,\n    typename                ReductionOp>\n__launch_bounds__ (BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)\n__global__ void FullTileReduceKernel(\n    T                       *d_in,\n    T                       *d_out,\n    ReductionOp             reduction_op,\n    int                     tiles,\n    clock_t                 *d_elapsed)\n{\n    const int BLOCK_THREADS     = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z;\n    const int TILE_SIZE         = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Cooperative thread block reduction utility type (returns aggregate in thread 0)\n    typedef BlockReduce<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z> BlockReduceT;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename BlockReduceT::TempStorage temp_storage;\n\n    int linear_tid = RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n\n    // Per-thread tile data\n    T data[ITEMS_PER_THREAD];\n\n    // Load first tile of data\n    int block_offset = 0;\n\n    if (block_offset < TILE_SIZE * tiles)\n    {\n        LoadDirectBlocked(linear_tid, d_in + block_offset, data);\n        block_offset += TILE_SIZE;\n\n        // Start cycle timer\n        clock_t start = clock();\n\n        // Cooperative reduce first tile\n        BlockReduceT block_reduce(temp_storage) ;\n        T block_aggregate = DeviceTest(block_reduce, data, reduction_op);\n\n        // Stop cycle timer\n #if CUB_PTX_ARCH == 100\n        // Bug: recording stop clock causes mis-write of running prefix value\n        clock_t stop = 0;\n#else\n        clock_t stop = clock();\n#endif // CUB_PTX_ARCH == 100\n        clock_t elapsed = (start > stop) ? start - stop : stop - start;\n\n        // Loop over input tiles\n        while (block_offset < TILE_SIZE * tiles)\n        {\n            // TestBarrier between thread block reductions\n            __syncthreads();\n    \n            // Load tile of data\n            LoadDirectBlocked(linear_tid, d_in + block_offset, data);\n            block_offset += TILE_SIZE;\n\n            // Start cycle timer\n            clock_t start = clock();\n\n            // Cooperatively reduce the tile's aggregate\n            BlockReduceT block_reduce(temp_storage) ;\n            T tile_aggregate = DeviceTest(block_reduce, data, reduction_op);\n\n            // Stop cycle timer\n#if CUB_PTX_ARCH == 100\n            // Bug: recording stop clock causes mis-write of running prefix value\n            clock_t stop = 0;\n#else\n            clock_t stop = clock();\n#endif // CUB_PTX_ARCH == 100\n            elapsed += (start > stop) ? start - stop : stop - start;\n\n            // Reduce thread block aggregate\n            block_aggregate = reduction_op(block_aggregate, tile_aggregate);\n        }\n\n        // Store data\n        if (linear_tid == 0)\n        {\n            d_out[0] = block_aggregate;\n            *d_elapsed = elapsed;\n        }\n    }\n}\n\n\n\n/**\n * Test partial-tile reduction kernel (where num_items < BLOCK_THREADS)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    typename                T,\n    typename                ReductionOp>\n__launch_bounds__ (BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)\n__global__ void PartialTileReduceKernel(\n    T                       *d_in,\n    T                       *d_out,\n    int                     num_items,\n    ReductionOp             reduction_op,\n    clock_t                 *d_elapsed)\n{\n    // Cooperative thread block reduction utility type (returns aggregate only in thread-0)\n    typedef BlockReduce<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z> BlockReduceT;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename BlockReduceT::TempStorage temp_storage;\n\n    int linear_tid = RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n\n    // Per-thread tile data\n    T partial;\n\n    // Load partial tile data\n    if (linear_tid < num_items)\n    {\n        partial = d_in[linear_tid];\n    }\n\n    // Start cycle timer\n    clock_t start = clock();\n\n    // Cooperatively reduce the tile's aggregate\n    BlockReduceT block_reduce(temp_storage) ;\n    T tile_aggregate = DeviceTest(block_reduce, partial, reduction_op, num_items);\n\n    // Stop cycle timer\n#if CUB_PTX_ARCH == 100\n    // Bug: recording stop clock causes mis-write of running prefix value\n    clock_t stop = 0;\n#else\n    clock_t stop = clock();\n#endif // CUB_PTX_ARCH == 100\n\n    clock_t elapsed = (start > stop) ? start - stop : stop - start;\n\n    // Store data\n    if (linear_tid == 0)\n    {\n        d_out[0] = tile_aggregate;\n        *d_elapsed = elapsed;\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Host utility subroutines\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem (and solution)\n */\ntemplate <\n    typename    T,\n    typename    ReductionOp>\nvoid Initialize(\n    GenMode     gen_mode,\n    T           *h_in,\n    T           h_reference[1],\n    ReductionOp reduction_op,\n    int         num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n        if (i == 0)\n            h_reference[0] = h_in[0];\n        else\n            h_reference[0] = reduction_op(h_reference[0], h_in[i]);\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\");\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Full tile test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Test full-tile reduction.  (Specialized for sufficient resources)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    int                     ITEMS_PER_THREAD,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    int                     tiles,\n    ReductionOp             reduction_op,\n    Int2Type<true>          sufficient_resources)\n{\n    const int BLOCK_THREADS     = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z;\n    const int TILE_SIZE         = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    int num_items = TILE_SIZE * tiles;\n\n    // Allocate host arrays\n    T *h_in = new T[num_items];\n    T h_reference[1];\n\n    // Initialize problem\n    Initialize(gen_mode, h_in, h_reference, reduction_op, num_items);\n\n    // Initialize/clear device arrays\n    T       *d_in = NULL;\n    T       *d_out = NULL;\n    clock_t *d_elapsed = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(unsigned long long)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * 1));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * 1));\n\n    // Test multi-tile (unguarded)\n    printf(\"TestFullTile %s, %s, gen-mode %d, num_items(%d), BLOCK_THREADS(%d) (%d,%d,%d), ITEMS_PER_THREAD(%d), tiles(%d), %s (%d bytes) elements:\\n\",\n        Equals<ReductionOp, Sum>::VALUE ? \"Sum\" : \"Max\",\n        (ALGORITHM == BLOCK_REDUCE_RAKING) ? \"BLOCK_REDUCE_RAKING\" : (ALGORITHM == BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY) ? \"BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY\" : \"BLOCK_REDUCE_WARP_REDUCTIONS\",\n        gen_mode,\n        num_items,\n        BLOCK_THREADS, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z,\n        ITEMS_PER_THREAD,\n        tiles,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    dim3 block_dims(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n    FullTileReduceKernel<ALGORITHM, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, ITEMS_PER_THREAD><<<1, block_dims>>>(\n        d_in,\n        d_out,\n        reduction_op,\n        tiles,\n        d_elapsed);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tReduction results: \");\n    int compare = CompareDeviceResults(h_reference, d_out, 1, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Test full-tile reduction.  (Specialized for insufficient resources)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    int                     ITEMS_PER_THREAD,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    int                     tiles,\n    ReductionOp             reduction_op,\n    Int2Type<false>         sufficient_resources)\n{}\n\n\n/**\n * Test full-tile reduction.\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    int                     ITEMS_PER_THREAD,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    int                     tiles,\n    ReductionOp             reduction_op)\n{\n    // Check size of smem storage for the target arch to make sure it will fit\n    typedef BlockReduce<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z, TEST_ARCH> BlockReduceT;\n\n    enum \n    {\n#if defined(SM100) || defined(SM110) || defined(SM130)\n        sufficient_smem       = (sizeof(typename BlockReduceT::TempStorage) <= 16 * 1024),\n        sufficient_threads    = ((BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z) <= 512),\n#else\n        sufficient_smem       = (sizeof(typename BlockReduceT::TempStorage) <= 48 * 1024),\n        sufficient_threads    = ((BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z) <= 1024),\n#endif\n    };\n\n    TestFullTile<ALGORITHM, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, ITEMS_PER_THREAD, T>(gen_mode, tiles, reduction_op, Int2Type<sufficient_smem && sufficient_threads>());\n}\n\n\n/**\n * Run battery of tests for different thread block dimensions\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_THREADS,\n    int                     ITEMS_PER_THREAD,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    int                     tiles,\n    ReductionOp             reduction_op)\n{\n    TestFullTile<ALGORITHM, BLOCK_THREADS, 1, 1, ITEMS_PER_THREAD, T>(gen_mode, tiles, reduction_op);\n    TestFullTile<ALGORITHM, BLOCK_THREADS, 2, 2, ITEMS_PER_THREAD, T>(gen_mode, tiles, reduction_op);\n}\n\n/**\n * Run battery of tests for different thread items\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_THREADS,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    int                     tiles,\n    ReductionOp             reduction_op)\n{\n    TestFullTile<ALGORITHM, BLOCK_THREADS, 1, T>(gen_mode, tiles, reduction_op);\n    TestFullTile<ALGORITHM, BLOCK_THREADS, 4, T>(gen_mode, tiles, reduction_op);\n}\n\n\n/**\n * Run battery of full-tile tests for different numbers of tiles\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_THREADS,\n    typename                T,\n    typename                ReductionOp>\nvoid TestFullTile(\n    GenMode                 gen_mode,\n    ReductionOp             reduction_op)\n{\n    for (int tiles = 1; tiles < 3; tiles++)\n    {\n        TestFullTile<ALGORITHM, BLOCK_THREADS, T>(gen_mode, tiles, reduction_op);\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Partial-tile test generation\n//---------------------------------------------------------------------\n\n/**\n * Test partial-tile reduction.  (Specialized for sufficient resources)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    typename                T,\n    typename                ReductionOp>\nvoid TestPartialTile(\n    GenMode                 gen_mode,\n    int                     num_items,\n    ReductionOp             reduction_op,\n    Int2Type<true>          sufficient_resources)\n{\n    const int BLOCK_THREADS     = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z;\n    const int TILE_SIZE         = BLOCK_THREADS;\n\n    // Allocate host arrays\n    T *h_in = new T[num_items];\n    T h_reference[1];\n\n    // Initialize problem\n    Initialize(gen_mode, h_in, h_reference, reduction_op, num_items);\n\n    // Initialize/clear device arrays\n    T       *d_in = NULL;\n    T       *d_out = NULL;\n    clock_t *d_elapsed = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(unsigned long long)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * TILE_SIZE));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * 1));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * 1));\n\n    printf(\"TestPartialTile %s, gen-mode %d, num_items(%d), BLOCK_THREADS(%d) (%d,%d,%d), %s (%d bytes) elements:\\n\",\n        (ALGORITHM == BLOCK_REDUCE_RAKING) ? \"BLOCK_REDUCE_RAKING\" : (ALGORITHM == BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY) ? \"BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY\" : \"BLOCK_REDUCE_WARP_REDUCTIONS\",\n        gen_mode,\n        num_items,\n        BLOCK_THREADS, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    dim3 block_dims(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n    PartialTileReduceKernel<ALGORITHM, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z><<<1, block_dims>>>(\n        d_in,\n        d_out,\n        num_items,\n        reduction_op,\n        d_elapsed);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tReduction results: \");\n    int compare = CompareDeviceResults(h_reference, d_out, 1, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n\n/**\n * Test partial-tile reduction (specialized for insufficient resources)\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    typename                T,\n    typename                ReductionOp>\nvoid TestPartialTile(\n    GenMode                 gen_mode,\n    int                     num_items,\n    ReductionOp             reduction_op,\n    Int2Type<false>         sufficient_resources)\n{}\n\n\n/**\n *  Run battery of partial-tile tests for different numbers of effective threads and thread dimensions\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_DIM_X,\n    int                     BLOCK_DIM_Y,\n    int                     BLOCK_DIM_Z,\n    typename                T,\n    typename                ReductionOp>\nvoid TestPartialTile(\n    GenMode                 gen_mode,\n    int                     num_items,\n    ReductionOp             reduction_op)\n{\n    // Check size of smem storage for the target arch to make sure it will fit\n    typedef BlockReduce<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z, TEST_ARCH> BlockReduceT;\n\n    enum \n    {\n#if defined(SM100) || defined(SM110) || defined(SM130)\n        sufficient_smem       = sizeof(typename BlockReduceT::TempStorage)  <= 16 * 1024,\n        sufficient_threads    = (BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)   <= 512,\n#else\n        sufficient_smem       = sizeof(typename BlockReduceT::TempStorage)  <= 48 * 1024,\n        sufficient_threads    = (BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)   <= 1024,\n#endif\n    };\n\n    TestPartialTile<ALGORITHM, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, T>(gen_mode, num_items, reduction_op, Int2Type<sufficient_smem && sufficient_threads>());\n}\n\n\n\n/**\n *  Run battery of partial-tile tests for different numbers of effective threads and thread dimensions\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_THREADS,\n    typename                T,\n    typename                ReductionOp>\nvoid TestPartialTile(\n    GenMode                 gen_mode,\n    ReductionOp             reduction_op)\n{\n    for (\n        int num_items = 1;\n        num_items < BLOCK_THREADS;\n        num_items += CUB_MAX(1, BLOCK_THREADS / 5))\n    {\n        TestPartialTile<ALGORITHM, BLOCK_THREADS, 1, 1, T>(gen_mode, num_items, reduction_op);\n        TestPartialTile<ALGORITHM, BLOCK_THREADS, 2, 2, T>(gen_mode, num_items, reduction_op);\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Run battery of full-tile tests for different gen modes\n */\ntemplate <\n    BlockReduceAlgorithm    ALGORITHM,\n    int                     BLOCK_THREADS,\n    typename                T,\n    typename                ReductionOp>\nvoid Test(\n    ReductionOp             reduction_op)\n{\n    TestFullTile<ALGORITHM, BLOCK_THREADS, T>(UNIFORM, reduction_op);\n    TestPartialTile<ALGORITHM, BLOCK_THREADS, T>(UNIFORM, reduction_op);\n\n    TestFullTile<ALGORITHM, BLOCK_THREADS, T>(INTEGER_SEED, reduction_op);\n    TestPartialTile<ALGORITHM, BLOCK_THREADS, T>(INTEGER_SEED, reduction_op);\n\n    if (Traits<T>::CATEGORY != FLOATING_POINT)\n    {\n        // Don't test randomly-generated floats b/c of stability\n        TestFullTile<ALGORITHM, BLOCK_THREADS, T>(RANDOM, reduction_op);\n        TestPartialTile<ALGORITHM, BLOCK_THREADS, T>(RANDOM, reduction_op);\n    }\n}\n\n\n/**\n * Run battery of tests for different block-reduction algorithmic variants\n */\ntemplate <\n    int             BLOCK_THREADS,\n    typename        T,\n    typename        ReductionOp>\nvoid Test(\n    ReductionOp     reduction_op)\n{\n#ifdef TEST_RAKING\n    Test<BLOCK_REDUCE_RAKING, BLOCK_THREADS, T>(reduction_op);\n    Test<BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY, BLOCK_THREADS, T>(reduction_op);\n#endif\n#ifdef TEST_WARP_REDUCTIONS\n    Test<BLOCK_REDUCE_WARP_REDUCTIONS, BLOCK_THREADS, T>(reduction_op);\n#endif\n}\n\n\n/**\n * Run battery of tests for different block sizes\n */\ntemplate <\n    typename        T,\n    typename        ReductionOp>\nvoid Test(\n    ReductionOp     reduction_op)\n{\n    Test<7,   T>(reduction_op);\n    Test<32,  T>(reduction_op);\n    Test<63,  T>(reduction_op);\n    Test<97,  T>(reduction_op);\n    Test<128, T>(reduction_op);\n    Test<238, T>(reduction_op);\n}\n\n\n/**\n * Run battery of tests for different block sizes\n */\ntemplate <typename T>\nvoid Test()\n{\n    Test<T>(Sum());\n    Test<T>(Max());\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef QUICK_TEST\n\n    // Compile/run quick tests\n\n\n    printf(\"\\n full tile ------------------------\\n\\n\");\n\n    TestFullTile<BLOCK_REDUCE_RAKING,                   128, 1, 1, 4, int>(RANDOM, 1, Sum());\n    TestFullTile<BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY,  128, 1, 1, 4, int>(RANDOM, 1, Sum());\n    TestFullTile<BLOCK_REDUCE_WARP_REDUCTIONS,          128, 1, 1, 4, int>(RANDOM, 1, Sum());\n\n    TestFullTile<BLOCK_REDUCE_RAKING,                   128, 1, 1, 1, int>(RANDOM, 1, Sum());\n    TestFullTile<BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY,  128, 1, 1, 1, int>(RANDOM, 1, Sum());\n    TestFullTile<BLOCK_REDUCE_WARP_REDUCTIONS,          128, 1, 1, 1, int>(RANDOM, 1, Sum());\n\n    printf(\"\\n partial tile ------------------------\\n\\n\");\n\n    TestPartialTile<BLOCK_REDUCE_RAKING,                   128, 1, 1, int>(RANDOM, 7, Sum());\n    TestPartialTile<BLOCK_REDUCE_RAKING_COMMUTATIVE_ONLY,  128, 1, 1, int>(RANDOM, 7, Sum());\n    TestPartialTile<BLOCK_REDUCE_WARP_REDUCTIONS,          128, 1, 1, int>(RANDOM, 7, Sum());\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // primitives\n        Test<char>();\n        Test<short>();\n        Test<int>();\n        Test<long long>();\n        if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n            Test<double>();\n\n        Test<float>();\n\n        // vector types\n        Test<char2>();\n        Test<short2>();\n        Test<int2>();\n        Test<longlong2>();\n\n        Test<char4>();\n        Test<short4>();\n        Test<int4>();\n        Test<longlong4>();\n\n        // Complex types\n        Test<TestFoo>();\n        Test<TestBar>();\n    }\n\n#endif\n\n    return 0;\n}\n\n\n"
  },
  {
    "path": "external/cub/test/test_block_scan.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of BlockScan utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <iostream>\n#include <limits>\n#include <typeinfo>\n\n#include <cub/block/block_scan.cuh>\n#include <cub/block/block_load.cuh>\n#include <cub/block/block_store.cuh>\n#include <cub/util_ptx.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose       = false;\nint                     g_repeat        = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n/**\n * Primitive variant to test\n */\nenum TestMode\n{\n    BASIC,\n    AGGREGATE,\n    PREFIX,\n};\n\n\n/**\n * Scan mode to test\n */\nenum ScanMode\n{\n    EXCLUSIVE,\n    INCLUSIVE\n};\n\n\n/**\n * \\brief WrapperFunctor (for precluding test-specialized dispatch to *Sum variants)\n */\ntemplate<typename OpT>\nstruct WrapperFunctor\n{\n    OpT op;\n\n    WrapperFunctor(OpT op) : op(op) {}\n\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return op(a, b);\n    }\n};\n\n\n/**\n * Stateful prefix functor\n */\ntemplate <\n    typename T,\n    typename ScanOpT>\nstruct BlockPrefixCallbackOp\n{\n    int     linear_tid;\n    T       prefix;\n    ScanOpT  scan_op;\n\n    __device__ __forceinline__\n    BlockPrefixCallbackOp(int linear_tid, T prefix, ScanOpT scan_op) :\n        linear_tid(linear_tid),\n        prefix(prefix),\n        scan_op(scan_op)\n    {}\n\n    __device__ __forceinline__\n    T operator()(T block_aggregate)\n    {\n        // For testing purposes\n        T retval = (linear_tid == 0) ? prefix  : T();\n        prefix = scan_op(prefix, block_aggregate);\n        return retval;\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Exclusive scan\n//---------------------------------------------------------------------\n\n/// Exclusive scan (BASIC, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data[0], data[0], initial_value, scan_op);\n}\n\n/// Exclusive scan (BASIC, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data, data, initial_value, scan_op);\n}\n\n/// Exclusive scan (AGGREGATE, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data[0], data[0], initial_value, scan_op, block_aggregate);\n}\n\n/// Exclusive scan (AGGREGATE, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data, data, initial_value, scan_op, block_aggregate);\n}\n\n/// Exclusive scan (PREFIX, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data[0], data[0], scan_op, prefix_op);\n}\n\n/// Exclusive scan (PREFIX, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.ExclusiveScan(data, data, scan_op, prefix_op);\n}\n\n\n//---------------------------------------------------------------------\n// Exclusive sum\n//---------------------------------------------------------------------\n\n/// Exclusive sum (BASIC, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data[0], data[0]);\n}\n\n/// Exclusive sum (BASIC, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data, data);\n}\n\n/// Exclusive sum (AGGREGATE, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data[0], data[0], block_aggregate);\n}\n\n/// Exclusive sum (AGGREGATE, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data, data, block_aggregate);\n}\n\n/// Exclusive sum (PREFIX, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data[0], data[0], prefix_op);\n}\n\n/// Exclusive sum (PREFIX, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<EXCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.ExclusiveSum(data, data, prefix_op);\n}\n\n\n//---------------------------------------------------------------------\n// Inclusive scan\n//---------------------------------------------------------------------\n\n/// Inclusive scan (BASIC, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data[0], data[0], scan_op);\n}\n\n/// Inclusive scan (BASIC, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data, data, scan_op);\n}\n\n/// Inclusive scan (AGGREGATE, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data[0], data[0], scan_op, block_aggregate);\n}\n\n/// Inclusive scan (AGGREGATE, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data, data, scan_op, block_aggregate);\n}\n\n/// Inclusive scan (PREFIX, 1)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data[0], data[0], scan_op, prefix_op);\n}\n\n/// Inclusive scan (PREFIX, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename ScanOpT, typename PrefixCallbackOp, int ITEMS_PER_THREAD, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, ScanOpT &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, IsPrimitiveT is_primitive)\n{\n    block_scan.InclusiveScan(data, data, scan_op, prefix_op);\n}\n\n\n//---------------------------------------------------------------------\n// Inclusive sum\n//---------------------------------------------------------------------\n\n/// Inclusive sum (BASIC, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data[0], data[0]);\n}\n\n/// Inclusive sum (BASIC, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<BASIC> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data, data);\n}\n\n/// Inclusive sum (AGGREGATE, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data[0], data[0], block_aggregate);\n}\n\n/// Inclusive sum (AGGREGATE, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<AGGREGATE> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data, data, block_aggregate);\n}\n\n/// Inclusive sum (PREFIX, 1)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[1], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data[0], data[0], prefix_op);\n}\n\n/// Inclusive sum (PREFIX, ITEMS_PER_THREAD)\ntemplate <typename BlockScanT, typename T, typename PrefixCallbackOp, int ITEMS_PER_THREAD>\n__device__ __forceinline__ void DeviceTest(\n    BlockScanT &block_scan, T (&data)[ITEMS_PER_THREAD], T &initial_value, Sum &scan_op, T &block_aggregate, PrefixCallbackOp &prefix_op,\n    Int2Type<INCLUSIVE> scan_mode, Int2Type<PREFIX> test_mode, Int2Type<true> is_primitive)\n{\n    block_scan.InclusiveSum(data, data, prefix_op);\n}\n\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/**\n * BlockScan test kernel.\n */\ntemplate <\n    int                 BLOCK_DIM_X,\n    int                 BLOCK_DIM_Y,\n    int                 BLOCK_DIM_Z,\n    int                 ITEMS_PER_THREAD,\n    ScanMode            SCAN_MODE,\n    TestMode            TEST_MODE,\n    BlockScanAlgorithm  ALGORITHM,\n    typename            T,\n    typename            ScanOpT>\n__launch_bounds__ (BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)\n__global__ void BlockScanKernel(\n    T                   *d_in,\n    T                   *d_out,\n    T                   *d_aggregate,\n    ScanOpT              scan_op,\n    T                   initial_value,\n    clock_t             *d_elapsed)\n{\n    const int BLOCK_THREADS     = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z;\n    const int TILE_SIZE         = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Parameterize BlockScan type for our thread block\n    typedef BlockScan<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z> BlockScanT;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename BlockScanT::TempStorage temp_storage;\n\n    int linear_tid = RowMajorTid(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n\n    // Per-thread tile data\n    T data[ITEMS_PER_THREAD];\n    LoadDirectBlocked(linear_tid, d_in, data);\n\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Test scan\n    T                                   block_aggregate;\n    BlockScanT                          block_scan(temp_storage);\n    BlockPrefixCallbackOp<T, ScanOpT>   prefix_op(linear_tid, initial_value, scan_op);\n\n    DeviceTest(block_scan, data, initial_value, scan_op, block_aggregate, prefix_op,\n        Int2Type<SCAN_MODE>(), Int2Type<TEST_MODE>(), Int2Type<Traits<T>::PRIMITIVE>());\n\n    // Stop cycle timer\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Store output\n    StoreDirectBlocked(linear_tid, d_out, data);\n\n    // Store block_aggregate\n    if (TEST_MODE != BASIC)\n        d_aggregate[linear_tid] = block_aggregate;\n\n    // Store prefix\n    if (TEST_MODE == PREFIX)\n    {\n        if (linear_tid == 0)\n            d_out[TILE_SIZE] = prefix_op.prefix;\n    }\n\n    // Store time\n    if (linear_tid == 0)\n        *d_elapsed = (start > stop) ? start - stop : stop - start;\n}\n\n\n\n//---------------------------------------------------------------------\n// Host utility subroutines\n//---------------------------------------------------------------------\n\n/**\n * Initialize exclusive-scan problem (and solution)\n */\ntemplate <typename T, typename ScanOpT>\nT Initialize(\n    GenMode     gen_mode,\n    T           *h_in,\n    T           *h_reference,\n    int         num_items,\n    ScanOpT     scan_op,\n    T           initial_value,\n    Int2Type<EXCLUSIVE>)\n{\n    InitValue(gen_mode, h_in[0], 0);\n\n    T block_aggregate   = h_in[0];\n    h_reference[0]      = initial_value;\n    T inclusive         = scan_op(initial_value, h_in[0]);\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n        h_reference[i] = inclusive;\n        inclusive = scan_op(inclusive, h_in[i]);\n        block_aggregate = scan_op(block_aggregate, h_in[i]);\n    }\n\n    return block_aggregate;\n}\n\n\n/**\n * Initialize inclusive-scan problem (and solution)\n */\ntemplate <typename T, typename ScanOpT>\nT Initialize(\n    GenMode     gen_mode,\n    T           *h_in,\n    T           *h_reference,\n    int         num_items,\n    ScanOpT      scan_op,\n    T           initial_value,\n    Int2Type<INCLUSIVE>)\n{\n    InitValue(gen_mode, h_in[0], 0);\n\n    T block_aggregate   = h_in[0];\n    T inclusive         = scan_op(initial_value, h_in[0]);\n    h_reference[0]      = inclusive;\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n        inclusive = scan_op(inclusive, h_in[i]);\n        block_aggregate = scan_op(block_aggregate, h_in[i]);\n        h_reference[i] = inclusive;\n    }\n\n    return block_aggregate;\n}\n\n\n/**\n * Test thread block scan.  (Specialized for sufficient resources)\n */\ntemplate <\n    int                 BLOCK_DIM_X,\n    int                 BLOCK_DIM_Y,\n    int                 BLOCK_DIM_Z,\n    int                 ITEMS_PER_THREAD,\n    ScanMode            SCAN_MODE,\n    TestMode            TEST_MODE,\n    BlockScanAlgorithm  ALGORITHM,\n    typename            ScanOpT,\n    typename            T>\nvoid Test(\n    GenMode             gen_mode,\n    ScanOpT             scan_op,\n    T                   initial_value,\n    Int2Type<true>      sufficient_resources)\n{\n    const int BLOCK_THREADS     = BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z;\n    const int TILE_SIZE         = BLOCK_THREADS * ITEMS_PER_THREAD;\n\n    // Allocate host arrays\n    T *h_in = new T[TILE_SIZE];\n    T *h_reference = new T[TILE_SIZE];\n    T *h_aggregate = new T[BLOCK_THREADS];\n\n    // Initialize problem\n    T block_aggregate = Initialize(\n        gen_mode,\n        h_in,\n        h_reference,\n        TILE_SIZE,\n        scan_op,\n        initial_value,\n        Int2Type<SCAN_MODE>());\n\n    // Test reference block_aggregate is returned in all threads\n    for (int i = 0; i < BLOCK_THREADS; ++i)\n    {\n        h_aggregate[i] = block_aggregate;\n    }\n\n    // Run kernel\n    printf(\"Test-mode %d, gen-mode %d, policy %d, %s %s BlockScan, %d (%d,%d,%d) thread block threads, %d items per thread, %d tile size, %s (%d bytes) elements:\\n\",\n        TEST_MODE, gen_mode, ALGORITHM,\n        (SCAN_MODE == INCLUSIVE) ? \"Inclusive\" : \"Exclusive\", typeid(ScanOpT).name(),\n        BLOCK_THREADS, BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z,\n        ITEMS_PER_THREAD,  TILE_SIZE,\n        typeid(T).name(), (int) sizeof(T));\n    fflush(stdout);\n\n    // Initialize/clear device arrays\n    T       *d_in = NULL;\n    T       *d_out = NULL;\n    T       *d_aggregate = NULL;\n    clock_t *d_elapsed = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(unsigned long long)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * TILE_SIZE));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * (TILE_SIZE + 2)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_aggregate, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * TILE_SIZE, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * (TILE_SIZE + 1)));\n    CubDebugExit(cudaMemset(d_aggregate, 0, sizeof(T) * BLOCK_THREADS));\n\n    // Display input problem data\n    if (g_verbose)\n    {\n        printf(\"Input data: \");\n        for (int i = 0; i < TILE_SIZE; i++)\n        {\n            std::cout << CoutCast(h_in[i]) << \", \";\n        }\n        printf(\"\\n\\n\");\n    }\n\n    // Run block_aggregate/prefix kernel\n    dim3 block_dims(BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z);\n    BlockScanKernel<BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, ALGORITHM><<<1, block_dims>>>(\n        d_in,\n        d_out,\n        d_aggregate,\n        scan_op,\n        initial_value,\n        d_elapsed);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tScan results: \");\n    int compare = CompareDeviceResults(h_reference, d_out, TILE_SIZE, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    if (TEST_MODE == AGGREGATE)\n    {\n        // Copy out and display block_aggregate\n        printf(\"\\tScan block aggregate: \");\n        compare = CompareDeviceResults(h_aggregate, d_aggregate, BLOCK_THREADS, g_verbose, g_verbose);\n        printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n        AssertEquals(0, compare);\n    }\n\n    if (TEST_MODE == PREFIX)\n    {\n        // Copy out and display updated prefix\n        printf(\"\\tScan running total: \");\n        T running_total = scan_op(initial_value, block_aggregate);\n        compare = CompareDeviceResults(&running_total, d_out + TILE_SIZE, 1, g_verbose, g_verbose);\n        printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n        AssertEquals(0, compare);\n    }\n\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (h_aggregate) delete[] h_aggregate;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_aggregate) CubDebugExit(g_allocator.DeviceFree(d_aggregate));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Test thread block scan.  (Specialized for insufficient resources)\n */\ntemplate <\n    int                 BLOCK_DIM_X,\n    int                 BLOCK_DIM_Y,\n    int                 BLOCK_DIM_Z,\n    int                 ITEMS_PER_THREAD,\n    ScanMode            SCAN_MODE,\n    TestMode            TEST_MODE,\n    BlockScanAlgorithm  ALGORITHM,\n    typename            ScanOpT,\n    typename            T>\nvoid Test(\n    GenMode             gen_mode,\n    ScanOpT             scan_op,\n    T                   initial_value,\n    Int2Type<false>     sufficient_resources)\n{}\n\n\n/**\n * Test thread block scan.\n */\ntemplate <\n    int                 BLOCK_DIM_X,\n    int                 BLOCK_DIM_Y,\n    int                 BLOCK_DIM_Z,\n    int                 ITEMS_PER_THREAD,\n    ScanMode            SCAN_MODE,\n    TestMode            TEST_MODE,\n    BlockScanAlgorithm  ALGORITHM,\n    typename            ScanOpT,\n    typename            T>\nvoid Test(\n    GenMode             gen_mode,\n    ScanOpT             scan_op,\n    T                   initial_value)\n{\n    // Check size of smem storage for the target arch to make sure it will fit\n    typedef BlockScan<T, BLOCK_DIM_X, ALGORITHM, BLOCK_DIM_Y, BLOCK_DIM_Z> BlockScanT;\n\n    enum\n    {\n#if defined(SM100) || defined(SM110) || defined(SM130)\n        sufficient_smem         = (sizeof(typename BlockScanT::TempStorage)     <= 16 * 1024),\n        sufficient_threads      = ((BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)    <= 512),\n#else\n        sufficient_smem         = (sizeof(typename BlockScanT::TempStorage)     <= 16 * 1024),\n        sufficient_threads      = ((BLOCK_DIM_X * BLOCK_DIM_Y * BLOCK_DIM_Z)    <= 1024),\n#endif\n\n#if defined(_WIN32) || defined(_WIN64)\n        // Accommodate ptxas crash bug (access violation) on Windows\n        special_skip            = ((TEST_ARCH <= 130) && (Equals<T, TestBar>::VALUE) && (BLOCK_DIM_Z > 1)),\n#else\n        special_skip            = false,\n#endif\n        sufficient_resources    = (sufficient_smem && sufficient_threads && !special_skip),\n    };\n\n    Test<BLOCK_DIM_X, BLOCK_DIM_Y, BLOCK_DIM_Z, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, ALGORITHM>(\n        gen_mode, scan_op, initial_value, Int2Type<sufficient_resources>());\n}\n\n\n\n/**\n * Run test for different thread block dimensions\n */\ntemplate <\n    int                 BLOCK_THREADS,\n    int                 ITEMS_PER_THREAD,\n    ScanMode            SCAN_MODE,\n    TestMode            TEST_MODE,\n    BlockScanAlgorithm  ALGORITHM,\n    typename            ScanOpT,\n    typename            T>\nvoid Test(\n    GenMode     gen_mode,\n    ScanOpT     scan_op,\n    T           initial_value)\n{\n    Test<BLOCK_THREADS, 1, 1, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, ALGORITHM>(gen_mode, scan_op, initial_value);\n    Test<BLOCK_THREADS, 2, 2, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, ALGORITHM>(gen_mode, scan_op, initial_value);\n}\n\n\n/**\n * Run test for different policy types\n */\ntemplate <\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD,\n    ScanMode    SCAN_MODE,\n    TestMode    TEST_MODE,\n    typename    ScanOpT,\n    typename    T>\nvoid Test(\n    GenMode     gen_mode,\n    ScanOpT     scan_op,\n    T           initial_value)\n{\n#ifdef TEST_RAKING\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, BLOCK_SCAN_RAKING>(gen_mode, scan_op, initial_value);\n#endif\n#ifdef TEST_RAKING_MEMOIZE\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, BLOCK_SCAN_RAKING_MEMOIZE>(gen_mode, scan_op, initial_value);\n#endif\n#ifdef TEST_WARP_SCANS\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, SCAN_MODE, TEST_MODE, BLOCK_SCAN_WARP_SCANS>(gen_mode, scan_op, initial_value);\n#endif\n}\n\n\n/**\n * Run tests for different primitive variants\n */\ntemplate <\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD,\n    typename    ScanOpT,\n    typename    T>\nvoid Test(\n    GenMode     gen_mode,\n    ScanOpT     scan_op,\n    T           identity,\n    T           initial_value)\n{\n    // Exclusive (use identity as initial value because it will dispatch to *Sum variants that don't take initial values)\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, BASIC>(gen_mode, scan_op, identity);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, AGGREGATE>(gen_mode, scan_op, identity);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, PREFIX>(gen_mode, scan_op, identity);\n\n    // Exclusive (non-specialized, so we can use initial-value)\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, BASIC>(gen_mode, WrapperFunctor<ScanOpT>(scan_op), initial_value);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, AGGREGATE>(gen_mode, WrapperFunctor<ScanOpT>(scan_op), initial_value);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, EXCLUSIVE, PREFIX>(gen_mode, WrapperFunctor<ScanOpT>(scan_op), initial_value);\n\n    // Inclusive\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, INCLUSIVE, BASIC>(gen_mode, scan_op, identity);      // This scan doesn't take an initial value\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, INCLUSIVE, AGGREGATE>(gen_mode, scan_op, identity);  // This scan doesn't take an initial value\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD, INCLUSIVE, PREFIX>(gen_mode, scan_op, initial_value);\n}\n\n\n/**\n * Run tests for different problem-generation options\n */\ntemplate <\n    int         BLOCK_THREADS,\n    int         ITEMS_PER_THREAD,\n    typename    ScanOpT,\n    typename    T>\nvoid Test(\n    ScanOpT     scan_op,\n    T           identity,\n    T           initial_value)\n{\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(UNIFORM, scan_op, identity, initial_value);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(INTEGER_SEED, scan_op, identity, initial_value);\n\n    // Don't test randomly-generated floats b/c of stability\n    if (Traits<T>::CATEGORY != FLOATING_POINT)\n        Test<BLOCK_THREADS, ITEMS_PER_THREAD>(RANDOM, scan_op, identity, initial_value);\n}\n\n\n/**\n * Run tests for different data types and scan ops\n */\ntemplate <\n    int BLOCK_THREADS,\n    int ITEMS_PER_THREAD>\nvoid Test()\n{\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n    // primitive\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), (unsigned char) 0, (unsigned char) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), (unsigned short) 0, (unsigned short) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), (unsigned int) 0, (unsigned int) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), (unsigned long long) 0, (unsigned long long) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), (float) 0, (float) 99);\n\n    // primitive (alternative scan op)\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Max(), std::numeric_limits<char>::min(), (char) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Max(), std::numeric_limits<short>::min(), (short) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Max(), std::numeric_limits<int>::min(), (int) 99);\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Max(), std::numeric_limits<long long>::min(), (long long) 99);\n\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Max(), std::numeric_limits<double>::max() * -1, (double) 99);\n\n    // vec-1\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_uchar1(0), make_uchar1(17));\n\n    // vec-2\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_uchar2(0, 0), make_uchar2(17, 21));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_ushort2(0, 0), make_ushort2(17, 21));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_uint2(0, 0), make_uint2(17, 21));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_ulonglong2(0, 0), make_ulonglong2(17, 21));\n\n    // vec-4\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_char4(0, 0, 0, 0), make_char4(17, 21, 32, 85));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_short4(0, 0, 0, 0), make_short4(17, 21, 32, 85));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_int4(0, 0, 0, 0), make_int4(17, 21, 32, 85));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), make_longlong4(0, 0, 0, 0), make_longlong4(17, 21, 32, 85));\n\n    // complex\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), TestFoo::MakeTestFoo(0, 0, 0, 0), TestFoo::MakeTestFoo(17, 21, 32, 85));\n    Test<BLOCK_THREADS, ITEMS_PER_THREAD>(Sum(), TestBar(0, 0), TestBar(17, 21));\n\n}\n\n\n/**\n * Run tests for different items per thread\n */\ntemplate <int BLOCK_THREADS>\nvoid Test()\n{\n    Test<BLOCK_THREADS, 1>();\n    Test<BLOCK_THREADS, 2>();\n    Test<BLOCK_THREADS, 9>();\n}\n\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#ifdef QUICK_TEST\n\n    Test<128, 1, 1, 1, EXCLUSIVE, AGGREGATE, BLOCK_SCAN_WARP_SCANS>(UNIFORM, Sum(), int(0));\n\n    // Compile/run quick tests\n    Test<128, 1, 1, 4, EXCLUSIVE, AGGREGATE, BLOCK_SCAN_WARP_SCANS>(UNIFORM, Sum(), int(0));\n    Test<128, 1, 1, 4, EXCLUSIVE, AGGREGATE, BLOCK_SCAN_RAKING>(UNIFORM, Sum(), int(0));\n    Test<128, 1, 1, 4, EXCLUSIVE, AGGREGATE, BLOCK_SCAN_RAKING_MEMOIZE>(UNIFORM, Sum(), int(0));\n\n    Test<128, 1, 1, 2, INCLUSIVE, PREFIX, BLOCK_SCAN_RAKING>(INTEGER_SEED, Sum(), TestFoo::MakeTestFoo(17, 21, 32, 85));\n    Test<128, 1, 1, 1, EXCLUSIVE, AGGREGATE, BLOCK_SCAN_WARP_SCANS>(UNIFORM, Sum(), make_longlong4(17, 21, 32, 85));\n\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Run tests for different thread block sizes\n        Test<17>();\n        Test<32>();\n        Test<62>();\n        Test<65>();\n//            Test<96>();             // TODO: file bug for UNREACHABLE error for Test<96, 9, BASIC, BLOCK_SCAN_RAKING>(UNIFORM, Sum(), NullType(), make_ulonglong2(17, 21));\n        Test<128>();\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_histogram.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceHistogram utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <limits>\n#include <algorithm>\n#include <typeinfo>\n\n#if defined(QUICK_TEST) || defined(QUICKER_TEST)\n    #include <npp.h>\n#endif\n\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/device/device_histogram.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    NPP,        // NPP method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\nbool                    g_verbose_input     = false;\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n\n\n//---------------------------------------------------------------------\n// Dispatch to NPP histogram\n//---------------------------------------------------------------------\n\n#if defined(QUICK_TEST) || defined(QUICKER_TEST)\n\n/**\n * Dispatch to single-channel 8b NPP histo-even\n */\ntemplate <typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchEven(\n    Int2Type<1>             num_channels,\n    Int2Type<1>             num_active_channels,\n    Int2Type<NPP>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    unsigned char       *d_samples,               ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[1],          ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[1],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              lower_level[1],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT              upper_level[1],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT             num_row_pixels,           ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                 ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,         ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef unsigned char SampleT;\n\n    cudaError_t error = cudaSuccess;\n    NppiSize oSizeROI = {\n        num_row_pixels,\n        num_rows\n    };\n\n    if (d_temp_storage_bytes == NULL)\n    {\n        int nDeviceBufferSize;\n        nppiHistogramEvenGetBufferSize_8u_C1R(oSizeROI, num_levels[0] ,&nDeviceBufferSize);\n        temp_storage_bytes = nDeviceBufferSize;\n    }\n    else\n    {\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            // compute the histogram\n            nppiHistogramEven_8u_C1R(\n                d_samples,\n                row_stride_bytes,\n                oSizeROI,\n                d_histogram[0],\n                num_levels[0],\n                lower_level[0],\n                upper_level[0],\n                (Npp8u*) d_temp_storage);\n        }\n    }\n\n    return error;\n}\n\n\n/**\n * Dispatch to 3/4 8b NPP histo-even\n */\ntemplate <typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchEven(\n    Int2Type<4>          num_channels,\n    Int2Type<3>   num_active_channels,\n    Int2Type<NPP>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    unsigned char       *d_samples,               ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[3],          ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[3],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              lower_level[3],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT              upper_level[3],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT             num_row_pixels,           ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                 ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,         ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef unsigned char SampleT;\n\n    cudaError_t error = cudaSuccess;\n    NppiSize oSizeROI = {\n        num_row_pixels,\n        num_rows\n    };\n\n    if (d_temp_storage_bytes == NULL)\n    {\n        int nDeviceBufferSize;\n        nppiHistogramEvenGetBufferSize_8u_AC4R(oSizeROI, num_levels ,&nDeviceBufferSize);\n        temp_storage_bytes = nDeviceBufferSize;\n    }\n    else\n    {\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            // compute the histogram\n            nppiHistogramEven_8u_AC4R(\n                d_samples,\n                row_stride_bytes,\n                oSizeROI,\n                d_histogram,\n                num_levels,\n                lower_level,\n                upper_level,\n                (Npp8u*) d_temp_storage);\n        }\n    }\n\n    return error;\n}\n\n\n#endif // #if defined(QUICK_TEST) || defined(QUICKER_TEST)\n\n\n//---------------------------------------------------------------------\n// Dispatch to different DeviceHistogram entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to CUB single histogram-even entrypoint\n */\ntemplate <typename SampleIteratorT, typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchEven(\n    Int2Type<1>             num_channels,\n    Int2Type<1>             num_active_channels,\n    Int2Type<CUB>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[1],                            ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[1],                              ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              lower_level[1],                             ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT              upper_level[1],                             ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceHistogram::HistogramEven(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram[0],\n            num_levels[0],\n            lower_level[0],\n            upper_level[0],\n            num_row_pixels,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to CUB multi histogram-even entrypoint\n */\ntemplate <int NUM_ACTIVE_CHANNELS, int NUM_CHANNELS, typename SampleIteratorT, typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchEven(\n    Int2Type<NUM_CHANNELS>          num_channels,\n    Int2Type<NUM_ACTIVE_CHANNELS>   num_active_channels,\n    Int2Type<CUB>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[NUM_ACTIVE_CHANNELS],          ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT              upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceHistogram::MultiHistogramEven<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram,\n            num_levels,\n            lower_level,\n            upper_level,\n            num_row_pixels,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to CUB single histogram-range entrypoint\n */\ntemplate <typename SampleIteratorT, typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchRange(\n    Int2Type<1>             num_channels,\n    Int2Type<1>             num_active_channels,\n    Int2Type<CUB>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[1],                            ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[1],                              ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              *d_levels[1],                               ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n    OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceHistogram::HistogramRange(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram[0],\n            num_levels[0],\n            d_levels[0],\n            num_row_pixels,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to CUB multi histogram-range entrypoint\n */\ntemplate <int NUM_ACTIVE_CHANNELS, int NUM_CHANNELS, typename SampleIteratorT, typename CounterT, typename LevelT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t DispatchRange(\n    Int2Type<NUM_CHANNELS>          num_channels,\n    Int2Type<NUM_ACTIVE_CHANNELS>   num_active_channels,\n    Int2Type<CUB>           dispatch_to,\n    int                     timing_timing_iterations,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    SampleIteratorT     d_samples,                                  ///< [in] The pointer to the multi-channel input sequence of data samples. The samples from different channels are assumed to be interleaved (e.g., an array of 32-bit pixels where each pixel consists of four RGBA 8-bit samples).\n    CounterT            *d_histogram[NUM_ACTIVE_CHANNELS],          ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    int                 num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT              *d_levels[NUM_ACTIVE_CHANNELS],             ///< [in] The pointers to the arrays of boundaries (levels), one for each active channel.  Bin ranges are defined by consecutive boundary pairings: lower sample value boundaries are inclusive and upper sample value boundaries are exclusive.\n    OffsetT             num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT             num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT             row_stride_bytes,                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceHistogram::MultiHistogramRange<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_samples,\n            d_histogram,\n            num_levels,\n            d_levels,\n            num_row_pixels,\n            num_rows,\n            row_stride_bytes,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n\n//---------------------------------------------------------------------\n// CUDA nested-parallelism test kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceHistogram\n * /\ntemplate <int BINS, int NUM_CHANNELS, int NUM_ACTIVE_CHANNELS, typename SampleT, typename SampleIteratorT, typename CounterT, int ALGORITHM>\n__global__ void CnpDispatchKernel(\n    Int2Type<ALGORITHM> algorithm,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t              temp_storage_bytes,\n    SampleT             *d_samples,\n    SampleIteratorT      d_sample_itr,\n    ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS> d_out_histograms,\n    int                 num_samples,\n    bool                debug_synchronous)\n{\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch<BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(algorithm, Int2Type<false>(), timing_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_samples, d_sample_itr, d_out_histograms.array, num_samples, 0, debug_synchronous);\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/ **\n * Dispatch to CDP kernel\n * /\ntemplate <int BINS, int NUM_CHANNELS, int NUM_ACTIVE_CHANNELS, typename SampleT, typename SampleIteratorT, typename CounterT, int ALGORITHM>\ncudaError_t Dispatch(\n    Int2Type<ALGORITHM> algorithm,\n    Int2Type<true>      use_cdp,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    SampleT             *d_samples,\n    SampleIteratorT      d_sample_itr,\n    CounterT        *d_histograms[NUM_ACTIVE_CHANNELS],\n    int                 num_samples,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Setup array wrapper for histogram channel output (because we can't pass static arrays as kernel parameters)\n    ArrayWrapper<CounterT*, NUM_ACTIVE_CHANNELS> d_histo_wrapper;\n    for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n        d_histo_wrapper.array[CHANNEL] = d_histograms[CHANNEL];\n\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<BINS, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleIteratorT, CounterT, ALGORITHM><<<1,1>>>(algorithm, timing_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_samples, d_sample_itr, d_histo_wrapper, num_samples, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n*/\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n// Searches for bin given a list of bin-boundary levels\ntemplate <typename LevelT>\nstruct SearchTransform\n{\n    LevelT          *levels;      // Pointer to levels array\n    int             num_levels;   // Number of levels in array\n\n    // Functor for converting samples to bin-ids (num_levels is returned if sample is out of range)\n    template <typename SampleT>\n    int operator()(SampleT sample)\n    {\n        int bin = int(std::upper_bound(levels, levels + num_levels, (LevelT) sample) - levels - 1);\n        if (bin < 0)\n        {\n            // Sample out of range\n            return num_levels;\n        }\n        return bin;\n    }\n};\n\n\n// Scales samples to evenly-spaced bins\ntemplate <typename LevelT>\nstruct ScaleTransform\n{\n    int    num_levels;  // Number of levels in array\n    LevelT max;         // Max sample level (exclusive)\n    LevelT min;         // Min sample level (inclusive)\n    LevelT scale;       // Bin scaling factor\n\n    void Init(\n        int    num_levels,  // Number of levels in array\n        LevelT max,         // Max sample level (exclusive)\n        LevelT min,         // Min sample level (inclusive)\n        LevelT scale)       // Bin scaling factor\n    {\n        this->num_levels = num_levels;\n        this->max = max;\n        this->min = min;\n        this->scale = scale;\n    }\n\n    // Functor for converting samples to bin-ids  (num_levels is returned if sample is out of range)\n    template <typename SampleT>\n    int operator()(SampleT sample)\n    {\n        if ((sample < min) || (sample >= max))\n        {\n            // Sample out of range\n            return num_levels;\n        }\n\n        return (int) ((((LevelT) sample) - min) / scale);\n    }\n};\n\n// Scales samples to evenly-spaced bins\ntemplate <>\nstruct ScaleTransform<float>\n{\n    int   num_levels;  // Number of levels in array\n    float max;         // Max sample level (exclusive)\n    float min;         // Min sample level (inclusive)\n    float scale;       // Bin scaling factor\n\n    void Init(\n        int    num_levels,  // Number of levels in array\n        float max,         // Max sample level (exclusive)\n        float min,         // Min sample level (inclusive)\n        float scale)       // Bin scaling factor\n    {\n        this->num_levels = num_levels;\n        this->max = max;\n        this->min = min;\n        this->scale = 1.0f / scale;\n    }\n\n    // Functor for converting samples to bin-ids  (num_levels is returned if sample is out of range)\n    template <typename SampleT>\n    int operator()(SampleT sample)\n    {\n        if ((sample < min) || (sample >= max))\n        {\n            // Sample out of range\n            return num_levels;\n        }\n\n        return (int) ((((float) sample) - min) * scale);\n    }\n};\n\n\n/**\n * Generate sample\n */\ntemplate <typename T, typename LevelT>\nvoid Sample(T &datum, LevelT max_level, int entropy_reduction)\n{\n    unsigned int max = (unsigned int) -1;\n    unsigned int bits;\n    RandomBits(bits, entropy_reduction);\n    float fraction = (float(bits) / max);\n\n    datum = (T) (fraction * max_level);\n}\n\n\n/**\n * Initialize histogram samples\n */\ntemplate <\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        LevelT,\n    typename        SampleT,\n    typename        OffsetT>\nvoid InitializeSamples(\n    LevelT          max_level,\n    int             entropy_reduction,\n    SampleT         *h_samples,\n    OffsetT         num_row_pixels,         ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,               ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes)       ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n{\n    // Initialize samples\n    for (OffsetT row = 0; row < num_rows; ++row)\n    {\n        for (OffsetT pixel = 0; pixel < num_row_pixels; ++pixel)\n        {\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                // Sample offset\n                OffsetT offset = (row * (row_stride_bytes / sizeof(SampleT))) + (pixel * NUM_CHANNELS) + channel;\n\n                // Init sample value\n                Sample(h_samples[offset], max_level, entropy_reduction);\n                if (g_verbose_input)\n                {\n                    if (channel > 0) printf(\", \");\n                    std::cout << CoutCast(h_samples[offset]);\n                }\n            }\n        }\n    }\n}\n\n\n/**\n * Initialize histogram solutions\n */\ntemplate <\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        SampleIteratorT,\n    typename        TransformOp,\n    typename        OffsetT>\nvoid InitializeBins(\n    SampleIteratorT h_samples,\n    int             num_levels[NUM_ACTIVE_CHANNELS],        ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    TransformOp     transform_op[NUM_ACTIVE_CHANNELS],      ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    CounterT        *h_histogram[NUM_ACTIVE_CHANNELS],      ///< [out] The pointers to the histogram counter output arrays, one for each active channel.  For channel<sub><em>i</em></sub>, the allocation length of <tt>d_histograms[i]</tt> should be <tt>num_levels[i]</tt> - 1.\n    OffsetT         num_row_pixels,                         ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,                               ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes)                       ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n{\n    typedef typename std::iterator_traits<SampleIteratorT>::value_type SampleT;\n\n    // Init bins\n    for (int CHANNEL = 0; CHANNEL < NUM_ACTIVE_CHANNELS; ++CHANNEL)\n    {\n        for (int bin = 0; bin < num_levels[CHANNEL] - 1; ++bin)\n        {\n            h_histogram[CHANNEL][bin] = 0;\n        }\n    }\n\n    // Initialize samples\n    if (g_verbose_input) printf(\"Samples: \\n\");\n    for (OffsetT row = 0; row < num_rows; ++row)\n    {\n        for (OffsetT pixel = 0; pixel < num_row_pixels; ++pixel)\n        {\n            if (g_verbose_input) printf(\"[\");\n            for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n            {\n                // Sample offset\n                OffsetT offset = (row * (row_stride_bytes / sizeof(SampleT))) + (pixel * NUM_CHANNELS) + channel;\n\n                // Update sample bin\n                int bin = transform_op[channel](h_samples[offset]);\n                if (g_verbose_input) printf(\" (%d)\", bin); fflush(stdout);\n                if ((bin >= 0) && (bin < num_levels[channel] - 1))\n                {\n                    // valid bin\n                    h_histogram[channel][bin]++;\n                }\n            }\n            if (g_verbose_input) printf(\"]\");\n        }\n        if (g_verbose_input) printf(\"\\n\\n\");\n    }\n}\n\n\n\n/**\n * Test histogram-even\n */\ntemplate <\n    Backend         BACKEND,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT,\n    typename        SampleIteratorT>\nvoid TestEven(\n    LevelT          max_level,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT          lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT          upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT         num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes,                           ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n    SampleIteratorT h_samples,\n    SampleIteratorT d_samples)\n{\n    OffsetT total_samples = num_rows * (row_stride_bytes / sizeof(SampleT));\n\n    printf(\"\\n----------------------------\\n\");\n    printf(\"%s cub::DeviceHistogramEven (%s) %d pixels (%d height, %d width, %d-byte row stride), %d %d-byte %s samples (entropy reduction %d), %s counters, %d/%d channels, max sample \",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == NPP) ? \"NPP\" : \"CUB\",\n        (IsPointer<SampleIteratorT>::VALUE) ? \"pointer\" : \"iterator\",\n        (int) (num_row_pixels * num_rows),\n        (int) num_rows,\n        (int) num_row_pixels,\n        (int) row_stride_bytes,\n        (int) total_samples,\n        (int) sizeof(SampleT),\n        typeid(SampleT).name(),\n        entropy_reduction,\n        typeid(CounterT).name(),\n        NUM_ACTIVE_CHANNELS,\n        NUM_CHANNELS);\n    std::cout << CoutCast(max_level) << \"\\n\";\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n        std::cout << \"\\n\\tChannel \" << channel << \": \" << num_levels[channel] - 1 << \" bins [\" << lower_level[channel] << \", \" << upper_level[channel] << \")\\n\";\n    fflush(stdout);\n\n    // Allocate and initialize host and device data\n\n    typedef SampleT Foo;        // rename type to quelch gcc warnings (bug?)\n    CounterT*                   h_histogram[NUM_ACTIVE_CHANNELS];\n    ScaleTransform<LevelT>      transform_op[NUM_ACTIVE_CHANNELS];\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        int bins = num_levels[channel] - 1;\n        h_histogram[channel] = new CounterT[bins];\n\n        transform_op[channel].Init(\n            num_levels[channel],\n            upper_level[channel],\n            lower_level[channel],\n            ((upper_level[channel] - lower_level[channel]) / bins));\n    }\n\n    InitializeBins<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n        h_samples, num_levels, transform_op, h_histogram, num_row_pixels, num_rows, row_stride_bytes);\n\n    // Allocate and initialize device data\n\n    CounterT* d_histogram[NUM_ACTIVE_CHANNELS];\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_histogram[channel], sizeof(CounterT) * (num_levels[channel] - 1)));\n        CubDebugExit(cudaMemset(d_histogram[channel], 0, sizeof(CounterT) * (num_levels[channel] - 1)));\n    }\n\n    // Allocate CDP device arrays\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n\n    DispatchEven(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, lower_level, upper_level,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, true);\n\n    // Allocate temporary storage with \"canary\" zones\n    int     canary_bytes    = 256;\n    char    canary_token    = 8;\n    char*   canary_zone     = new char[canary_bytes];\n\n    memset(canary_zone, canary_token, canary_bytes);\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes + (canary_bytes * 2)));\n    CubDebugExit(cudaMemset(d_temp_storage, canary_token, temp_storage_bytes + (canary_bytes * 2)));\n\n    // Run warmup/correctness iteration\n    DispatchEven(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error,\n        ((char *) d_temp_storage) + canary_bytes, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, lower_level, upper_level,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, true);\n\n    // Check canary zones\n    int error = CompareDeviceResults(canary_zone, (char *) d_temp_storage, canary_bytes, true, g_verbose);\n    AssertEquals(0, error);\n    error = CompareDeviceResults(canary_zone, ((char *) d_temp_storage) + canary_bytes + temp_storage_bytes, canary_bytes, true, g_verbose);\n    AssertEquals(0, error);\n\n    // Flush any stdout/stderr\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n    fflush(stdout);\n    fflush(stderr);\n\n    // Check for correctness (and display results, if specified)\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        int channel_error = CompareDeviceResults(h_histogram[channel], d_histogram[channel], num_levels[channel] - 1, true, g_verbose);\n        printf(\"\\tChannel %d %s\", channel, channel_error ? \"FAIL\" : \"PASS\\n\");\n        error |= channel_error;\n    }\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n\n    DispatchEven(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, lower_level, upper_level,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, false);\n\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(total_samples) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth = giga_rate * sizeof(SampleT);\n        printf(\"\\t%.3f avg ms, %.3f billion samples/s, %.3f billion bins/s, %.3f billion pixels/s, %.3f logical GB/s\",\n            avg_millis,\n            giga_rate,\n            giga_rate * NUM_ACTIVE_CHANNELS / NUM_CHANNELS,\n            giga_rate / NUM_CHANNELS,\n            giga_bandwidth);\n    }\n\n    printf(\"\\n\\n\");\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        if (h_histogram[channel])\n            delete[] h_histogram[channel];\n\n        if (d_histogram[channel])\n            CubDebugExit(g_allocator.DeviceFree(d_histogram[channel]));\n    }\n\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, error);\n}\n\n\n/**\n * Test histogram-even (native pointer input)\n */\ntemplate <\n    Backend         BACKEND,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestEvenNative(\n    LevelT          max_level,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT          lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT          upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT         num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes)                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n{\n    OffsetT total_samples = num_rows * (row_stride_bytes / sizeof(SampleT));\n\n    // Allocate and initialize host sample data\n    typedef SampleT Foo;        // rename type to quelch gcc warnings (bug?)\n    SampleT*                    h_samples = new Foo[total_samples];\n\n    InitializeSamples<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n        max_level, entropy_reduction, h_samples, num_row_pixels, num_rows, row_stride_bytes);\n\n    // Allocate and initialize device data\n    SampleT* d_samples = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_samples, sizeof(SampleT) * total_samples));\n    CubDebugExit(cudaMemcpy(d_samples, h_samples, sizeof(SampleT) * total_samples, cudaMemcpyHostToDevice));\n\n    TestEven<BACKEND, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleT, CounterT, LevelT, OffsetT>(\n        max_level, entropy_reduction, num_levels, lower_level, upper_level,\n        num_row_pixels, num_rows, row_stride_bytes,\n        h_samples, d_samples);\n\n    // Cleanup\n    if (h_samples) delete[] h_samples;\n    if (d_samples) CubDebugExit(g_allocator.DeviceFree(d_samples));\n}\n\n\n/**\n * Test histogram-even (native pointer input)\n */\ntemplate <\n    Backend         BACKEND,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestEvenIterator(\n    LevelT          max_level,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT          lower_level[NUM_ACTIVE_CHANNELS],           ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    LevelT          upper_level[NUM_ACTIVE_CHANNELS],           ///< [in] The upper sample value bound (exclusive) for the highest histogram bin in each active channel.\n    OffsetT         num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes)                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n{\n    SampleT sample = (SampleT) lower_level[0];\n    ConstantInputIterator<SampleT> sample_itr(sample);\n\n    TestEven<BACKEND, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleT, CounterT, LevelT, OffsetT>(\n        max_level, entropy_reduction, num_levels, lower_level, upper_level,\n        num_row_pixels, num_rows, row_stride_bytes,\n        sample_itr, sample_itr);\n\n}\n\n\n/**\n * Test histogram-range\n */\ntemplate <\n    Backend         BACKEND,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestRange(\n    LevelT          max_level,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],            ///< [in] The number of boundaries (levels) for delineating histogram samples in each active channel.  Implies that the number of bins for channel<sub><em>i</em></sub> is <tt>num_levels[i]</tt> - 1.\n    LevelT*         levels[NUM_ACTIVE_CHANNELS],                ///< [in] The lower sample value bound (inclusive) for the lowest histogram bin in each active channel.\n    OffsetT         num_row_pixels,                             ///< [in] The number of multi-channel pixels per row in the region of interest\n    OffsetT         num_rows,                                   ///< [in] The number of rows in the region of interest\n    OffsetT         row_stride_bytes)                                 ///< [in] The number of bytes between starts of consecutive rows in the region of interest\n{\n    OffsetT total_samples = num_rows * (row_stride_bytes / sizeof(SampleT));\n\n    printf(\"\\n----------------------------\\n\");\n    printf(\"%s cub::DeviceHistogramRange %d pixels (%d height, %d width, %d-byte row stride), %d %d-byte %s samples (entropy reduction %d), %s counters, %d/%d channels, max sample \",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == NPP) ? \"NPP\" : \"CUB\",\n        (int) (num_row_pixels * num_rows),\n        (int) num_rows,\n        (int) num_row_pixels,\n        (int) row_stride_bytes,\n        (int) total_samples,\n        (int) sizeof(SampleT),\n        typeid(SampleT).name(),\n        entropy_reduction,\n        typeid(CounterT).name(),\n        NUM_ACTIVE_CHANNELS,\n        NUM_CHANNELS);\n    std::cout << CoutCast(max_level) << \"\\n\";\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        printf(\"Channel %d: %d bins [\", channel, num_levels[channel] - 1);\n        std::cout << levels[channel][0];\n        for (int level = 1; level < num_levels[channel]; ++level)\n            std::cout << \", \" << levels[channel][level];\n        printf(\"]\\n\");\n    }\n    fflush(stdout);\n\n    // Allocate and initialize host and device data\n    typedef SampleT Foo;        // rename type to quelch gcc warnings (bug?)\n    SampleT*                    h_samples = new Foo[total_samples];\n    CounterT*                   h_histogram[NUM_ACTIVE_CHANNELS];\n    SearchTransform<LevelT>     transform_op[NUM_ACTIVE_CHANNELS];\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        transform_op[channel].levels = levels[channel];\n        transform_op[channel].num_levels = num_levels[channel];\n\n        int bins = num_levels[channel] - 1;\n        h_histogram[channel] = new CounterT[bins];\n    }\n\n    InitializeSamples<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n        max_level, entropy_reduction, h_samples, num_row_pixels, num_rows, row_stride_bytes);\n\n    InitializeBins<NUM_CHANNELS, NUM_ACTIVE_CHANNELS>(\n        h_samples, num_levels, transform_op, h_histogram, num_row_pixels, num_rows, row_stride_bytes);\n\n    // Allocate and initialize device data\n    SampleT*        d_samples = NULL;\n    LevelT*         d_levels[NUM_ACTIVE_CHANNELS];\n    CounterT*       d_histogram[NUM_ACTIVE_CHANNELS];\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_samples, sizeof(SampleT) * total_samples));\n    CubDebugExit(cudaMemcpy(d_samples, h_samples, sizeof(SampleT) * total_samples, cudaMemcpyHostToDevice));\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_levels[channel], sizeof(LevelT) * num_levels[channel]));\n        CubDebugExit(cudaMemcpy(d_levels[channel], levels[channel],         sizeof(LevelT) * num_levels[channel], cudaMemcpyHostToDevice));\n\n        int bins = num_levels[channel] - 1;\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_histogram[channel],  sizeof(CounterT) * bins));\n        CubDebugExit(cudaMemset(d_histogram[channel], 0,                        sizeof(CounterT) * bins));\n    }\n\n    // Allocate CDP device arrays\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n\n    DispatchRange(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, d_levels,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, true);\n\n    // Allocate temporary storage with \"canary\" zones\n    int     canary_bytes    = 256;\n    char    canary_token    = 9;\n    char*   canary_zone     = new char[canary_bytes];\n\n    memset(canary_zone, canary_token, canary_bytes);\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes + (canary_bytes * 2)));\n    CubDebugExit(cudaMemset(d_temp_storage, canary_token, temp_storage_bytes + (canary_bytes * 2)));\n\n    // Run warmup/correctness iteration\n    DispatchRange(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error,\n        ((char *) d_temp_storage) + canary_bytes, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, d_levels,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, true);\n\n    // Check canary zones\n    int error = CompareDeviceResults(canary_zone, (char *) d_temp_storage, canary_bytes, true, g_verbose);\n    AssertEquals(0, error);\n    error = CompareDeviceResults(canary_zone, ((char *) d_temp_storage) + canary_bytes + temp_storage_bytes, canary_bytes, true, g_verbose);\n    AssertEquals(0, error);\n\n    // Flush any stdout/stderr\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n    fflush(stdout);\n    fflush(stderr);\n\n    // Check for correctness (and display results, if specified)\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        int channel_error = CompareDeviceResults(h_histogram[channel], d_histogram[channel], num_levels[channel] - 1, true, g_verbose);\n        printf(\"\\tChannel %d %s\", channel, channel_error ? \"FAIL\" : \"PASS\\n\");\n        error |= channel_error;\n    }\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n\n    DispatchRange(\n        Int2Type<NUM_CHANNELS>(), Int2Type<NUM_ACTIVE_CHANNELS>(), Int2Type<BACKEND>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes,\n        d_samples, d_histogram, num_levels, d_levels,\n        num_row_pixels, num_rows, row_stride_bytes,\n        0, false);\n\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(total_samples) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth = giga_rate * sizeof(SampleT);\n        printf(\"\\t%.3f avg ms, %.3f billion samples/s, %.3f billion bins/s, %.3f billion pixels/s, %.3f logical GB/s\",\n            avg_millis,\n            giga_rate,\n            giga_rate * NUM_ACTIVE_CHANNELS / NUM_CHANNELS,\n            giga_rate / NUM_CHANNELS,\n            giga_bandwidth);\n    }\n\n    printf(\"\\n\\n\");\n\n    // Cleanup\n    if (h_samples) delete[] h_samples;\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        if (h_histogram[channel])\n            delete[] h_histogram[channel];\n\n        if (d_histogram[channel])\n            CubDebugExit(g_allocator.DeviceFree(d_histogram[channel]));\n\n        if (d_levels[channel])\n            CubDebugExit(g_allocator.DeviceFree(d_levels[channel]));\n    }\n\n    if (d_samples) CubDebugExit(g_allocator.DeviceFree(d_samples));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, error);\n}\n\n\n/**\n * Test histogram-even\n */\ntemplate <\n    Backend         BACKEND,\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestEven(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    OffsetT         row_stride_bytes,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    LevelT lower_level[NUM_ACTIVE_CHANNELS];\n    LevelT upper_level[NUM_ACTIVE_CHANNELS];\n\n    // Find smallest level increment\n    int max_bins = max_num_levels - 1;\n    LevelT min_level_increment = max_level / max_bins;\n\n    // Set upper and lower levels for each channel\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        int num_bins = num_levels[channel] - 1;\n        lower_level[channel] = (max_level - (num_bins * min_level_increment)) / 2;\n        upper_level[channel] = (max_level + (num_bins * min_level_increment)) / 2;\n    }\n\n    // Test pointer-based samples\n    TestEvenNative<BACKEND, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleT, CounterT, LevelT, OffsetT>(\n        max_level, entropy_reduction, num_levels, lower_level, upper_level, num_row_pixels, num_rows, row_stride_bytes);\n\n    // Test iterator-based samples (CUB-only)\n    TestEvenIterator<CUB, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleT, CounterT, LevelT, OffsetT>(\n        max_level, entropy_reduction, num_levels, lower_level, upper_level, num_row_pixels, num_rows, row_stride_bytes);\n}\n\n\n\n/**\n * Test histogram-range\n */\ntemplate <\n    Backend         BACKEND,\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestRange(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    OffsetT         row_stride_bytes,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    // Find smallest level increment\n    int max_bins = max_num_levels - 1;\n    LevelT min_level_increment = max_level / max_bins;\n\n    LevelT* levels[NUM_ACTIVE_CHANNELS];\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        levels[channel] = new LevelT[num_levels[channel]];\n\n        int num_bins = num_levels[channel] - 1;\n        LevelT lower_level = (max_level - (num_bins * min_level_increment)) / 2;\n\n        for (int level = 0; level < num_levels[channel]; ++level)\n            levels[channel][level] = lower_level + (level * min_level_increment);\n    }\n\n    TestRange<BACKEND, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, SampleT, CounterT, LevelT, OffsetT>(\n        max_level, entropy_reduction, num_levels, levels, num_row_pixels, num_rows, row_stride_bytes);\n\n    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n        delete[] levels[channel];\n\n}\n\n\n\n/**\n * Test different entrypoints\n */\ntemplate <\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid Test(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    OffsetT         row_stride_bytes,\n    int             entropy_reduction,\n    int             num_levels[NUM_ACTIVE_CHANNELS],\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    TestEven<CUB, SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, max_num_levels);\n\n    TestRange<CUB, SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, max_num_levels);\n}\n\n\n/**\n * Test different number of levels\n */\ntemplate <\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid Test(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    OffsetT         row_stride_bytes,\n    int             entropy_reduction,\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    int num_levels[NUM_ACTIVE_CHANNELS];\n\n// Unnecessary testing\n//    // All the same level\n//    for (int channel = 0; channel < NUM_ACTIVE_CHANNELS; ++channel)\n//    {\n//        num_levels[channel] = max_num_levels;\n//    }\n//    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n//        num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, max_num_levels);\n\n    // All different levels\n    num_levels[0] = max_num_levels;\n    for (int channel = 1; channel < NUM_ACTIVE_CHANNELS; ++channel)\n    {\n        num_levels[channel] = (num_levels[channel - 1] / 2) + 1;\n    }\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, max_num_levels);\n}\n\n\n\n/**\n * Test different entropy-levels\n */\ntemplate <\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid Test(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    OffsetT         row_stride_bytes,\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, 0,   max_level, max_num_levels);\n\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, -1,  max_level, max_num_levels);\n\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, 5,   max_level, max_num_levels);\n}\n\n\n/**\n * Test different row strides\n */\ntemplate <\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid Test(\n    OffsetT         num_row_pixels,\n    OffsetT         num_rows,\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    OffsetT row_stride_bytes = num_row_pixels * NUM_CHANNELS * sizeof(SampleT);\n\n    // No padding\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes, max_level, max_num_levels);\n\n    // 13 samples padding\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        num_row_pixels, num_rows, row_stride_bytes + (13 * sizeof(SampleT)), max_level, max_num_levels);\n}\n\n\n/**\n * Test different problem sizes\n */\ntemplate <\n    typename        SampleT,\n    int             NUM_CHANNELS,\n    int             NUM_ACTIVE_CHANNELS,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid Test(\n    LevelT          max_level,\n    int             max_num_levels)\n{\n    // 0 row/col images\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        OffsetT(1920), OffsetT(0), max_level, max_num_levels);\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        OffsetT(0), OffsetT(0), max_level, max_num_levels);\n\n    // 1080 image\n    Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n        OffsetT(1920), OffsetT(1080), max_level, max_num_levels);\n\n    // Sample different aspect ratios sizes\n    for (OffsetT rows = 1; rows < 1000000; rows *= 1000)\n    {\n        for (OffsetT cols = 1; cols < (1000000 / rows); cols *= 1000)\n        {\n            Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n                cols, rows, max_level, max_num_levels);\n        }\n    }\n\n    // Randomly select linear problem size between 1:10,000,000\n    unsigned int max_int = (unsigned int) -1;\n    for (int i = 0; i < 4; ++i)\n    {\n        unsigned int num_items;\n        RandomBits(num_items);\n        num_items = (unsigned int) ((double(num_items) * double(10000000)) / double(max_int));\n        num_items = CUB_MAX(1, num_items);\n\n        Test<SampleT, NUM_CHANNELS, NUM_ACTIVE_CHANNELS, CounterT, LevelT, OffsetT>(\n            OffsetT(num_items), 1, max_level, max_num_levels);\n    }\n}\n\n\n\n/**\n * Test different channel interleavings (valid specialiation)\n */\ntemplate <\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestChannels(\n    LevelT          max_level,\n    int             max_num_levels,\n    Int2Type<true>  is_valid_tag)\n{\n    Test<SampleT, 1, 1, CounterT, LevelT, OffsetT>(max_level, max_num_levels);\n    Test<SampleT, 4, 3, CounterT, LevelT, OffsetT>(max_level, max_num_levels);\n    Test<SampleT, 3, 3, CounterT, LevelT, OffsetT>(max_level, max_num_levels);\n    Test<SampleT, 4, 4, CounterT, LevelT, OffsetT>(max_level, max_num_levels);\n}\n\n\n/**\n * Test different channel interleavings (invalid specialiation)\n */\ntemplate <\n    typename        SampleT,\n    typename        CounterT,\n    typename        LevelT,\n    typename        OffsetT>\nvoid TestChannels(\n    LevelT          max_level,\n    int             max_num_levels,\n    Int2Type<false> is_valid_tag)\n{}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_row_pixels = -1;\n    int entropy_reduction = 0;\n    int num_rows = 1;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_verbose_input = args.CheckCmdLineFlag(\"v2\");\n    args.GetCmdLineArgument(\"n\", num_row_pixels);\n\n    int row_stride_pixels = num_row_pixels;\n\n    args.GetCmdLineArgument(\"rows\", num_rows);\n    args.GetCmdLineArgument(\"stride\", row_stride_pixels);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n#if defined(QUICK_TEST) || defined(QUICKER_TEST)\n    bool compare_npp = args.CheckCmdLineFlag(\"npp\");\n#endif\n\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<pixels per row> \"\n            \"[--rows=<number of rows> \"\n            \"[--stride=<row stride in pixels> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--entropy=<entropy-reduction factor (default 0)>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"[--npp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n    if (num_row_pixels < 0)\n    {\n        num_row_pixels      = 1920 * 1080;\n        row_stride_pixels   = num_row_pixels;\n    }\n\n#if defined(QUICKER_TEST)\n\n    // Compile/run quick tests\n    {\n        // HistogramEven: unsigned char 256 bins\n        typedef unsigned char       SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[1]       = {257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n        if (compare_npp)\n            TestEven<NPP, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n\n#elif defined(QUICK_TEST)\n\n    // Compile/run quick tests\n    {\n        // HistogramEven: unsigned char 256 bins\n        typedef unsigned char       SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[1]       = {257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n        if (compare_npp)\n            TestEven<NPP, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: 4/4 multichannel Unsigned char 256 bins\n        typedef unsigned char       SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[4]       = {257, 257, 257, 257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 4;\n\n        TestEven<CUB, SampleT, 4, 4, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: 3/4 multichannel Unsigned char 256 bins\n        typedef unsigned char       SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[3]       = {257, 257, 257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 4;\n\n        TestEven<CUB, SampleT, 4, 3, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n        if (compare_npp)\n            TestEven<NPP, SampleT, 4, 3, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: short [0,1024] 256 bins\n        typedef unsigned short      SampleT;\n        typedef unsigned short      LevelT;\n\n        LevelT  max_level           = 1024;\n        int     num_levels[1]       = {257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: float [0,1.0] 256 bins\n        typedef float               SampleT;\n        typedef float               LevelT;\n\n        LevelT  max_level           = 1.0;\n        int     num_levels[1]       = {257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: 3/4 multichannel float [0,1.0] 256 bins\n        typedef float               SampleT;\n        typedef float               LevelT;\n\n         LevelT  max_level           = 1.0;\n         int     num_levels[3]       = {257, 257, 257};\n         int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 4;\n\n         TestEven<CUB, SampleT, 4, 3, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramRange: signed char 256 bins\n        typedef signed char         SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[1]       = {257};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestRange<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramRange: 3/4 channel, unsigned char, varied bins (256, 128, 64)\n        typedef unsigned char       SampleT;\n        typedef int                 LevelT;\n\n        LevelT  max_level           = 256;\n        int     num_levels[3]       = {257, 129, 65};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 4;\n\n        TestRange<CUB, SampleT, 4, 3, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n    {\n        // HistogramEven: double [0,1.0] 64 bins\n        typedef double              SampleT;\n        typedef double              LevelT;\n\n        LevelT  max_level           = 1.0;\n        int     num_levels[1]       = {65};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n    {\n        // HistogramEven: short [0,1024] 512 bins\n        typedef unsigned short      SampleT;\n        typedef unsigned short      LevelT;\n\n        LevelT  max_level           = 1024;\n        int     num_levels[1]       = {513};\n        int     row_stride_bytes    = sizeof(SampleT) * row_stride_pixels * 1;\n\n        TestEven<CUB, SampleT, 1, 1, int, LevelT, int>(num_row_pixels, num_rows, row_stride_bytes, entropy_reduction, num_levels, max_level, num_levels[0]);\n    }\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        TestChannels <unsigned char,    int, int,   int>(256,   256 + 1, Int2Type<true>());\n        TestChannels <signed char,      int, int,   int>(256,   256 + 1, Int2Type<true>());\n        TestChannels <unsigned short,   int, int,   int>(128,   128 + 1, Int2Type<true>());\n        TestChannels <unsigned short,   int, int,   int>(8192,  8192 + 1, Int2Type<true>());\n        TestChannels <float,            int, float, int>(1.0,   256 + 1, Int2Type<true>());\n\n\t\t// Test down-conversion of size_t offsets to int\n        TestChannels <unsigned char,    int, int,   long long>(256, 256 + 1, Int2Type<(sizeof(size_t) != sizeof(int))>());\n    }\n\n#endif\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/test/test_device_radix_sort.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceRadixSort utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <algorithm>\n#include <typeinfo>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_radix_sort.cuh>\n#include <cub/device/device_segmented_radix_sort.cuh>\n\n#include \"test_util.h\"\n\n#include <thrust/device_ptr.h>\n#include <thrust/sort.h>\n#include <thrust/reverse.h>\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,                        // CUB method (allows overwriting of input)\n    CUB_NO_OVERWRITE,           // CUB method (disallows overwriting of input)\n\n    CUB_SEGMENTED,              // CUB method (allows overwriting of input)\n    CUB_SEGMENTED_NO_OVERWRITE, // CUB method (disallows overwriting of input)\n\n    THRUST,                     // Thrust method\n    CDP,                        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different DeviceRadixSort entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to CUB sorting entrypoint (specialized for ascending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<false>         is_descending,\n    Int2Type<CUB>           dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    return DeviceRadixSort::SortPairs(\n        d_temp_storage, temp_storage_bytes,\n        d_keys, d_values,\n        num_items, begin_bit, end_bit, stream, debug_synchronous);\n}\n\n/**\n * Dispatch to CUB_NO_OVERWRITE sorting entrypoint (specialized for ascending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<false>             is_descending,\n    Int2Type<CUB_NO_OVERWRITE>  dispatch_to,\n    int                         *d_selector,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    KeyT      const *const_keys_itr     = d_keys.Current();\n    ValueT    const *const_values_itr   = d_values.Current();\n\n    cudaError_t retval = DeviceRadixSort::SortPairs(\n        d_temp_storage, temp_storage_bytes,\n        const_keys_itr, d_keys.Alternate(), const_values_itr, d_values.Alternate(),\n        num_items, begin_bit, end_bit, stream, debug_synchronous);\n\n    d_keys.selector ^= 1;\n    d_values.selector ^= 1;\n    return retval;\n}\n\n/**\n * Dispatch to CUB sorting entrypoint (specialized for descending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<true>          is_descending,\n    Int2Type<CUB>           dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    return DeviceRadixSort::SortPairsDescending(\n        d_temp_storage, temp_storage_bytes,\n        d_keys, d_values,\n        num_items, begin_bit, end_bit, stream, debug_synchronous);\n}\n\n\n/**\n * Dispatch to CUB_NO_OVERWRITE sorting entrypoint (specialized for descending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<true>              is_descending,\n    Int2Type<CUB_NO_OVERWRITE>  dispatch_to,\n    int                         *d_selector,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    KeyT      const *const_keys_itr     = d_keys.Current();\n    ValueT    const *const_values_itr   = d_values.Current();\n\n    cudaError_t retval = DeviceRadixSort::SortPairsDescending(\n        d_temp_storage, temp_storage_bytes,\n        const_keys_itr, d_keys.Alternate(), const_values_itr, d_values.Alternate(),\n        num_items, begin_bit, end_bit, stream, debug_synchronous);\n\n    d_keys.selector ^= 1;\n    d_values.selector ^= 1;\n    return retval;\n}\n\n//---------------------------------------------------------------------\n// Dispatch to different DeviceRadixSort entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to CUB_SEGMENTED sorting entrypoint (specialized for ascending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<false>         is_descending,\n    Int2Type<CUB_SEGMENTED> dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    return DeviceSegmentedRadixSort::SortPairs(\n        d_temp_storage, temp_storage_bytes,\n        d_keys, d_values,\n        num_items, num_segments, d_segment_offsets, d_segment_offsets + 1,\n        begin_bit, end_bit, stream, debug_synchronous);\n}\n\n/**\n * Dispatch to CUB_SEGMENTED_NO_OVERWRITE sorting entrypoint (specialized for ascending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<false>                         is_descending,\n    Int2Type<CUB_SEGMENTED_NO_OVERWRITE>    dispatch_to,\n    int                                     *d_selector,\n    size_t                                  *d_temp_storage_bytes,\n    cudaError_t                             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    KeyT      const *const_keys_itr     = d_keys.Current();\n    ValueT    const *const_values_itr   = d_values.Current();\n\n    cudaError_t retval = DeviceSegmentedRadixSort::SortPairs(\n        d_temp_storage, temp_storage_bytes,\n        const_keys_itr, d_keys.Alternate(), const_values_itr, d_values.Alternate(),\n        num_items, num_segments, d_segment_offsets, d_segment_offsets + 1,\n        begin_bit, end_bit, stream, debug_synchronous);\n\n    d_keys.selector ^= 1;\n    d_values.selector ^= 1;\n    return retval;\n}\n\n\n/**\n * Dispatch to CUB_SEGMENTED sorting entrypoint (specialized for descending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<true>          is_descending,\n    Int2Type<CUB_SEGMENTED> dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    return DeviceSegmentedRadixSort::SortPairsDescending(\n        d_temp_storage, temp_storage_bytes,\n        d_keys, d_values,\n        num_items, num_segments, d_segment_offsets, d_segment_offsets + 1,\n        begin_bit, end_bit, stream, debug_synchronous);\n}\n\n/**\n * Dispatch to CUB_SEGMENTED_NO_OVERWRITE sorting entrypoint (specialized for descending)\n */\ntemplate <typename KeyT, typename ValueT>\nCUB_RUNTIME_FUNCTION\n__forceinline__\ncudaError_t Dispatch(\n    Int2Type<true>                          is_descending,\n    Int2Type<CUB_SEGMENTED_NO_OVERWRITE>    dispatch_to,\n    int                                     *d_selector,\n    size_t                                  *d_temp_storage_bytes,\n    cudaError_t                             *d_cdp_error,\n\n    void*                   d_temp_storage,\n    size_t&                 temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    KeyT      const *const_keys_itr     = d_keys.Current();\n    ValueT    const *const_values_itr   = d_values.Current();\n\n    cudaError_t retval = DeviceSegmentedRadixSort::SortPairsDescending(\n        d_temp_storage, temp_storage_bytes,\n        const_keys_itr, d_keys.Alternate(), const_values_itr, d_values.Alternate(),\n        num_items, num_segments, d_segment_offsets, d_segment_offsets + 1,\n        begin_bit, end_bit, stream, debug_synchronous);\n\n    d_keys.selector ^= 1;\n    d_values.selector ^= 1;\n    return retval;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch keys-only to Thrust sorting entrypoint\n */\ntemplate <int IS_DESCENDING, typename KeyT>\ncudaError_t Dispatch(\n    Int2Type<IS_DESCENDING> is_descending,\n    Int2Type<THRUST>        dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void                    *d_temp_storage,\n    size_t                  &temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<NullType>  &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<KeyT> d_keys_wrapper(d_keys.Current());\n\n        if (IS_DESCENDING) thrust::reverse(d_keys_wrapper, d_keys_wrapper + num_items);\n        thrust::sort(d_keys_wrapper, d_keys_wrapper + num_items);\n        if (IS_DESCENDING) thrust::reverse(d_keys_wrapper, d_keys_wrapper + num_items);\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch key-value pairs to Thrust sorting entrypoint\n */\ntemplate <int IS_DESCENDING, typename KeyT, typename ValueT>\ncudaError_t Dispatch(\n    Int2Type<IS_DESCENDING> is_descending,\n    Int2Type<THRUST>        dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void                    *d_temp_storage,\n    size_t                  &temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<KeyT>     d_keys_wrapper(d_keys.Current());\n        thrust::device_ptr<ValueT>   d_values_wrapper(d_values.Current());\n\n        if (IS_DESCENDING) {\n            thrust::reverse(d_keys_wrapper, d_keys_wrapper + num_items);\n            thrust::reverse(d_values_wrapper, d_values_wrapper + num_items);\n        }\n\n        thrust::sort_by_key(d_keys_wrapper, d_keys_wrapper + num_items, d_values_wrapper);\n\n        if (IS_DESCENDING) {\n            thrust::reverse(d_keys_wrapper, d_keys_wrapper + num_items);\n            thrust::reverse(d_values_wrapper, d_values_wrapper + num_items);\n        }\n    }\n\n    return cudaSuccess;\n}\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceRadixSort\n */\ntemplate <int IS_DESCENDING, typename KeyT, typename ValueT>\n__global__ void CnpDispatchKernel(\n    Int2Type<IS_DESCENDING> is_descending,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void                    *d_temp_storage,\n    size_t                  temp_storage_bytes,\n    DoubleBuffer<KeyT>      d_keys,\n    DoubleBuffer<ValueT>    d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    bool                    debug_synchronous)\n{\n#ifndef CUB_CDP\n    *d_cdp_error            = cudaErrorNotSupported;\n#else\n    *d_cdp_error            = Dispatch(\n                                is_descending, Int2Type<CUB>(), d_selector, d_temp_storage_bytes, d_cdp_error,\n                                d_temp_storage, temp_storage_bytes, d_keys, d_values,\n                                num_items, num_segments, d_segment_offsets,\n                                begin_bit, end_bit, 0, debug_synchronous);\n    *d_temp_storage_bytes   = temp_storage_bytes;\n    *d_selector             = d_keys.selector;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <int IS_DESCENDING, typename KeyT, typename ValueT>\ncudaError_t Dispatch(\n    Int2Type<IS_DESCENDING> is_descending,\n    Int2Type<CDP>           dispatch_to,\n    int                     *d_selector,\n    size_t                  *d_temp_storage_bytes,\n    cudaError_t             *d_cdp_error,\n\n    void                    *d_temp_storage,\n    size_t                  &temp_storage_bytes,\n    DoubleBuffer<KeyT>      &d_keys,\n    DoubleBuffer<ValueT>    &d_values,\n    int                     num_items,\n    int                     num_segments,\n    const int               *d_segment_offsets,\n    int                     begin_bit,\n    int                     end_bit,\n    cudaStream_t            stream,\n    bool                    debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(\n        is_descending, d_selector, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_keys, d_values,\n        num_items, num_segments, d_segment_offsets,\n        begin_bit, end_bit, debug_synchronous);\n\n    // Copy out selector\n    CubDebugExit(cudaMemcpy(&d_keys.selector, d_selector, sizeof(int) * 1, cudaMemcpyDeviceToHost));\n    d_values.selector = d_keys.selector;\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Problem generation\n//---------------------------------------------------------------------\n\n\n/**\n * Simple key-value pairing\n */\ntemplate <\n    typename KeyT,\n    typename ValueT,\n    bool IS_FLOAT = (Traits<KeyT>::CATEGORY == FLOATING_POINT)>\nstruct Pair\n{\n    KeyT     key;\n    ValueT   value;\n\n    bool operator<(const Pair &b) const\n    {\n        return (key < b.key);\n    }\n};\n\n\n/**\n * Simple key-value pairing (specialized for bool types)\n */\ntemplate <typename ValueT>\nstruct Pair<bool, ValueT, false>\n{\n    bool     key;\n    ValueT   value;\n\n    bool operator<(const Pair &b) const\n    {\n        return (!key && b.key);\n    }\n};\n\n\n/**\n * Simple key-value pairing (specialized for floating point types)\n */\ntemplate <typename KeyT, typename ValueT>\nstruct Pair<KeyT, ValueT, true>\n{\n    KeyT     key;\n    ValueT   value;\n\n    bool operator<(const Pair &b) const\n    {\n        if (key < b.key)\n            return true;\n\n        if (key > b.key)\n            return false;\n\n        // KeyT in unsigned bits\n        typedef typename Traits<KeyT>::UnsignedBits UnsignedBits;\n\n        // Return true if key is negative zero and b.key is positive zero\n        UnsignedBits key_bits   = *reinterpret_cast<UnsignedBits*>(const_cast<KeyT*>(&key));\n        UnsignedBits b_key_bits = *reinterpret_cast<UnsignedBits*>(const_cast<KeyT*>(&b.key));\n        UnsignedBits HIGH_BIT   = Traits<KeyT>::HIGH_BIT;\n\n        return ((key_bits & HIGH_BIT) != 0) && ((b_key_bits & HIGH_BIT) == 0);\n    }\n};\n\n\n/**\n * Initialize key data\n */\ntemplate <typename KeyT>\nvoid InitializeKeyBits(\n    GenMode         gen_mode,\n    KeyT            *h_keys,\n    int             num_items,\n    int             entropy_reduction)\n{\n    for (int i = 0; i < num_items; ++i)\n        InitValue(gen_mode, h_keys[i], i);\n}\n\n\n/**\n * Initialize solution\n */\ntemplate <bool IS_DESCENDING, typename KeyT>\nvoid InitializeSolution(\n    KeyT    *h_keys,\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets,\n    int     begin_bit,\n    int     end_bit,\n    int     *&h_reference_ranks,\n    KeyT    *&h_reference_keys)\n{\n    typedef Pair<KeyT, int> PairT;\n\n    PairT *h_pairs = new PairT[num_items];\n\n    int num_bits = end_bit - begin_bit;\n    for (int i = 0; i < num_items; ++i)\n    {\n\n        // Mask off unwanted portions\n        if (num_bits < sizeof(KeyT) * 8)\n        {\n            unsigned long long base = 0;\n            memcpy(&base, &h_keys[i], sizeof(KeyT));\n            base &= ((1ull << num_bits) - 1) << begin_bit;\n            memcpy(&h_pairs[i].key, &base, sizeof(KeyT));\n        }\n        else\n        {\n            h_pairs[i].key = h_keys[i];\n        }\n\n        h_pairs[i].value = i;\n    }\n\n    printf(\"\\nSorting reference solution on CPU (%d segments)...\", num_segments); fflush(stdout);\n\n    for (int i = 0; i < num_segments; ++i)\n    {\n        if (IS_DESCENDING) std::reverse(h_pairs + h_segment_offsets[i], h_pairs + h_segment_offsets[i + 1]);\n        std::stable_sort(               h_pairs + h_segment_offsets[i], h_pairs + h_segment_offsets[i + 1]);\n        if (IS_DESCENDING) std::reverse(h_pairs + h_segment_offsets[i], h_pairs + h_segment_offsets[i + 1]);\n    }\n\n    printf(\" Done.\\n\"); fflush(stdout);\n\n    h_reference_ranks  = new int[num_items];\n    h_reference_keys   = new KeyT[num_items];\n\n    for (int i = 0; i < num_items; ++i)\n    {\n        h_reference_ranks[i]    = h_pairs[i].value;\n        h_reference_keys[i]     = h_keys[h_pairs[i].value];\n    }\n\n    if (h_pairs) delete[] h_pairs;\n}\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Test DeviceRadixSort\n */\ntemplate <\n    Backend     BACKEND,\n    bool        IS_DESCENDING,\n    typename    KeyT,\n    typename    ValueT>\nvoid Test(\n    KeyT        *h_keys,\n    ValueT      *h_values,\n    int         num_items,\n    int         num_segments,\n    int         *h_segment_offsets,\n    int         begin_bit,\n    int         end_bit,\n    KeyT        *h_reference_keys,\n    ValueT      *h_reference_values)\n{\n    const bool KEYS_ONLY = Equals<ValueT, NullType>::VALUE;\n\n    printf(\"%s %s cub::DeviceRadixSort %d items, %d segments, %d-byte keys (%s) %d-byte values (%s), descending %d, begin_bit %d, end_bit %d\\n\",\n        (BACKEND == CUB_NO_OVERWRITE) ? \"CUB_NO_OVERWRITE\" : (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        (KEYS_ONLY) ? \"keys-only\" : \"key-value\",\n        num_items, num_segments,\n        (int) sizeof(KeyT), typeid(KeyT).name(), (KEYS_ONLY) ? 0 : (int) sizeof(ValueT), typeid(ValueT).name(),\n        IS_DESCENDING, begin_bit, end_bit);\n    fflush(stdout);\n\n    if (g_verbose)\n    {\n        printf(\"Input keys:\\n\");\n        DisplayResults(h_keys, num_items);\n        printf(\"\\n\\n\");\n    }\n\n    // Allocate device arrays\n    DoubleBuffer<KeyT>   d_keys;\n    DoubleBuffer<ValueT> d_values;\n    int                 *d_selector;\n    int                 *d_segment_offsets;\n    size_t              *d_temp_storage_bytes;\n    cudaError_t         *d_cdp_error;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[0], sizeof(KeyT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(KeyT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_selector, sizeof(int) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_segment_offsets, sizeof(int) * (num_segments + 1)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes, sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error, sizeof(cudaError_t) * 1));\n    if (!KEYS_ONLY)\n    {\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[0], sizeof(ValueT) * num_items));\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values.d_buffers[1], sizeof(ValueT) * num_items));\n    }\n\n    // Allocate temporary storage (and make it un-aligned)\n    size_t  temp_storage_bytes  = 0;\n    void    *d_temp_storage     = NULL;\n    CubDebugExit(Dispatch(\n        Int2Type<IS_DESCENDING>(), Int2Type<BACKEND>(), d_selector, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_keys, d_values,\n        num_items, num_segments, d_segment_offsets,\n        begin_bit, end_bit, 0, true));\n\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes + 1));\n    void* mis_aligned_temp = static_cast<char*>(d_temp_storage) + 1;\n\n    // Initialize/clear device arrays\n    d_keys.selector = 0;\n    CubDebugExit(cudaMemcpy(d_keys.d_buffers[0], h_keys, sizeof(KeyT) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_keys.d_buffers[1], 0, sizeof(KeyT) * num_items));\n    if (!KEYS_ONLY)\n    {\n        d_values.selector = 0;\n        CubDebugExit(cudaMemcpy(d_values.d_buffers[0], h_values, sizeof(ValueT) * num_items, cudaMemcpyHostToDevice));\n        CubDebugExit(cudaMemset(d_values.d_buffers[1], 0, sizeof(ValueT) * num_items));\n    }\n    CubDebugExit(cudaMemcpy(d_segment_offsets, h_segment_offsets, sizeof(int) * (num_segments + 1), cudaMemcpyHostToDevice));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(\n        Int2Type<IS_DESCENDING>(), Int2Type<BACKEND>(), d_selector, d_temp_storage_bytes, d_cdp_error,\n        mis_aligned_temp, temp_storage_bytes, d_keys, d_values,\n        num_items, num_segments, d_segment_offsets,\n        begin_bit, end_bit, 0, true));\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Check for correctness (and display results, if specified)\n    printf(\"Warmup done.  Checking results:\\n\"); fflush(stdout);\n    int compare = CompareDeviceResults(h_reference_keys, d_keys.Current(), num_items, true, g_verbose);\n    printf(\"\\t Compare keys (selector %d): %s \", d_keys.selector, compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    if (!KEYS_ONLY)\n    {\n        int values_compare = CompareDeviceResults(h_reference_values, d_values.Current(), num_items, true, g_verbose);\n        compare |= values_compare;\n        printf(\"\\t Compare values (selector %d): %s \", d_values.selector, values_compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n    if (BACKEND == CUB_NO_OVERWRITE)\n    {\n        // Check that input isn't overwritten\n        int input_compare = CompareDeviceResults(h_keys, d_keys.d_buffers[0], num_items, true, g_verbose);\n        compare |= input_compare;\n        printf(\"\\t Compare input keys: %s \", input_compare ? \"FAIL\" : \"PASS\"); fflush(stdout);\n    }\n\n    // Performance\n    if (g_timing_iterations)\n        printf(\"\\nPerforming timing iterations:\\n\"); fflush(stdout);\n\n    GpuTimer gpu_timer;\n    float elapsed_millis = 0.0f;\n    for (int i = 0; i < g_timing_iterations; ++i)\n    {\n        // Initialize/clear device arrays\n        CubDebugExit(cudaMemcpy(d_keys.d_buffers[d_keys.selector], h_keys, sizeof(KeyT) * num_items, cudaMemcpyHostToDevice));\n        CubDebugExit(cudaMemset(d_keys.d_buffers[d_keys.selector ^ 1], 0, sizeof(KeyT) * num_items));\n        if (!KEYS_ONLY)\n        {\n            CubDebugExit(cudaMemcpy(d_values.d_buffers[d_values.selector], h_values, sizeof(ValueT) * num_items, cudaMemcpyHostToDevice));\n            CubDebugExit(cudaMemset(d_values.d_buffers[d_values.selector ^ 1], 0, sizeof(ValueT) * num_items));\n        }\n\n        gpu_timer.Start();\n        CubDebugExit(Dispatch(\n            Int2Type<IS_DESCENDING>(), Int2Type<BACKEND>(), d_selector, d_temp_storage_bytes, d_cdp_error,\n            mis_aligned_temp, temp_storage_bytes, d_keys, d_values,\n            num_items, num_segments, d_segment_offsets,\n            begin_bit, end_bit, 0, false));\n        gpu_timer.Stop();\n        elapsed_millis += gpu_timer.ElapsedMillis();\n    }\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth = (KEYS_ONLY) ?\n            giga_rate * sizeof(KeyT) * 2 :\n            giga_rate * (sizeof(KeyT) + sizeof(ValueT)) * 2;\n        printf(\"\\n%.3f elapsed ms, %.3f avg ms, %.3f billion items/s, %.3f logical GB/s\", elapsed_millis, avg_millis, giga_rate, giga_bandwidth);\n    }\n\n    printf(\"\\n\\n\");\n\n    // Cleanup\n    if (d_keys.d_buffers[0]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[0]));\n    if (d_keys.d_buffers[1]) CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[1]));\n    if (d_values.d_buffers[0]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[0]));\n    if (d_values.d_buffers[1]) CubDebugExit(g_allocator.DeviceFree(d_values.d_buffers[1]));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_selector) CubDebugExit(g_allocator.DeviceFree(d_selector));\n    if (d_segment_offsets) CubDebugExit(g_allocator.DeviceFree(d_segment_offsets));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n\n    // Correctness asserts\n    AssertEquals(0, compare);\n}\n\n\n/**\n * Test backend\n */\ntemplate <bool IS_DESCENDING, typename KeyT, typename ValueT>\nvoid TestBackend(\n    KeyT    *h_keys,\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets,\n    int     begin_bit,\n    int     end_bit,\n    KeyT    *h_reference_keys,\n    int     *h_reference_ranks)\n{\n    const bool KEYS_ONLY = Equals<ValueT, NullType>::VALUE;\n\n    ValueT *h_values             = NULL;\n    ValueT *h_reference_values   = NULL;\n\n    if (!KEYS_ONLY)\n    {\n        h_values            = new ValueT[num_items];\n        h_reference_values  = new ValueT[num_items];\n\n        for (int i = 0; i < num_items; ++i)\n        {\n            InitValue(INTEGER_SEED, h_values[i], i);\n            InitValue(INTEGER_SEED, h_reference_values[i], h_reference_ranks[i]);\n        }\n    }\n\n    if (num_segments == 1)\n    {\n        // Test single-segment implementations\n        Test<CUB, IS_DESCENDING>(               h_keys, h_values, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_values);\n        Test<CUB_NO_OVERWRITE, IS_DESCENDING>(  h_keys, h_values, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_values);\n#ifdef CUB_CDP\n        Test<CDP, IS_DESCENDING>(               h_keys, h_values, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_values);\n#endif\n    }\n\n    // Test multi-segment implementations\n    Test<CUB_SEGMENTED, IS_DESCENDING>(               h_keys, h_values, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_values);\n    Test<CUB_SEGMENTED_NO_OVERWRITE, IS_DESCENDING>(  h_keys, h_values, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_values);\n\n    if (h_values) delete[] h_values;\n    if (h_reference_values) delete[] h_reference_values;\n}\n\n\n\n\n/**\n * Test value type\n */\ntemplate <bool IS_DESCENDING, typename KeyT>\nvoid TestValueTypes(\n    KeyT    *h_keys,\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets,\n    int     begin_bit,\n    int     end_bit)\n{\n    // Initialize the solution\n\n    int *h_reference_ranks = NULL;\n    KeyT *h_reference_keys = NULL;\n    InitializeSolution<IS_DESCENDING>(h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_ranks, h_reference_keys);\n\n    // Test keys-only\n    TestBackend<IS_DESCENDING, KeyT, NullType>          (h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_ranks);\n\n    // Test with 8b value\n    TestBackend<IS_DESCENDING, KeyT, unsigned char>     (h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_ranks);\n\n    // Test with 32b value\n    TestBackend<IS_DESCENDING, KeyT, unsigned int>      (h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_ranks);\n\n    // Test with 64b value\n    TestBackend<IS_DESCENDING, KeyT, unsigned long long>(h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_ranks);\n\n    // Test with non-trivially-constructable value\n    TestBackend<IS_DESCENDING, KeyT, TestBar>           (h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit, h_reference_keys, h_reference_ranks);\n\n    // Cleanup\n    if (h_reference_ranks) delete[] h_reference_ranks;\n    if (h_reference_keys) delete[] h_reference_keys;\n}\n\n\n\n/**\n * Test ascending/descending\n */\ntemplate <typename KeyT>\nvoid TestDirection(\n    KeyT    *h_keys,\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets,\n    int     begin_bit,\n    int     end_bit)\n{\n    TestValueTypes<true>(h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit);\n    TestValueTypes<false>(h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit);\n}\n\n\n/**\n * Test different bit ranges\n */\ntemplate <typename KeyT>\nvoid TestBits(\n    KeyT    *h_keys,\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets)\n{\n    // Don't test partial-word sorting for boolean, fp, or signed types (the bit-flipping techniques get in the way)\n    if ((Traits<KeyT>::CATEGORY == UNSIGNED_INTEGER) && (!Equals<KeyT, bool>::VALUE))\n    {\n        // Partial bits\n        int begin_bit = 1;\n        int end_bit = (sizeof(KeyT) * 8) - 1;\n        printf(\"Testing key bits [%d,%d)\\n\", begin_bit, end_bit); fflush(stdout);\n        TestDirection(h_keys, num_items, num_segments, h_segment_offsets, begin_bit, end_bit);\n\n        // Across subword boundaries\n        int mid_bit = sizeof(KeyT) * 4;\n        printf(\"Testing key bits [%d,%d)\\n\", mid_bit - 1, mid_bit + 1); fflush(stdout);\n        TestDirection(h_keys, num_items, num_segments, h_segment_offsets, mid_bit - 1, mid_bit + 1);\n    }\n\n    printf(\"Testing key bits [%d,%d)\\n\", 0, int(sizeof(KeyT)) * 8); fflush(stdout);\n    TestDirection(h_keys, num_items, num_segments, h_segment_offsets, 0, sizeof(KeyT) * 8);\n}\n\n\n/**\n * Test different segment compositions\n */\ntemplate <typename KeyT>\nvoid TestSegments(\n    KeyT    *h_keys,\n    int     num_items,\n    int     max_segments)\n{\n    int *h_segment_offsets = new int[max_segments + 1];\n\n    for (int num_segments = max_segments; num_segments > 1; num_segments = (num_segments + 32 - 1) / 32)\n    {\n        if (num_items / num_segments < 128 * 1000) {\n            // Right now we assign a single thread block to each segment, so lets keep it to under 128K items per segment\n            InitializeSegments(num_items, num_segments, h_segment_offsets);\n            TestBits(h_keys, num_items, num_segments, h_segment_offsets);\n        }\n    }\n\n    // Test single segment\n    if (num_items < 128 * 1000) {\n        // Right now we assign a single thread block to each segment, so lets keep it to under 128K items per segment\n        InitializeSegments(num_items, 1, h_segment_offsets);\n        TestBits(h_keys, num_items, 1, h_segment_offsets);\n    }\n\n    if (h_segment_offsets) delete[] h_segment_offsets;\n}\n\n\n/**\n * Test different (sub)lengths and number of segments\n */\ntemplate <typename KeyT>\nvoid TestSizes(\n    KeyT    *h_keys,\n    int     max_items,\n    int     max_segments)\n{\n    for (int num_items = max_items; num_items > 1; num_items = (num_items + 32 - 1) / 32)\n    {\n        TestSegments(h_keys, num_items, max_segments);\n    }\n    TestSegments(h_keys, 1, max_segments);\n    TestSegments(h_keys, 0, max_segments);\n}\n\n\n/**\n * Test key sampling distributions\n */\ntemplate <typename KeyT>\nvoid TestGen(\n    int             max_items,\n    int             max_segments)\n{\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n    if (max_items < 0)\n        max_items = (ptx_version > 100) ? 9000003 : max_items = 5000003;\n\n    if (max_segments < 0)\n        max_segments = 5003;\n\n    KeyT *h_keys = new KeyT[max_items];\n\n    for (int entropy_reduction = 0; entropy_reduction <= 6; entropy_reduction += 3)\n    {\n        printf(\"\\nTesting random %s keys with entropy reduction factor %d\\n\", typeid(KeyT).name(), entropy_reduction); fflush(stdout);\n        InitializeKeyBits(RANDOM, h_keys, max_items, entropy_reduction);\n        TestSizes(h_keys, max_items, max_segments);\n    }\n\n    printf(\"\\nTesting uniform %s keys\\n\", typeid(KeyT).name()); fflush(stdout);\n    InitializeKeyBits(UNIFORM, h_keys, max_items, 0);\n    TestSizes(h_keys, max_items, max_segments);\n\n    printf(\"\\nTesting natural number %s keys\\n\", typeid(KeyT).name()); fflush(stdout);\n    InitializeKeyBits(INTEGER_SEED, h_keys, max_items, 0);\n    TestSizes(h_keys, max_items, max_segments);\n\n    if (h_keys) delete[] h_keys;\n}\n\n\n//---------------------------------------------------------------------\n// Simple test\n//---------------------------------------------------------------------\n\ntemplate <\n    Backend     BACKEND,\n    typename    KeyT,\n    typename    ValueT,\n    bool        IS_DESCENDING>\nvoid Test(\n    int         num_items,\n    int         num_segments,\n    GenMode     gen_mode,\n    int         entropy_reduction,\n    int         begin_bit,\n    int         end_bit)\n{\n    const bool KEYS_ONLY = Equals<ValueT, NullType>::VALUE;\n\n    KeyT    *h_keys             = new KeyT[num_items];\n    int     *h_reference_ranks  = NULL;\n    KeyT    *h_reference_keys   = NULL;\n    ValueT  *h_values           = NULL;\n    ValueT  *h_reference_values = NULL;\n    int     *h_segment_offsets  = new int[num_segments + 1];\n\n    if (end_bit < 0)\n        end_bit = sizeof(KeyT) * 8;\n\n    InitializeKeyBits(gen_mode, h_keys, num_items, entropy_reduction);\n    InitializeSegments(num_items, num_segments, h_segment_offsets);\n    InitializeSolution<IS_DESCENDING>(\n        h_keys, num_items, num_segments, h_segment_offsets,\n        begin_bit, end_bit, h_reference_ranks, h_reference_keys);\n\n    if (!KEYS_ONLY)\n    {\n        h_values            = new ValueT[num_items];\n        h_reference_values  = new ValueT[num_items];\n\n        for (int i = 0; i < num_items; ++i)\n        {\n            InitValue(INTEGER_SEED, h_values[i], i);\n            InitValue(INTEGER_SEED, h_reference_values[i], h_reference_ranks[i]);\n        }\n    }\n    if (h_reference_ranks) delete[] h_reference_ranks;\n\n    printf(\"\\nTesting bits [%d,%d) of %s keys with gen-mode %d\\n\", begin_bit, end_bit, typeid(KeyT).name(), gen_mode); fflush(stdout);\n    Test<BACKEND, IS_DESCENDING>(\n        h_keys, h_values,\n        num_items, num_segments, h_segment_offsets,\n        begin_bit, end_bit, h_reference_keys, h_reference_values);\n\n    if (h_keys)             delete[] h_keys;\n    if (h_reference_keys)   delete[] h_reference_keys;\n    if (h_values)           delete[] h_values;\n    if (h_reference_values) delete[] h_reference_values;\n    if (h_segment_offsets)  delete[] h_segment_offsets;\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int bits = -1;\n    int num_items = -1;\n    int num_segments = -1;\n    int entropy_reduction = 0;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"s\", num_segments);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"bits\", bits);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--bits=<valid key bits>]\"\n            \"[--n=<input items> \"\n            \"[--s=<num segments> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--entropy=<entropy-reduction factor (default 0)>]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef QUICKER_TEST\n\n    enum {\n        IS_DESCENDING   = false\n    };\n\n    // Compile/run basic CUB test\n    if (num_items < 0)      num_items       = 48000000;\n    if (num_segments < 0)   num_segments    = 5000;\n\n\n    Test<CUB_SEGMENTED, unsigned int,       NullType, IS_DESCENDING>(       num_items, num_segments,    RANDOM, entropy_reduction, 0, bits);\n\n    Test<CUB,           unsigned int,       NullType, IS_DESCENDING>(       num_items, 1,               RANDOM, entropy_reduction, 0, bits);\n    Test<CUB,           unsigned long long, NullType, IS_DESCENDING>(       num_items, 1,               RANDOM, entropy_reduction, 0, bits);\n\n    Test<CUB,           unsigned int,       unsigned int, IS_DESCENDING>(   num_items, 1,               RANDOM, entropy_reduction, 0, bits);\n    Test<CUB,           unsigned long long, unsigned int, IS_DESCENDING>(   num_items, 1,               RANDOM, entropy_reduction, 0, bits);\n\n#elif defined(QUICK_TEST)\n\n    // Compile/run quick tests\n    if (num_items < 0)      num_items       = 48000000;\n    if (num_segments < 0)   num_segments    = 5000;\n\n    // Compare CUB and thrust on 32b keys-only\n    Test<CUB, unsigned int, NullType, false> (                      num_items, 1, RANDOM, entropy_reduction, 0, bits);\n    Test<THRUST, unsigned int, NullType, false> (                   num_items, 1, RANDOM, entropy_reduction, 0, bits);\n\n    // Compare CUB and thrust on 64b keys-only\n    Test<CUB, unsigned long long, NullType, false> (                num_items, 1, RANDOM, entropy_reduction, 0, bits);\n    Test<THRUST, unsigned long long, NullType, false> (             num_items, 1, RANDOM, entropy_reduction, 0, bits);\n\n\n    // Compare CUB and thrust on 32b key-value pairs\n    Test<CUB, unsigned int, unsigned int, false> (                  num_items, 1, RANDOM, entropy_reduction, 0, bits);\n    Test<THRUST, unsigned int, unsigned int, false> (               num_items, 1, RANDOM, entropy_reduction, 0, bits);\n\n    // Compare CUB and thrust on 64b key-value pairs\n    Test<CUB, unsigned long long, unsigned long long, false> (      num_items, 1, RANDOM, entropy_reduction, 0, bits);\n    Test<THRUST, unsigned long long, unsigned long long, false> (   num_items, 1, RANDOM, entropy_reduction, 0, bits);\n\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        TestGen<bool>                 (num_items, num_segments);\n\n        TestGen<char>                 (num_items, num_segments);\n        TestGen<signed char>          (num_items, num_segments);\n        TestGen<unsigned char>        (num_items, num_segments);\n\n        TestGen<short>                (num_items, num_segments);\n        TestGen<unsigned short>       (num_items, num_segments);\n\n        TestGen<int>                  (num_items, num_segments);\n        TestGen<unsigned int>         (num_items, num_segments);\n\n        TestGen<long>                 (num_items, num_segments);\n        TestGen<unsigned long>        (num_items, num_segments);\n\n        TestGen<long long>            (num_items, num_segments);\n        TestGen<unsigned long long>   (num_items, num_segments);\n\n        TestGen<float>                (num_items, num_segments);\n\n        if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n            TestGen<double>           (num_items, num_segments);\n\n    }\n\n#endif\n\n    return 0;\n}\n\n"
  },
  {
    "path": "external/cub/test/test_device_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceReduce utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <limits>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/reduce.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_reduce.cuh>\n#include <cub/device/device_segmented_reduce.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/iterator/discard_output_iterator.cuh>\n#include <cub/iterator/transform_input_iterator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nint                     g_ptx_version;\nint                     g_sm_count;\nbool                    g_verbose           = false;\nbool                    g_verbose_input     = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n// Dispatch types\nenum Backend\n{\n    CUB,            // CUB method\n    CUB_SEGMENTED,  // CUB segmented method\n    CUB_CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n    THRUST,         // Thrust method\n};\n\n\n// Custom max functor\nstruct CustomMax\n{\n    /// Boolean max operator, returns <tt>(a > b) ? a : b</tt>\n    template <typename OutputT>\n    __host__ __device__ __forceinline__ OutputT operator()(const OutputT &a, const OutputT &b)\n    {\n        return CUB_MAX(a, b);\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB DeviceReduce entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to reduce entrypoint (custom-max)\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT, typename ReductionOpT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    ReductionOpT        reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Max-identity\n    OutputT identity = Traits<InputT>::Lowest(); // replace with std::numeric_limits<OutputT>::lowest() when C++ support is more prevalent\n\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::Reduce(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, num_items, reduction_op, identity,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Sum            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::Sum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to min entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Min            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::Min(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to max entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Max            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::Max(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to argmin entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::ArgMin         reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::ArgMin(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to argmax entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::ArgMax         reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::ArgMax(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB DeviceSegmentedReduce entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to reduce entrypoint (custom-max)\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT, typename ReductionOpT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    ReductionOpT        reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    // Max-identity\n    OutputT identity = Traits<InputT>::Lowest(); // replace with std::numeric_limits<OutputT>::lowest() when C++ support is more prevalent\n\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::Reduce(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1, reduction_op, identity,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Sum            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::Sum(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to min entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Min            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::Min(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to max entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::Max            reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::Max(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to argmin entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::ArgMin         reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::ArgMin(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n/**\n * Dispatch to argmax entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_SEGMENTED>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    cub::ArgMax         reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to device reduction directly\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSegmentedReduce::ArgMax(d_temp_storage, temp_storage_bytes,\n            d_in, d_out, max_segments, d_segment_offsets, d_segment_offsets + 1,\n            stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to reduction entrypoint (min or max specialization)\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT, typename ReductionOpT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    ReductionOpT         reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        OutputT init;\n        CubDebugExit(cudaMemcpy(&init, d_in + 0, sizeof(OutputT), cudaMemcpyDeviceToHost));\n\n        thrust::device_ptr<OutputT> d_in_wrapper(d_in);\n        OutputT retval;\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            retval = thrust::reduce(d_in_wrapper, d_in_wrapper + num_items, init, reduction_op);\n        }\n\n        if (!Equals<OutputIteratorT, DiscardOutputIterator<int> >::VALUE)\n            CubDebugExit(cudaMemcpy(d_out, &retval, sizeof(OutputT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n/**\n * Dispatch to reduction entrypoint (sum specialization)\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    Sum                 reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<OutputT> d_in_wrapper(d_in);\n        OutputT retval;\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            retval = thrust::reduce(d_in_wrapper, d_in_wrapper + num_items);\n        }\n\n        if (!Equals<OutputIteratorT, DiscardOutputIterator<int> >::VALUE)\n            CubDebugExit(cudaMemcpy(d_out, &retval, sizeof(OutputT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n//---------------------------------------------------------------------\n// CUDA nested-parallelism test kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceReduce\n */\ntemplate <\n    typename            InputIteratorT,\n    typename            OutputIteratorT,\n    typename            OffsetIteratorT,\n    typename            ReductionOpT>\n__global__ void CnpDispatchKernel(\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t              temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    ReductionOpT        reduction_op,\n    bool                debug_synchronous)\n{\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(Int2Type<CUB>(), timing_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n        d_in, d_out, num_items, max_segments, d_segment_offsets, reduction_op, 0, debug_synchronous);\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CUB_CDP kernel\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetIteratorT, typename ReductionOpT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB_CDP>       dispatch_to,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    int                 num_items,\n    int                 max_segments,\n    OffsetIteratorT     d_segment_offsets,\n    ReductionOpT        reduction_op,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(timing_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n        d_in, d_out, num_items, max_segments, d_segment_offsets, reduction_op, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Problem generation\n//---------------------------------------------------------------------\n\n/// Initialize problem\ntemplate <typename InputT>\nvoid Initialize(\n    GenMode         gen_mode,\n    InputT          *h_in,\n    int             num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n    }\n\n    if (g_verbose_input)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/// Solve problem (max/custom-max functor)\ntemplate <typename ReductionOpT, typename InputT, typename _OutputT>\nstruct Solution\n{\n    typedef _OutputT OutputT;\n\n    template <typename HostInputIteratorT, typename OffsetT, typename OffsetIteratorT>\n    static void Solve(HostInputIteratorT h_in, OutputT *h_reference, OffsetT num_segments, OffsetIteratorT h_segment_offsets,\n        ReductionOpT reduction_op)\n    {\n        for (int i = 0; i < num_segments; ++i)\n        {\n            OutputT aggregate = Traits<InputT>::Lowest(); // replace with std::numeric_limits<OutputT>::lowest() when C++ support is more prevalent\n            for (int j = h_segment_offsets[i]; j < h_segment_offsets[i + 1]; ++j)\n                aggregate = reduction_op(aggregate, OutputT(h_in[j]));\n            h_reference[i] = aggregate;\n        }\n    }\n};\n\n/// Solve problem (min functor)\ntemplate <typename InputT, typename _OutputT>\nstruct Solution<cub::Min, InputT, _OutputT>\n{\n    typedef _OutputT OutputT;\n\n    template <typename HostInputIteratorT, typename OffsetT, typename OffsetIteratorT>\n    static void Solve(HostInputIteratorT h_in, OutputT *h_reference, OffsetT num_segments, OffsetIteratorT h_segment_offsets,\n        cub::Min reduction_op)\n    {\n        for (int i = 0; i < num_segments; ++i)\n        {\n            OutputT aggregate = Traits<InputT>::Max();    // replace with std::numeric_limits<OutputT>::max() when C++ support is more prevalent\n            for (int j = h_segment_offsets[i]; j < h_segment_offsets[i + 1]; ++j)\n                aggregate = reduction_op(aggregate, OutputT(h_in[j]));\n            h_reference[i] = aggregate;\n        }\n    }\n};\n\n\n/// Solve problem (sum functor)\ntemplate <typename InputT, typename _OutputT>\nstruct Solution<cub::Sum, InputT, _OutputT>\n{\n    typedef _OutputT OutputT;\n\n    template <typename HostInputIteratorT, typename OffsetT, typename OffsetIteratorT>\n    static void Solve(HostInputIteratorT h_in, OutputT *h_reference, OffsetT num_segments, OffsetIteratorT h_segment_offsets,\n        cub::Sum reduction_op)\n    {\n        for (int i = 0; i < num_segments; ++i)\n        {\n            OutputT aggregate;\n            InitValue(INTEGER_SEED, aggregate, 0);\n            for (int j = h_segment_offsets[i]; j < h_segment_offsets[i + 1]; ++j)\n                aggregate = reduction_op(aggregate, OutputT(h_in[j]));\n            h_reference[i] = aggregate;\n        }\n    }\n};\n\n/// Solve problem (argmin functor)\ntemplate <typename InputValueT, typename OutputValueT>\nstruct Solution<cub::ArgMin, InputValueT, OutputValueT>\n{\n    typedef KeyValuePair<int, OutputValueT> OutputT;\n\n    template <typename HostInputIteratorT, typename OffsetT, typename OffsetIteratorT>\n    static void Solve(HostInputIteratorT h_in, OutputT *h_reference, OffsetT num_segments, OffsetIteratorT h_segment_offsets,\n        cub::ArgMin reduction_op)\n    {\n        for (int i = 0; i < num_segments; ++i)\n        {\n            OutputT aggregate(1, Traits<InputValueT>::Max()); // replace with std::numeric_limits<OutputT>::max() when C++ support is more prevalent\n            for (int j = h_segment_offsets[i]; j < h_segment_offsets[i + 1]; ++j)\n            {\n                OutputT item(j - h_segment_offsets[i], OutputValueT(h_in[j]));\n                aggregate = reduction_op(aggregate, item);\n            }\n            h_reference[i] = aggregate;\n        }\n    }\n};\n\n\n/// Solve problem (argmax functor)\ntemplate <typename InputValueT, typename OutputValueT>\nstruct Solution<cub::ArgMax, InputValueT, OutputValueT>\n{\n    typedef KeyValuePair<int, OutputValueT> OutputT;\n\n    template <typename HostInputIteratorT, typename OffsetT, typename OffsetIteratorT>\n    static void Solve(HostInputIteratorT h_in, OutputT *h_reference, OffsetT num_segments, OffsetIteratorT h_segment_offsets,\n        cub::ArgMax reduction_op)\n    {\n        for (int i = 0; i < num_segments; ++i)\n        {\n            OutputT aggregate(1, Traits<InputValueT>::Lowest()); // replace with std::numeric_limits<OutputT>::lowest() when C++ support is more prevalent\n            for (int j = h_segment_offsets[i]; j < h_segment_offsets[i + 1]; ++j)\n            {\n                OutputT item(j - h_segment_offsets[i], OutputValueT(h_in[j]));\n                aggregate = reduction_op(aggregate, item);\n            }\n            h_reference[i] = aggregate;\n        }\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Problem generation\n//---------------------------------------------------------------------\n\n/// Test DeviceReduce for a given problem input\ntemplate <\n    typename                BackendT,\n    typename                DeviceInputIteratorT,\n    typename                HostReferenceIteratorT,\n    typename                OffsetT,\n    typename                OffsetIteratorT,\n    typename                ReductionOpT>\nvoid Test(\n    BackendT                backend,\n    DeviceInputIteratorT    d_in,\n    OffsetT                 num_items,\n    OffsetT                 num_segments,\n    OffsetIteratorT         d_segment_offsets,\n    ReductionOpT            reduction_op,\n    HostReferenceIteratorT  h_reference)\n{\n    // Input and output data types\n    typedef typename std::iterator_traits<DeviceInputIteratorT>::value_type     InputT;\n    typedef typename std::iterator_traits<HostReferenceIteratorT>::value_type   OutputT;\n\n    // Allocate CUB_CDP device arrays for temp storage size and error\n    OutputT         *d_out = NULL;\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out,                 sizeof(OutputT) * num_segments));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Inquire temp device storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(backend, 1,\n        d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n        d_in, d_out, num_items, num_segments, d_segment_offsets,\n        reduction_op, 0, true));\n\n    // Allocate temp device storage\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(OutputT) * num_segments));\n\n    // Run once with discard iterator\n    DiscardOutputIterator<OffsetT> discard_itr;\n    CubDebugExit(Dispatch(backend, 1,\n        d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n        d_in, discard_itr, num_items, num_segments, d_segment_offsets,\n        reduction_op, 0, true));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(backend, 1,\n        d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n        d_in, d_out, num_items, num_segments, d_segment_offsets,\n        reduction_op, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_segments, g_verbose, g_verbose);\n    printf(\"\\t%s\", compare ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    if (g_timing_iterations > 0)\n    {\n        GpuTimer gpu_timer;\n        gpu_timer.Start();\n\n        CubDebugExit(Dispatch(backend, g_timing_iterations,\n            d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes,\n            d_in, d_out, num_items, num_segments, d_segment_offsets,\n            reduction_op, 0, false));\n\n        gpu_timer.Stop();\n        float elapsed_millis = gpu_timer.ElapsedMillis();\n\n        // Display performance\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth = giga_rate * sizeof(InputT);\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s\", avg_millis, giga_rate, giga_bandwidth);\n    }\n\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare);\n}\n\n\n/// Test DeviceReduce\ntemplate <\n    Backend                 BACKEND,\n    typename                OutputValueT,\n    typename                HostInputIteratorT,\n    typename                DeviceInputIteratorT,\n    typename                OffsetT,\n    typename                OffsetIteratorT,\n    typename                ReductionOpT>\nvoid SolveAndTest(\n    HostInputIteratorT      h_in,\n    DeviceInputIteratorT    d_in,\n    OffsetT                 num_items,\n    OffsetT                 num_segments,\n    OffsetIteratorT         h_segment_offsets,\n    OffsetIteratorT         d_segment_offsets,\n    ReductionOpT            reduction_op)\n{\n    typedef typename std::iterator_traits<DeviceInputIteratorT>::value_type     InputValueT;\n    typedef Solution<ReductionOpT, InputValueT, OutputValueT>                   SolutionT;\n    typedef typename SolutionT::OutputT                                         OutputT;\n\n    printf(\"\\n\\n%s cub::DeviceReduce<%s> %d items (%s), %d segments\\n\",\n        (BACKEND == CUB_CDP) ? \"CUB_CDP\" : (BACKEND == THRUST) ? \"Thrust\" : (BACKEND == CUB_SEGMENTED) ? \"CUB_SEGMENTED\" : \"CUB\",\n        typeid(ReductionOpT).name(), num_items, typeid(HostInputIteratorT).name(), num_segments);\n    fflush(stdout);\n\n    // Allocate and solve solution\n    OutputT *h_reference = new OutputT[num_segments];\n    SolutionT::Solve(h_in, h_reference, num_segments, h_segment_offsets, reduction_op);\n\n    // Run test\n    Test(Int2Type<BACKEND>(), d_in, num_items, num_segments, d_segment_offsets, reduction_op, h_reference);\n\n    // Cleanup\n    if (h_reference) delete[] h_reference;\n}\n\n\n/// Test specific problem type\ntemplate <\n    Backend         BACKEND,\n    typename        InputT,\n    typename        OutputT,\n    typename        OffsetT,\n    typename        ReductionOpT>\nvoid TestProblem(\n    OffsetT         num_items,\n    OffsetT         num_segments,\n    GenMode         gen_mode,\n    ReductionOpT    reduction_op)\n{\n    printf(\"\\n\\nInitializing %d %s->%s (gen mode %d)... \", num_items, typeid(InputT).name(), typeid(OutputT).name(), gen_mode); fflush(stdout);\n    fflush(stdout);\n\n    // Initialize value data\n    InputT* h_in = new InputT[num_items];\n    Initialize(gen_mode, h_in, num_items);\n\n    // Initialize segment data\n    OffsetT *h_segment_offsets = new OffsetT[num_segments + 1];\n    InitializeSegments(num_items, num_segments, h_segment_offsets, g_verbose_input);\n\n    // Initialize device data\n    OffsetT *d_segment_offsets      = NULL;\n    InputT  *d_in                   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in,              sizeof(InputT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_segment_offsets, sizeof(OffsetT) * (num_segments + 1)));\n    CubDebugExit(cudaMemcpy(d_in,               h_in,                   sizeof(InputT) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_segment_offsets,  h_segment_offsets,      sizeof(OffsetT) * (num_segments + 1), cudaMemcpyHostToDevice));\n\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, reduction_op);\n\n    if (h_segment_offsets)  delete[] h_segment_offsets;\n    if (d_segment_offsets)  CubDebugExit(g_allocator.DeviceFree(d_segment_offsets));\n    if (h_in)               delete[] h_in;\n    if (d_in)               CubDebugExit(g_allocator.DeviceFree(d_in));\n}\n\n\n/// Test different operators\ntemplate <\n    Backend             BACKEND,\n    typename            OutputT,\n    typename            HostInputIteratorT,\n    typename            DeviceInputIteratorT,\n    typename            OffsetT,\n    typename            OffsetIteratorT>\nvoid TestByOp(\n    HostInputIteratorT      h_in,\n    DeviceInputIteratorT    d_in,\n    OffsetT                 num_items,\n    OffsetT                 num_segments,\n    OffsetIteratorT         h_segment_offsets,\n    OffsetIteratorT         d_segment_offsets)\n{\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, CustomMax());\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, Sum());\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, Min());\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, ArgMin());\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, Max());\n    SolveAndTest<BACKEND, OutputT>(h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets, ArgMax());\n}\n\n\n/// Test different backends\ntemplate <\n    typename    InputT,\n    typename    OutputT,\n    typename    OffsetT>\nvoid TestByBackend(\n    OffsetT     num_items,\n    OffsetT     max_segments,\n    GenMode     gen_mode)\n{\n    // Initialize host data\n    printf(\"\\n\\nInitializing %d %s -> %s (gen mode %d)... \",\n        num_items, typeid(InputT).name(), typeid(OutputT).name(), gen_mode); fflush(stdout);\n\n    InputT  *h_in               = new InputT[num_items];\n    OffsetT *h_segment_offsets  = new OffsetT[max_segments + 1];\n    Initialize(gen_mode, h_in, num_items);\n\n    // Initialize device data\n    InputT  *d_in               = NULL;\n    OffsetT *d_segment_offsets  = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(InputT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_segment_offsets, sizeof(OffsetT) * (max_segments + 1)));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(InputT) * num_items, cudaMemcpyHostToDevice));\n\n    //\n    // Test single-segment implementations\n    //\n\n    InitializeSegments(num_items, 1, h_segment_offsets, g_verbose_input);\n\n    // Page-aligned-input tests\n    TestByOp<CUB, OutputT>(h_in, d_in, num_items, 1, h_segment_offsets, (OffsetT*) NULL);                 // Host-dispatch\n#ifdef CUB_CDP\n    TestByOp<CUB_CDP, OutputT>(h_in, d_in, num_items, 1, h_segment_offsets, (OffsetT*) NULL);             // Device-dispatch\n#endif\n\n    // Non-page-aligned-input tests\n    if (num_items > 1)\n    {\n        InitializeSegments(num_items - 1, 1, h_segment_offsets, g_verbose_input);\n        TestByOp<CUB, OutputT>(h_in + 1, d_in + 1, num_items - 1, 1, h_segment_offsets, (OffsetT*) NULL);\n    }\n\n    //\n    // Test segmented implementation\n    //\n\n    // Right now we assign a single thread block to each segment, so lets keep it to under 128K items per segment\n    int max_items_per_segment = 128000;\n\n    for (int num_segments = (num_items + max_items_per_segment - 1) / max_items_per_segment;\n        num_segments < max_segments;\n        num_segments = (num_segments * 32) + 1)\n    {\n        // Test with segment pointer\n        InitializeSegments(num_items, num_segments, h_segment_offsets, g_verbose_input);\n        CubDebugExit(cudaMemcpy(d_segment_offsets, h_segment_offsets, sizeof(OffsetT) * (num_segments + 1), cudaMemcpyHostToDevice));\n        TestByOp<CUB_SEGMENTED, OutputT>(\n            h_in, d_in, num_items, num_segments, h_segment_offsets, d_segment_offsets);\n\n        // Test with segment iterator\n        typedef CastOp<OffsetT> IdentityOpT;\n        IdentityOpT identity_op;\n        TransformInputIterator<OffsetT, IdentityOpT, OffsetT*, OffsetT> h_segment_offsets_itr(\n            h_segment_offsets,\n            identity_op);\n       TransformInputIterator<OffsetT, IdentityOpT, OffsetT*, OffsetT> d_segment_offsets_itr(\n            d_segment_offsets,\n            identity_op);\n\n        TestByOp<CUB_SEGMENTED, OutputT>(\n            h_in, d_in, num_items, num_segments, h_segment_offsets_itr, d_segment_offsets_itr);\n    }\n\n    if (h_in)               delete[] h_in;\n    if (h_segment_offsets)  delete[] h_segment_offsets;\n    if (d_in)               CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_segment_offsets)  CubDebugExit(g_allocator.DeviceFree(d_segment_offsets));\n}\n\n\n/// Test different input-generation modes\ntemplate <\n    typename InputT,\n    typename OutputT,\n    typename OffsetT>\nvoid TestByGenMode(\n    OffsetT num_items,\n    OffsetT max_segments)\n{\n    //\n    // Test pointer support using different input-generation modes\n    //\n\n    TestByBackend<InputT, OutputT>(num_items, max_segments, UNIFORM);\n    TestByBackend<InputT, OutputT>(num_items, max_segments, INTEGER_SEED);\n    TestByBackend<InputT, OutputT>(num_items, max_segments, RANDOM);\n\n    //\n    // Test iterator support using a constant-iterator and SUM\n    //\n\n    InputT val;\n    InitValue(UNIFORM, val, 0);\n    ConstantInputIterator<InputT, OffsetT> h_in(val);\n\n    OffsetT *h_segment_offsets = new OffsetT[1 + 1];\n    InitializeSegments(num_items, 1, h_segment_offsets, g_verbose_input);\n\n    SolveAndTest<CUB, OutputT>(h_in, h_in, num_items, 1, h_segment_offsets, (OffsetT*) NULL, Sum());\n#ifdef CUB_CDP\n    SolveAndTest<CUB_CDP, OutputT>(h_in, h_in, num_items, 1, h_segment_offsets, (OffsetT*) NULL, Sum());\n#endif\n\n    if (h_segment_offsets) delete[] h_segment_offsets;\n}\n\n\n/// Test different problem sizes\ntemplate <\n    typename InputT,\n    typename OutputT,\n    typename OffsetT>\nstruct TestBySize\n{\n    OffsetT max_items;\n    OffsetT max_segments;\n\n    TestBySize(OffsetT max_items, OffsetT max_segments) :\n        max_items(max_items),\n        max_segments(max_segments)\n    {}\n\n    template <typename ActivePolicyT>\n    cudaError_t Invoke()\n    {\n        //\n        // Black-box testing on all backends\n        //\n\n        // Test 0, 1, many\n        TestByGenMode<InputT, OutputT>(0,           max_segments);\n        TestByGenMode<InputT, OutputT>(1,           max_segments);\n        TestByGenMode<InputT, OutputT>(max_items,   max_segments);\n\n        // Test random problem sizes from a log-distribution [8, max_items-ish)\n        int     num_iterations = 8;\n        double  max_exp = log(double(max_items)) / log(double(2.0));\n        for (int i = 0; i < num_iterations; ++i)\n        {\n            OffsetT num_items = (OffsetT) pow(2.0, RandomValue(max_exp - 3.0) + 3.0);\n            TestByGenMode<InputT, OutputT>(num_items, max_segments);\n        }\n\n        //\n        // White-box testing of single-segment problems around specific sizes\n        //\n\n        // Tile-boundaries: multiple blocks, one tile per block\n        OffsetT tile_size = ActivePolicyT::ReducePolicy::BLOCK_THREADS * ActivePolicyT::ReducePolicy::ITEMS_PER_THREAD;\n        TestProblem<CUB, InputT, OutputT>(tile_size * 4,  1,      RANDOM, Sum());\n        TestProblem<CUB, InputT, OutputT>(tile_size * 4 + 1, 1,   RANDOM, Sum());\n        TestProblem<CUB, InputT, OutputT>(tile_size * 4 - 1, 1,   RANDOM, Sum());\n\n        // Tile-boundaries: multiple blocks, multiple tiles per block\n        OffsetT sm_occupancy = 32;\n        OffsetT occupancy = tile_size * sm_occupancy * g_sm_count;\n        TestProblem<CUB, InputT, OutputT>(occupancy,  1,      RANDOM, Sum());\n        TestProblem<CUB, InputT, OutputT>(occupancy + 1, 1,   RANDOM, Sum());\n        TestProblem<CUB, InputT, OutputT>(occupancy - 1, 1,   RANDOM, Sum());\n\n        return cudaSuccess;\n    }\n};\n\n\n/// Test problem type\ntemplate <\n    typename    InputT,\n    typename    OutputT,\n    typename    OffsetT>\nvoid TestType(\n    OffsetT     max_items,\n    OffsetT     max_segments)\n{\n    typedef typename DeviceReducePolicy<OutputT, OffsetT, cub::Sum>::MaxPolicy MaxPolicyT;\n\n    TestBySize<InputT, OutputT, OffsetT> dispatch(max_items, max_segments);\n\n    MaxPolicyT::Invoke(g_ptx_version, dispatch);\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    typedef int OffsetT;\n\n    OffsetT max_items       = 27000000;\n    OffsetT max_segments    = 34000;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_verbose_input = args.CheckCmdLineFlag(\"v2\");\n    args.GetCmdLineArgument(\"n\", max_items);\n    args.GetCmdLineArgument(\"s\", max_segments);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--s=<num segments> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    CubDebugExit(PtxVersion(g_ptx_version));\n\n    // Get SM count\n    g_sm_count = args.deviceProp.multiProcessorCount;\n\n    std::numeric_limits<float>::max();\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic test\n\n\n\n    TestProblem<CUB, int, int>(     max_items, 1, RANDOM, Sum());\n\n    TestProblem<CUB, char, int>(    max_items, 1, RANDOM, Sum());\n\n    TestProblem<CUB, int, int>(     max_items, 1, RANDOM, ArgMax());\n\n    TestProblem<CUB, float, float>( max_items, 1, RANDOM, Sum());\n\n    TestProblem<CUB_SEGMENTED, int, int>(max_items, max_segments, RANDOM, Sum());\n\n\n#elif defined(QUICK_TEST)\n\n    // Compile/run quick comparison tests\n\n    TestProblem<CUB, char, char>(         max_items * 4, 1, UNIFORM, Sum());\n    TestProblem<THRUST, char, char>(      max_items * 4, 1, UNIFORM, Sum());\n\n    printf(\"\\n----------------------------\\n\");\n    TestProblem<CUB, short, short>(        max_items * 2, 1, UNIFORM, Sum());\n    TestProblem<THRUST, short, short>(     max_items * 2, 1, UNIFORM, Sum());\n\n    printf(\"\\n----------------------------\\n\");\n    TestProblem<CUB, int, int>(          max_items,     1, UNIFORM, Sum());\n    TestProblem<THRUST, int, int>(       max_items,     1, UNIFORM, Sum());\n\n    printf(\"\\n----------------------------\\n\");\n    TestProblem<CUB, long long, long long>(    max_items / 2, 1, UNIFORM, Sum());\n    TestProblem<THRUST, long long, long long>( max_items / 2, 1, UNIFORM, Sum());\n\n    printf(\"\\n----------------------------\\n\");\n    TestProblem<CUB, TestFoo, TestFoo>(      max_items / 4, 1, UNIFORM, Max());\n    TestProblem<THRUST, TestFoo, TestFoo>(   max_items / 4, 1, UNIFORM, Max());\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test different input types\n        TestType<char, char>(max_items, max_segments);\n\n        TestType<unsigned char, unsigned char>(max_items, max_segments);\n\n        TestType<char, int>(max_items, max_segments);\n\n        TestType<short, short>(max_items, max_segments);\n        TestType<int, int>(max_items, max_segments);\n        TestType<long, long>(max_items, max_segments);\n        TestType<long long, long long>(max_items, max_segments);\n\n        TestType<uchar2, uchar2>(max_items, max_segments);\n        TestType<uint2, uint2>(max_items, max_segments);\n        TestType<ulonglong2, ulonglong2>(max_items, max_segments);\n        TestType<ulonglong4, ulonglong4>(max_items, max_segments);\n\n        TestType<TestFoo, TestFoo>(max_items, max_segments);\n        TestType<TestBar, TestBar>(max_items, max_segments);\n\n    }\n\n#endif\n\n\n    printf(\"\\n\");\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_reduce_by_key.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceReduce::ReduceByKey utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/reduce.h>\n#include <thrust/iterator/constant_iterator.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/device/device_reduce.cuh>\n#include <cub/device/device_run_length_encode.cuh>\n#include <cub/thread/thread_operators.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to reduce-by-key entrypoint\n */\ntemplate <\n    typename                    KeyInputIteratorT,\n    typename                    KeyOutputIteratorT,\n    typename                    ValueInputIteratorT,\n    typename                    ValueOutputIteratorT,\n    typename                    NumRunsIteratorT,\n    typename                    EqualityOpT,\n    typename                    ReductionOpT,\n    typename                    OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    KeyInputIteratorT           d_keys_in,\n    KeyOutputIteratorT          d_keys_out,\n    ValueInputIteratorT         d_values_in,\n    ValueOutputIteratorT        d_values_out,\n    NumRunsIteratorT            d_num_runs,\n    EqualityOpT                  equality_op,\n    ReductionOpT                 reduction_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceReduce::ReduceByKey(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_keys_in,\n            d_keys_out,\n            d_values_in,\n            d_values_out,\n            d_num_runs,\n            reduction_op,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to reduce-by-key entrypoint\n */\ntemplate <\n    typename                    KeyInputIteratorT,\n    typename                    KeyOutputIteratorT,\n    typename                    ValueInputIteratorT,\n    typename                    ValueOutputIteratorT,\n    typename                    NumRunsIteratorT,\n    typename                    EqualityOpT,\n    typename                    ReductionOpT,\n    typename                    OffsetT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    KeyInputIteratorT           d_keys_in,\n    KeyOutputIteratorT          d_keys_out,\n    ValueInputIteratorT         d_values_in,\n    ValueOutputIteratorT        d_values_out,\n    NumRunsIteratorT            d_num_runs,\n    EqualityOpT                 equality_op,\n    ReductionOpT                reduction_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The input keys type\n    typedef typename std::iterator_traits<KeyInputIteratorT>::value_type KeyInputT;\n\n    // The output keys type\n    typedef typename If<(Equals<typename std::iterator_traits<KeyOutputIteratorT>::value_type, void>::VALUE),   // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<KeyInputIteratorT>::value_type,                                           // ... then the input iterator's value type,\n        typename std::iterator_traits<KeyOutputIteratorT>::value_type>::Type KeyOutputT;                        // ... else the output iterator's value type\n\n    // The input values type\n    typedef typename std::iterator_traits<ValueInputIteratorT>::value_type ValueInputT;\n\n    // The output values type\n    typedef typename If<(Equals<typename std::iterator_traits<ValueOutputIteratorT>::value_type, void>::VALUE), // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<ValueInputIteratorT>::value_type,                                         // ... then the input iterator's value type,\n        typename std::iterator_traits<ValueOutputIteratorT>::value_type>::Type ValueOuputT;                     // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<KeyInputT> d_keys_in_wrapper(d_keys_in);\n        thrust::device_ptr<KeyOutputT> d_keys_out_wrapper(d_keys_out);\n\n        thrust::device_ptr<ValueInputT> d_values_in_wrapper(d_values_in);\n        thrust::device_ptr<ValueOuputT> d_values_out_wrapper(d_values_out);\n\n        thrust::pair<thrust::device_ptr<KeyOutputT>, thrust::device_ptr<ValueOuputT> > d_out_ends;\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_ends = thrust::reduce_by_key(\n                d_keys_in_wrapper,\n                d_keys_in_wrapper + num_items,\n                d_values_in_wrapper,\n                d_keys_out_wrapper,\n                d_values_out_wrapper);\n        }\n\n        OffsetT num_segments = OffsetT(d_out_ends.first - d_keys_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_runs, &num_segments, sizeof(OffsetT), cudaMemcpyHostToDevice));\n\n    }\n\n    return cudaSuccess;\n}\n\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceSelect\n */\ntemplate <\n    typename                    KeyInputIteratorT,\n    typename                    KeyOutputIteratorT,\n    typename                    ValueInputIteratorT,\n    typename                    ValueOutputIteratorT,\n    typename                    NumRunsIteratorT,\n    typename                    EqualityOpT,\n    typename                    ReductionOpT,\n    typename                    OffsetT>\n__global__ void CnpDispatchKernel(\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      temp_storage_bytes,\n    KeyInputIteratorT           d_keys_in,\n    KeyOutputIteratorT          d_keys_out,\n    ValueInputIteratorT         d_values_in,\n    ValueOutputIteratorT        d_values_out,\n    NumRunsIteratorT            d_num_runs,\n    EqualityOpT                 equality_op,\n    ReductionOpT                reduction_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(Int2Type<CUB>(), timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, d_num_runs, equality_op, reduction_op, num_items, 0, debug_synchronous);\n\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <\n    typename                    KeyInputIteratorT,\n    typename                    KeyOutputIteratorT,\n    typename                    ValueInputIteratorT,\n    typename                    ValueOutputIteratorT,\n    typename                    NumRunsIteratorT,\n    typename                    EqualityOpT,\n    typename                    ReductionOpT,\n    typename                    OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CDP>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    KeyInputIteratorT           d_keys_in,\n    KeyOutputIteratorT          d_keys_out,\n    ValueInputIteratorT         d_values_in,\n    ValueOutputIteratorT        d_values_out,\n    NumRunsIteratorT            d_num_runs,\n    EqualityOpT                 equality_op,\n    ReductionOpT                reduction_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, d_num_runs, equality_op, reduction_op, num_items, 0, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    int         entropy_reduction,\n    T           *h_in,\n    int         num_items,\n    int         max_segment)\n{\n    unsigned int max_int = (unsigned int) -1;\n\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Select number of repeating occurrences\n\n        int repeat;\n\n        if (max_segment < 0)\n        {\n            repeat = num_items;\n        }\n        else if (max_segment < 2)\n        {\n            repeat = 1;\n        }\n        else\n        {\n            RandomBits(repeat, entropy_reduction);\n            repeat = (int) ((double(repeat) * double(max_segment)) / double(max_int));\n            repeat = CUB_MAX(1, repeat);\n        }\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            InitValue(INTEGER_SEED, h_in[j], key);\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve problem.  Returns total number of segments identified\n */\ntemplate <\n    typename        KeyInputIteratorT,\n    typename        ValueInputIteratorT,\n    typename        KeyT,\n    typename        ValueT,\n    typename        EqualityOpT,\n    typename        ReductionOpT>\nint Solve(\n    KeyInputIteratorT       h_keys_in,\n    KeyT                    *h_keys_reference,\n    ValueInputIteratorT     h_values_in,\n    ValueT                  *h_values_reference,\n    EqualityOpT             equality_op,\n    ReductionOpT            reduction_op,\n    int                     num_items)\n{\n    // First item\n    KeyT previous        = h_keys_in[0];\n    ValueT aggregate     = h_values_in[0];\n    int num_segments    = 0;\n\n    // Subsequent items\n    for (int i = 1; i < num_items; ++i)\n    {\n        if (!equality_op(previous, h_keys_in[i]))\n        {\n            h_keys_reference[num_segments] = previous;\n            h_values_reference[num_segments] = aggregate;\n            num_segments++;\n            aggregate = h_values_in[i];\n        }\n        else\n        {\n            aggregate = reduction_op(aggregate, h_values_in[i]);\n        }\n        previous = h_keys_in[i];\n    }\n\n    h_keys_reference[num_segments] = previous;\n    h_values_reference[num_segments] = aggregate;\n    num_segments++;\n\n    return num_segments;\n}\n\n\n\n/**\n * Test DeviceSelect for a given problem input\n */\ntemplate <\n    Backend             BACKEND,\n    typename            DeviceKeyInputIteratorT,\n    typename            DeviceValueInputIteratorT,\n    typename            KeyT,\n    typename            ValueT,\n    typename            EqualityOpT,\n    typename            ReductionOpT>\nvoid Test(\n    DeviceKeyInputIteratorT     d_keys_in,\n    DeviceValueInputIteratorT   d_values_in,\n    KeyT*                       h_keys_reference,\n    ValueT*                     h_values_reference,\n    EqualityOpT                 equality_op,\n    ReductionOpT                reduction_op,\n    int                         num_segments,\n    int                         num_items)\n{\n    // Allocate device output arrays and number of segments\n    KeyT*   d_keys_out             = NULL;\n    ValueT* d_values_out           = NULL;\n    int*    d_num_runs         = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys_out, sizeof(KeyT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values_out, sizeof(ValueT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_runs, sizeof(int)));\n\n    // Allocate CDP device arrays\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, d_num_runs, equality_op, reduction_op, num_items, 0, true));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output arrays\n    CubDebugExit(cudaMemset(d_keys_out, 0, sizeof(KeyT) * num_items));\n    CubDebugExit(cudaMemset(d_values_out, 0, sizeof(ValueT) * num_items));\n    CubDebugExit(cudaMemset(d_num_runs, 0, sizeof(int)));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, d_num_runs, equality_op, reduction_op, num_items, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare1 = CompareDeviceResults(h_keys_reference, d_keys_out, num_segments, true, g_verbose);\n    printf(\"\\t Keys %s \", compare1 ? \"FAIL\" : \"PASS\");\n\n    int compare2 = CompareDeviceResults(h_values_reference, d_values_out, num_segments, true, g_verbose);\n    printf(\"\\t Values %s \", compare2 ? \"FAIL\" : \"PASS\");\n\n    int compare3 = CompareDeviceResults(&num_segments, d_num_runs, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare3 ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_keys_in, d_keys_out, d_values_in, d_values_out, d_num_runs, equality_op, reduction_op, num_items, 0, false));\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float   avg_millis  = elapsed_millis / g_timing_iterations;\n        float   giga_rate   = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        int     bytes_moved = ((num_items + num_segments) * sizeof(KeyT)) + ((num_items + num_segments) * sizeof(ValueT));\n        float   giga_bandwidth  = float(bytes_moved) / avg_millis / 1000.0f / 1000.0f;\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s\", avg_millis, giga_rate, giga_bandwidth);\n    }\n    printf(\"\\n\\n\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Cleanup\n    if (d_keys_out) CubDebugExit(g_allocator.DeviceFree(d_keys_out));\n    if (d_values_out) CubDebugExit(g_allocator.DeviceFree(d_values_out));\n    if (d_num_runs) CubDebugExit(g_allocator.DeviceFree(d_num_runs));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare1 | compare2 | compare3);\n}\n\n\n/**\n * Test DeviceSelect on pointer type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid TestPointer(\n    int             num_items,\n    int             entropy_reduction,\n    int             max_segment,\n    ReductionOpT    reduction_op)\n{\n    // Allocate host arrays\n    KeyT* h_keys_in        = new KeyT[num_items];\n    KeyT* h_keys_reference = new KeyT[num_items];\n\n    ValueT* h_values_in        = new ValueT[num_items];\n    ValueT* h_values_reference = new ValueT[num_items];\n\n    for (int i = 0; i < num_items; ++i)\n        InitValue(INTEGER_SEED, h_values_in[i], 1);\n\n    // Initialize problem and solution\n    Equality equality_op;\n    Initialize(entropy_reduction, h_keys_in, num_items, max_segment);\n    int num_segments = Solve(h_keys_in, h_keys_reference, h_values_in, h_values_reference, equality_op, reduction_op, num_items);\n\n    printf(\"\\nPointer %s cub::DeviceReduce::ReduceByKey %s reduction of %d items, %d segments (avg run length %.3f), {%s,%s} key value pairs, max_segment %d, entropy_reduction %d\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        (Equals<ReductionOpT, Sum>::VALUE) ? \"Sum\" : \"Max\",\n        num_items, num_segments, float(num_items) / num_segments,\n        typeid(KeyT).name(), typeid(ValueT).name(),\n        max_segment, entropy_reduction);\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    KeyT     *d_keys_in = NULL;\n    ValueT   *d_values_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys_in, sizeof(KeyT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_values_in, sizeof(ValueT) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_keys_in, h_keys_in, sizeof(KeyT) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_values_in, h_values_in, sizeof(ValueT) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<BACKEND>(d_keys_in, d_values_in, h_keys_reference, h_values_reference, equality_op, reduction_op, num_segments, num_items);\n\n    // Cleanup\n    if (h_keys_in) delete[] h_keys_in;\n    if (h_values_in) delete[] h_values_in;\n    if (h_keys_reference) delete[] h_keys_reference;\n    if (h_values_reference) delete[] h_values_reference;\n    if (d_keys_in) CubDebugExit(g_allocator.DeviceFree(d_keys_in));\n    if (d_values_in) CubDebugExit(g_allocator.DeviceFree(d_values_in));\n}\n\n\n/**\n * Test on iterator type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid TestIterator(\n    int             num_items,\n    int             entropy_reduction,\n    int             max_segment,\n    ReductionOpT    reduction_op)\n{\n    // Allocate host arrays\n    KeyT* h_keys_in        = new KeyT[num_items];\n    KeyT* h_keys_reference = new KeyT[num_items];\n\n    ValueT one_val;\n    InitValue(INTEGER_SEED, one_val, 1);\n    ConstantInputIterator<ValueT, int> h_values_in(one_val);\n    ValueT* h_values_reference = new ValueT[num_items];\n\n    // Initialize problem and solution\n    Equality equality_op;\n    Initialize(entropy_reduction, h_keys_in, num_items, max_segment);\n    int num_segments = Solve(h_keys_in, h_keys_reference, h_values_in, h_values_reference, equality_op, reduction_op, num_items);\n\n    printf(\"\\nIterator %s cub::DeviceReduce::ReduceByKey %s reduction of %d items, %d segments (avg run length %.3f), {%s,%s} key value pairs, max_segment %d, entropy_reduction %d\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        (Equals<ReductionOpT, Sum>::VALUE) ? \"Sum\" : \"Max\",\n        num_items, num_segments, float(num_items) / num_segments,\n        typeid(KeyT).name(), typeid(ValueT).name(),\n        max_segment, entropy_reduction);\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    KeyT     *d_keys_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys_in, sizeof(KeyT) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_keys_in, h_keys_in, sizeof(KeyT) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<BACKEND>(d_keys_in, h_values_in, h_keys_reference, h_values_reference, equality_op, reduction_op, num_segments, num_items);\n\n    // Cleanup\n    if (h_keys_in) delete[] h_keys_in;\n    if (h_keys_reference) delete[] h_keys_reference;\n    if (h_values_reference) delete[] h_values_reference;\n    if (d_keys_in) CubDebugExit(g_allocator.DeviceFree(d_keys_in));\n}\n\n\n/**\n * Test different gen modes\n */\ntemplate <\n    Backend         BACKEND,\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid Test(\n    int             num_items,\n    ReductionOpT    reduction_op,\n    int             max_segment)\n{\n    // 0 key-bit entropy reduction rounds\n    TestPointer<BACKEND, KeyT, ValueT>(num_items, 0, max_segment, reduction_op);\n\n    if (max_segment > 1)\n    {\n        // 2 key-bit entropy reduction rounds\n        TestPointer<BACKEND, KeyT, ValueT>(num_items, 2, max_segment, reduction_op);\n\n        // 7 key-bit entropy reduction rounds\n        TestPointer<BACKEND, KeyT, ValueT>(num_items, 7, max_segment, reduction_op);\n    }\n}\n\n\n/**\n * Test different avg segment lengths modes\n */\ntemplate <\n    Backend         BACKEND,\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid Test(\n    int             num_items,\n    ReductionOpT    reduction_op)\n{\n    Test<BACKEND, KeyT, ValueT>(num_items, reduction_op, -1);\n    Test<BACKEND, KeyT, ValueT>(num_items, reduction_op, 1);\n\n    // Evaluate different max-segment lengths\n    for (int max_segment = 3; max_segment < CUB_MIN(num_items, (unsigned short) -1); max_segment *= 11)\n    {\n        Test<BACKEND, KeyT, ValueT>(num_items, reduction_op, max_segment);\n    }\n}\n\n\n\n/**\n * Test different dispatch\n */\ntemplate <\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid TestDispatch(\n    int             num_items,\n    ReductionOpT    reduction_op)\n{\n    Test<CUB, KeyT, ValueT>(num_items, reduction_op);\n#ifdef CUB_CDP\n    Test<CDP, KeyT, ValueT>(num_items, reduction_op);\n#endif\n}\n\n\n/**\n * Test different input sizes\n */\ntemplate <\n    typename        KeyT,\n    typename        ValueT,\n    typename        ReductionOpT>\nvoid TestSize(\n    int             num_items,\n    ReductionOpT    reduction_op)\n{\n    if (num_items < 0)\n    {\n        TestDispatch<KeyT, ValueT>(1,        reduction_op);\n        TestDispatch<KeyT, ValueT>(100,      reduction_op);\n        TestDispatch<KeyT, ValueT>(10000,    reduction_op);\n        TestDispatch<KeyT, ValueT>(1000000,  reduction_op);\n    }\n    else\n    {\n        TestDispatch<KeyT, ValueT>(num_items, reduction_op);\n    }\n\n}\n\n\ntemplate <\n    typename        KeyT,\n    typename        ValueT>\nvoid TestOp(\n    int             num_items)\n{\n    TestSize<KeyT, ValueT>(num_items, cub::Sum());\n    TestSize<KeyT, ValueT>(num_items, cub::Max());\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = -1;\n    int entropy_reduction   = 0;\n    int maxseg              = 1000;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"maxseg\", maxseg);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--entropy=<segment length bit entropy reduction rounds>]\"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    printf(\"\\n\");\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic CUB test\n    if (num_items < 0) num_items = 32000000;\n\n    TestPointer<CUB, int, double>(num_items, entropy_reduction, maxseg, cub::Sum());\n    TestPointer<CUB, int, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n    TestIterator<CUB, int, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n\n#elif defined(QUICK_TEST)\n\n    // Compile/run quick tests\n    if (num_items < 0) num_items = 32000000;\n\n    printf(\"---- RLE int ---- \\n\");\n    TestIterator<CUB, int, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n\n    printf(\"---- RLE long long ---- \\n\");\n    TestIterator<CUB, long long, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n\n    printf(\"---- int ---- \\n\");\n    TestPointer<CUB, int, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n    TestPointer<THRUST, int, int>(num_items, entropy_reduction, maxseg, cub::Sum());\n\n    printf(\"---- float ---- \\n\");\n    TestPointer<CUB, int, float>(num_items, entropy_reduction, maxseg, cub::Sum());\n    TestPointer<THRUST, int, float>(num_items, entropy_reduction, maxseg, cub::Sum());\n\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n    {\n        printf(\"---- double ---- \\n\");\n        TestPointer<CUB, int, double>(num_items, entropy_reduction, maxseg, cub::Sum());\n        TestPointer<THRUST, int, double>(num_items, entropy_reduction, maxseg, cub::Sum());\n    }\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n\n        // Test different input types\n        TestOp<int, char>(num_items);\n        TestOp<int, short>(num_items);\n        TestOp<int, int>(num_items);\n        TestOp<int, long>(num_items);\n        TestOp<int, long long>(num_items);\n        TestOp<int, float>(num_items);\n        if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n            TestOp<int, double>(num_items);\n\n        TestOp<int, uchar2>(num_items);\n        TestOp<int, uint2>(num_items);\n        TestOp<int, uint3>(num_items);\n        TestOp<int, uint4>(num_items);\n        TestOp<int, ulonglong4>(num_items);\n        TestOp<int, TestFoo>(num_items);\n        TestOp<int, TestBar>(num_items);\n\n        TestOp<char, int>(num_items);\n        TestOp<long long, int>(num_items);\n        TestOp<TestFoo, int>(num_items);\n        TestOp<TestBar, int>(num_items);\n\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_run_length_encode.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceReduce::RunLengthEncode utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/reduce.h>\n#include <thrust/iterator/constant_iterator.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/device/device_reduce.cuh>\n#include <cub/device/device_run_length_encode.cuh>\n#include <cub/thread/thread_operators.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n// Operation types\nenum RleMethod\n{\n    RLE,                // Run length encode\n    NON_TRIVIAL,\n    CSR,\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB entrypoints\n//---------------------------------------------------------------------\n\n\n/**\n * Dispatch to run-length encode entrypoint\n */\ntemplate <\n    typename                    InputIteratorT,\n    typename                    UniqueOutputIteratorT,\n    typename                    OffsetsOutputIteratorT,\n    typename                    LengthsOutputIteratorT,\n    typename                    NumRunsIterator,\n    typename                    OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<RLE>               method,\n    Int2Type<CUB>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    UniqueOutputIteratorT       d_unique_out,\n    OffsetsOutputIteratorT      d_offsets_out,\n    LengthsOutputIteratorT      d_lengths_out,\n    NumRunsIterator             d_num_runs,\n    cub::Equality               equality_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceRunLengthEncode::Encode(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_unique_out,\n            d_lengths_out,\n            d_num_runs,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to non-trivial runs entrypoint\n */\ntemplate <\n    typename                    InputIteratorT,\n    typename                    UniqueOutputIteratorT,\n    typename                    OffsetsOutputIteratorT,\n    typename                    LengthsOutputIteratorT,\n    typename                    NumRunsIterator,\n    typename                    OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<NON_TRIVIAL>       method,\n    Int2Type<CUB>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    UniqueOutputIteratorT       d_unique_out,\n    OffsetsOutputIteratorT      d_offsets_out,\n    LengthsOutputIteratorT      d_lengths_out,\n    NumRunsIterator             d_num_runs,\n    cub::Equality               equality_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceRunLengthEncode::NonTrivialRuns(\n            d_temp_storage,\n            temp_storage_bytes,\n            d_in,\n            d_offsets_out,\n            d_lengths_out,\n            d_num_runs,\n            num_items,\n            stream,\n            debug_synchronous);\n    }\n    return error;\n}\n\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to run-length encode entrypoint\n */\ntemplate <\n    typename                    InputIteratorT,\n    typename                    UniqueOutputIteratorT,\n    typename                    OffsetsOutputIteratorT,\n    typename                    LengthsOutputIteratorT,\n    typename                    NumRunsIterator,\n    typename                    OffsetT>\ncudaError_t Dispatch(\n    Int2Type<RLE>               method,\n    Int2Type<THRUST>            dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    UniqueOutputIteratorT       d_unique_out,\n    OffsetsOutputIteratorT      d_offsets_out,\n    LengthsOutputIteratorT      d_lengths_out,\n    NumRunsIterator             d_num_runs,\n    cub::Equality               equality_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<UniqueOutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                                // ... then the input iterator's value type,\n        typename std::iterator_traits<UniqueOutputIteratorT>::value_type>::Type UniqueT;                          // ... else the output iterator's value type\n\n    // The lengths output value type\n    typedef typename If<(Equals<typename std::iterator_traits<LengthsOutputIteratorT>::value_type, void>::VALUE),   // LengthT =  (if output iterator's value type is void) ?\n        OffsetT,                                                                                                    // ... then the OffsetT type,\n        typename std::iterator_traits<LengthsOutputIteratorT>::value_type>::Type LengthT;                           // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<InputT>      d_in_wrapper(d_in);\n        thrust::device_ptr<UniqueT>     d_unique_out_wrapper(d_unique_out);\n        thrust::device_ptr<LengthT>     d_lengths_out_wrapper(d_lengths_out);\n\n        thrust::pair<thrust::device_ptr<UniqueT>, thrust::device_ptr<LengthT> > d_out_ends;\n\n        LengthT one_val;\n        InitValue(INTEGER_SEED, one_val, 1);\n        thrust::constant_iterator<LengthT> constant_one(one_val);\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_ends = thrust::reduce_by_key(\n                d_in_wrapper,\n                d_in_wrapper + num_items,\n                constant_one,\n                d_unique_out_wrapper,\n                d_lengths_out_wrapper);\n        }\n\n        OffsetT num_runs = OffsetT(d_out_ends.first - d_unique_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_runs, &num_runs, sizeof(OffsetT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceRunLengthEncode\n */\ntemplate <\n    int                         RLE_METHOD,\n    typename                    InputIteratorT,\n    typename                    UniqueOutputIteratorT,\n    typename                    OffsetsOutputIteratorT,\n    typename                    LengthsOutputIteratorT,\n    typename                    NumRunsIterator,\n    typename                    EqualityOp,\n    typename                    OffsetT>\n__global__ void CnpDispatchKernel(\n    Int2Type<RLE_METHOD>            method,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      temp_storage_bytes,\n    InputIteratorT              d_in,\n    UniqueOutputIteratorT       d_unique_out,\n    OffsetsOutputIteratorT      d_offsets_out,\n    LengthsOutputIteratorT      d_lengths_out,\n    NumRunsIterator             d_num_runs,\n    cub::Equality               equality_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(method, Int2Type<CUB>(), timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_offsets_out, d_lengths_out, d_num_runs, equality_op, num_items, 0, debug_synchronous);\n\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <\n    int                         RLE_METHOD,\n    typename                    InputIteratorT,\n    typename                    UniqueOutputIteratorT,\n    typename                    OffsetsOutputIteratorT,\n    typename                    LengthsOutputIteratorT,\n    typename                    NumRunsIterator,\n    typename                    EqualityOp,\n    typename                    OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<RLE_METHOD>        method,\n    Int2Type<CDP>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    UniqueOutputIteratorT       d_unique_out,\n    OffsetsOutputIteratorT      d_offsets_out,\n    LengthsOutputIteratorT      d_lengths_out,\n    NumRunsIterator             d_num_runs,\n    EqualityOp                  equality_op,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(method, timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_offsets_out, d_lengths_out, d_num_runs, equality_op, num_items, 0, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    int         entropy_reduction,\n    T           *h_in,\n    int         num_items,\n    int         max_segment)\n{\n    unsigned int max_int = (unsigned int) -1;\n\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Select number of repeating occurrences for the current run\n        int repeat;\n        if (max_segment < 0)\n        {\n            repeat = num_items;\n        }\n        else if (max_segment < 2)\n        {\n            repeat = 1;\n        }\n        else\n        {\n            RandomBits(repeat, entropy_reduction);\n            repeat = (int) ((double(repeat) * double(max_segment)) / double(max_int));\n            repeat = CUB_MAX(1, repeat);\n        }\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            InitValue(INTEGER_SEED, h_in[j], key);\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve problem.  Returns total number of segments identified\n */\ntemplate <\n    RleMethod       RLE_METHOD,\n    typename        InputIteratorT,\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT,\n    typename        EqualityOp>\nint Solve(\n    InputIteratorT  h_in,\n    T               *h_unique_reference,\n    OffsetT         *h_offsets_reference,\n    LengthT         *h_lengths_reference,\n    EqualityOp      equality_op,\n    int             num_items)\n{\n    if (num_items == 0) \n        return 0;\n\n    // First item\n    T       previous        = h_in[0];\n    LengthT  length          = 1;\n    int     num_runs        = 0;\n    int     run_begin       = 0;\n\n    // Subsequent items\n    for (int i = 1; i < num_items; ++i)\n    {\n        if (!equality_op(previous, h_in[i]))\n        {\n            if ((RLE_METHOD != NON_TRIVIAL) || (length > 1))\n            {\n                h_unique_reference[num_runs]      = previous;\n                h_offsets_reference[num_runs]     = run_begin;\n                h_lengths_reference[num_runs]     = length;\n                num_runs++;\n            }\n            length = 1;\n            run_begin = i;\n        }\n        else\n        {\n            length++;\n        }\n        previous = h_in[i];\n    }\n\n    if ((RLE_METHOD != NON_TRIVIAL) || (length > 1))\n    {\n        h_unique_reference[num_runs]    = previous;\n        h_offsets_reference[num_runs]   = run_begin;\n        h_lengths_reference[num_runs]   = length;\n        num_runs++;\n    }\n\n    return num_runs;\n}\n\n\n\n/**\n * Test DeviceRunLengthEncode for a given problem input\n */\ntemplate <\n    RleMethod           RLE_METHOD,\n    Backend             BACKEND,\n    typename            DeviceInputIteratorT,\n    typename            T,\n    typename            OffsetT,\n    typename            LengthT,\n    typename            EqualityOp>\nvoid Test(\n    DeviceInputIteratorT d_in,\n    T                   *h_unique_reference,\n    OffsetT             *h_offsets_reference,\n    LengthT             *h_lengths_reference,\n    EqualityOp          equality_op,\n    int                 num_runs,\n    int                 num_items)\n{\n    // Allocate device output arrays and number of segments\n    T*          d_unique_out       = NULL;\n    LengthT*    d_offsets_out      = NULL;\n    OffsetT*    d_lengths_out      = NULL;\n    int*        d_num_runs         = NULL;\n\n    if (RLE_METHOD == RLE)\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_unique_out, sizeof(T) * num_items));\n    if (RLE_METHOD == NON_TRIVIAL)\n        CubDebugExit(g_allocator.DeviceAllocate((void**)&d_offsets_out, sizeof(OffsetT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_lengths_out, sizeof(LengthT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_runs, sizeof(int)));\n\n    // Allocate CDP device arrays\n    size_t*          d_temp_storage_bytes = NULL;\n    cudaError_t*     d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void*           d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(Int2Type<RLE_METHOD>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_offsets_out, d_lengths_out, d_num_runs, equality_op, num_items, 0, true));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output arrays\n    if (RLE_METHOD == RLE)\n        CubDebugExit(cudaMemset(d_unique_out,   0, sizeof(T) * num_items));\n    if (RLE_METHOD == NON_TRIVIAL)\n        CubDebugExit(cudaMemset(d_offsets_out,  0, sizeof(OffsetT) * num_items));\n    CubDebugExit(cudaMemset(d_lengths_out,  0, sizeof(LengthT) * num_items));\n    CubDebugExit(cudaMemset(d_num_runs,     0, sizeof(int)));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(Int2Type<RLE_METHOD>(), Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_offsets_out, d_lengths_out, d_num_runs, equality_op, num_items, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare0 = 0;\n    int compare1 = 0;\n    int compare2 = 0;\n    int compare3 = 0;\n\n    if (RLE_METHOD == RLE)\n    {\n        compare0 = CompareDeviceResults(h_unique_reference, d_unique_out, num_runs, true, g_verbose);\n        printf(\"\\t Keys %s\\n\", compare0 ? \"FAIL\" : \"PASS\");\n    }\n\n    if (RLE_METHOD != RLE)\n    {\n        compare1 = CompareDeviceResults(h_offsets_reference, d_offsets_out, num_runs, true, g_verbose);\n        printf(\"\\t Offsets %s\\n\", compare1 ? \"FAIL\" : \"PASS\");\n    }\n\n    if (RLE_METHOD != CSR)\n    {\n        compare2 = CompareDeviceResults(h_lengths_reference, d_lengths_out, num_runs, true, g_verbose);\n        printf(\"\\t Lengths %s\\n\", compare2 ? \"FAIL\" : \"PASS\");\n    }\n\n    compare3 = CompareDeviceResults(&num_runs, d_num_runs, 1, true, g_verbose);\n    printf(\"\\t Count %s\\n\", compare3 ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    CubDebugExit(Dispatch(Int2Type<RLE_METHOD>(), Int2Type<BACKEND>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_unique_out, d_offsets_out, d_lengths_out, d_num_runs, equality_op, num_items, 0, false));\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        int bytes_moved = (num_items * sizeof(T)) + (num_runs * (sizeof(OffsetT) + sizeof(LengthT)));\n        float giga_bandwidth = float(bytes_moved) / avg_millis / 1000.0f / 1000.0f;\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s\", avg_millis, giga_rate, giga_bandwidth);\n    }\n    printf(\"\\n\\n\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Cleanup\n    if (d_unique_out) CubDebugExit(g_allocator.DeviceFree(d_unique_out));\n    if (d_offsets_out) CubDebugExit(g_allocator.DeviceFree(d_offsets_out));\n    if (d_lengths_out) CubDebugExit(g_allocator.DeviceFree(d_lengths_out));\n    if (d_num_runs) CubDebugExit(g_allocator.DeviceFree(d_num_runs));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare0 | compare1 | compare2 | compare3);\n}\n\n\n/**\n * Test DeviceRunLengthEncode on pointer type\n */\ntemplate <\n    RleMethod       RLE_METHOD,\n    Backend         BACKEND,\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid TestPointer(\n    int             num_items,\n    int             entropy_reduction,\n    int             max_segment)\n{\n    // Allocate host arrays\n    T*      h_in                    = new T[num_items];\n    T*      h_unique_reference      = new T[num_items];\n    OffsetT* h_offsets_reference     = new OffsetT[num_items];\n    LengthT* h_lengths_reference     = new LengthT[num_items];\n\n    for (int i = 0; i < num_items; ++i)\n        InitValue(INTEGER_SEED, h_offsets_reference[i], 1);\n\n    // Initialize problem and solution\n    Equality equality_op;\n    Initialize(entropy_reduction, h_in, num_items, max_segment);\n\n    int num_runs = Solve<RLE_METHOD>(h_in, h_unique_reference, h_offsets_reference, h_lengths_reference, equality_op, num_items);\n\n    printf(\"\\nPointer %s cub::%s on %d items, %d segments (avg run length %.3f), {%s key, %s offset, %s length}, max_segment %d, entropy_reduction %d\\n\",\n        (RLE_METHOD == RLE) ? \"DeviceReduce::RunLengthEncode\" : (RLE_METHOD == NON_TRIVIAL) ? \"DeviceRunLengthEncode::NonTrivialRuns\" : \"Other\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_runs, float(num_items) / num_runs,\n        typeid(T).name(), typeid(OffsetT).name(), typeid(LengthT).name(),\n        max_segment, entropy_reduction);\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    T* d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<RLE_METHOD, BACKEND>(d_in, h_unique_reference, h_offsets_reference, h_lengths_reference, equality_op, num_runs, num_items);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_unique_reference) delete[] h_unique_reference;\n    if (h_offsets_reference) delete[] h_offsets_reference;\n    if (h_lengths_reference) delete[] h_lengths_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n}\n\n\n/**\n * Test on iterator type\n */\ntemplate <\n    RleMethod       RLE_METHOD,\n    Backend         BACKEND,\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid TestIterator(\n    int             num_items,\n    Int2Type<true>  is_primitive)\n{\n    // Allocate host arrays\n    T* h_unique_reference       = new T[num_items];\n    OffsetT* h_offsets_reference = new OffsetT[num_items];\n    LengthT* h_lengths_reference = new LengthT[num_items];\n\n    T one_val;\n    InitValue(INTEGER_SEED, one_val, 1);\n    ConstantInputIterator<T, int> h_in(one_val);\n\n    // Initialize problem and solution\n    Equality equality_op;\n    int num_runs = Solve<RLE_METHOD>(h_in, h_unique_reference, h_offsets_reference, h_lengths_reference, equality_op, num_items);\n\n    printf(\"\\nIterator %s cub::%s on %d items, %d segments (avg run length %.3f), {%s key, %s offset, %s length}\\n\",\n        (RLE_METHOD == RLE) ? \"DeviceReduce::RunLengthEncode\" : (RLE_METHOD == NON_TRIVIAL) ? \"DeviceRunLengthEncode::NonTrivialRuns\" : \"Other\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_runs, float(num_items) / num_runs,\n        typeid(T).name(), typeid(OffsetT).name(), typeid(LengthT).name());\n    fflush(stdout);\n\n    // Run Test\n    Test<RLE_METHOD, BACKEND>(h_in, h_unique_reference, h_offsets_reference, h_lengths_reference, equality_op, num_runs, num_items);\n\n    // Cleanup\n    if (h_unique_reference) delete[] h_unique_reference;\n    if (h_offsets_reference) delete[] h_offsets_reference;\n    if (h_lengths_reference) delete[] h_lengths_reference;\n}\n\n\ntemplate <\n    RleMethod       RLE_METHOD,\n    Backend         BACKEND,\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid TestIterator(\n    int             num_items,\n    Int2Type<false> is_primitive)\n{}\n\n\n/**\n * Test different gen modes\n */\ntemplate <\n    RleMethod       RLE_METHOD,\n    Backend         BACKEND,\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid Test(\n    int             num_items)\n{\n    // Test iterator (one run)\n    TestIterator<RLE_METHOD, BACKEND, T, OffsetT, LengthT>(num_items, Int2Type<Traits<T>::PRIMITIVE>());\n\n    // num_items runs\n    TestPointer<RLE_METHOD, BACKEND, T, OffsetT, LengthT>(num_items, 0, 1);\n\n    // Evaluate different run lengths\n    for (int max_segment = 3; max_segment < CUB_MIN(num_items, (unsigned short) -1); max_segment *= 3)\n    {\n        // Uniform selection run length\n        TestPointer<RLE_METHOD, BACKEND, T, OffsetT, LengthT>(num_items, 0, max_segment);\n\n        // Reduced-entropy run length\n        TestPointer<RLE_METHOD, BACKEND, T, OffsetT, LengthT>(num_items, 4, max_segment);\n    }\n}\n\n\n/**\n * Test different dispatch\n */\ntemplate <\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid TestDispatch(\n    int             num_items)\n{\n    Test<RLE,           CUB, T, OffsetT, LengthT>(num_items);\n    Test<NON_TRIVIAL,   CUB, T, OffsetT, LengthT>(num_items);\n\n#ifdef CUB_CDP\n    Test<RLE,           CDP, T, OffsetT, LengthT>(num_items);\n    Test<NON_TRIVIAL,   CDP, T, OffsetT, LengthT>(num_items);\n#endif\n}\n\n\n/**\n * Test different input sizes\n */\ntemplate <\n    typename        T,\n    typename        OffsetT,\n    typename        LengthT>\nvoid TestSize(\n    int             num_items)\n{\n    if (num_items < 0)\n    {\n        TestDispatch<T, OffsetT, LengthT>(0);\n        TestDispatch<T, OffsetT, LengthT>(1);\n        TestDispatch<T, OffsetT, LengthT>(100);\n        TestDispatch<T, OffsetT, LengthT>(10000);\n        TestDispatch<T, OffsetT, LengthT>(1000000);\n\n        // Randomly select problem size between 1:10,000,000\n        unsigned int max_int = (unsigned int) -1;\n        for (int i = 0; i < 10; ++i)\n        {\n            unsigned int num_items;\n            RandomBits(num_items);\n            num_items = (unsigned int) ((double(num_items) * double(10000000)) / double(max_int));\n            num_items = CUB_MAX(1, num_items);\n            TestDispatch<T, OffsetT, LengthT>(num_items);\n        }\n    }\n    else\n    {\n        TestDispatch<T, OffsetT, LengthT>(num_items);\n    }\n\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = -1;\n    int entropy_reduction   = 0;\n    int max_segment              = 1000;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"maxseg\", max_segment);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--entropy=<segment length bit entropy reduction rounds>]\"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    printf(\"\\n\");\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic CUB test\n    if (num_items < 0) num_items = 32000000;\n\n    TestPointer<RLE,            CUB, int, int, int>(    num_items, entropy_reduction, max_segment);\n    TestPointer<NON_TRIVIAL,    CUB, int, int, int>(    num_items, entropy_reduction, max_segment);\n    TestIterator<RLE,           CUB, float, int, int>(  num_items, Int2Type<Traits<float>::PRIMITIVE>());\n\n\n#elif defined(QUICK_TEST)\n\n    // Compile/run quick tests\n    if (num_items < 0) num_items = 32000000;\n\n    TestPointer<RLE,            CUB, int, int, int>(    num_items, entropy_reduction, max_segment);\n    TestPointer<RLE,            THRUST, int, int, int>(    num_items, entropy_reduction, max_segment);\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test different input types\n        TestSize<char,          int, int>(num_items);\n        TestSize<short,         int, int>(num_items);\n        TestSize<int,           int, int>(num_items);\n        TestSize<long,          int, int>(num_items);\n        TestSize<long long,     int, int>(num_items);\n        TestSize<float,         int, int>(num_items);\n        TestSize<double,        int, int>(num_items);\n\n        TestSize<uchar2,        int, int>(num_items);\n        TestSize<uint2,         int, int>(num_items);\n        TestSize<uint3,         int, int>(num_items);\n        TestSize<uint4,         int, int>(num_items);\n        TestSize<ulonglong4,    int, int>(num_items);\n        TestSize<TestFoo,       int, int>(num_items);\n        TestSize<TestBar,       int, int>(num_items);\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_scan.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceScan utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/scan.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/iterator/discard_output_iterator.cuh>\n#include <cub/device/device_scan.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose           = false;\nint                     g_timing_iterations = 0;\nint                     g_repeat            = 0;\ndouble                  g_device_giga_bandwidth;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\n/**\n * \\brief WrapperFunctor (for precluding test-specialized dispatch to *Sum variants)\n */\ntemplate<typename OpT>\nstruct WrapperFunctor\n{\n    OpT op;\n\n    WrapperFunctor(OpT op) : op(op) {}\n\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return op(a, b);\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB DeviceScan entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to exclusive scan entrypoint\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename InitialValueT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceScan::ExclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, scan_op, initial_value, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to exclusive sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename InitialValueT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    Int2Type<true>      is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    Sum                 scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to inclusive scan entrypoint\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    NullType            initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceScan::InclusiveScan(d_temp_storage, temp_storage_bytes, d_in, d_out, scan_op, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to inclusive sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>       dispatch_to,\n    Int2Type<true>      is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    Sum                 scan_op,\n    NullType            initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceScan::InclusiveSum(d_temp_storage, temp_storage_bytes, d_in, d_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to exclusive scan entrypoint\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename InitialValueT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<InputT> d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            thrust::exclusive_scan(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper, initial_value, scan_op);\n        }\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to exclusive sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename InitialValueT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    Int2Type<true>      is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    Sum                 scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<InputT> d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            thrust::exclusive_scan(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper);\n        }\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to inclusive scan entrypoint\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    NullType            initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<InputT> d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            thrust::inclusive_scan(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper, scan_op);\n        }\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to inclusive sum entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<THRUST>    dispatch_to,\n    Int2Type<true>      is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    Sum                 scan_op,\n    NullType            initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<InputT> d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            thrust::inclusive_scan(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper);\n        }\n    }\n\n    return cudaSuccess;\n}\n\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceScan\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename InitialValueT, typename OffsetT>\n__global__ void CnpDispatchKernel(\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t              temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    bool                debug_synchronous)\n{\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(\n        Int2Type<CUB>(),\n        is_primitive,\n        timing_timing_iterations,\n        d_temp_storage_bytes,\n        d_cdp_error,\n        d_temp_storage,\n        temp_storage_bytes,\n        d_in,\n        d_out,\n        scan_op,\n        initial_value,\n        num_items,\n        0,\n        debug_synchronous);\n\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <typename IsPrimitiveT, typename InputIteratorT, typename OutputIteratorT, typename ScanOpT, typename InitialValueT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<CDP>       dispatch_to,\n    IsPrimitiveT        is_primitive,\n    int                 timing_timing_iterations,\n    size_t              *d_temp_storage_bytes,\n    cudaError_t         *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t&             temp_storage_bytes,\n    InputIteratorT      d_in,\n    OutputIteratorT     d_out,\n    ScanOpT             scan_op,\n    InitialValueT       initial_value,\n    OffsetT             num_items,\n    cudaStream_t        stream,\n    bool                debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(\n        is_primitive,\n        timing_timing_iterations,\n        d_temp_storage_bytes,\n        d_cdp_error,\n        d_temp_storage,\n        temp_storage_bytes,\n        d_in,\n        d_out,\n        scan_op,\n        initial_value,\n        num_items,\n        debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    GenMode      gen_mode,\n    T            *h_in,\n    int          num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n/**\n * Solve exclusive-scan problem\n */\ntemplate <\n    typename        InputIteratorT,\n    typename        OutputT,\n    typename        ScanOpT>\nvoid Solve(\n    InputIteratorT  h_in,\n    OutputT         *h_reference,\n    int             num_items,\n    ScanOpT         scan_op,\n    OutputT         initial_value)\n{\n    if (num_items > 0)\n    {\n        OutputT val         = h_in[0];\n        h_reference[0]      = initial_value;\n        OutputT inclusive   = scan_op(initial_value, val);\n\n        for (int i = 1; i < num_items; ++i)\n        {\n            val = h_in[i];\n            h_reference[i] = inclusive;\n            inclusive = scan_op(inclusive, val);\n        }\n    }\n}\n\n\n/**\n * Solve inclusive-scan problem\n */\ntemplate <\n    typename        InputIteratorT,\n    typename        OutputT,\n    typename        ScanOpT>\nvoid Solve(\n    InputIteratorT  h_in,\n    OutputT         *h_reference,\n    int             num_items,\n    ScanOpT         scan_op,\n    NullType)\n{\n    if (num_items > 0)\n    {\n        OutputT inclusive   = h_in[0];\n        h_reference[0]      = inclusive;\n\n        for (int i = 1; i < num_items; ++i)\n        {\n            OutputT val = h_in[i];\n            inclusive = scan_op(inclusive, val);\n            h_reference[i] = inclusive;\n        }\n    }\n}\n\n\n/**\n * Test DeviceScan for a given problem input\n */\ntemplate <\n    Backend             BACKEND,\n    typename            DeviceInputIteratorT,\n    typename            OutputT,\n    typename            ScanOpT,\n    typename            InitialValueT>\nvoid Test(\n    DeviceInputIteratorT    d_in,\n    OutputT                 *h_reference,\n    int                     num_items,\n    ScanOpT                 scan_op,\n    InitialValueT           initial_value)\n{\n    typedef typename std::iterator_traits<DeviceInputIteratorT>::value_type InputT;\n\n    // Allocate device output array\n    OutputT *d_out = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(OutputT) * num_items));\n\n    // Allocate CDP device arrays\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,   sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(\n        Int2Type<BACKEND>(),\n        Int2Type<Traits<OutputT>::PRIMITIVE>(),\n        1,\n        d_temp_storage_bytes,\n        d_cdp_error,\n        d_temp_storage,\n        temp_storage_bytes,\n        d_in,\n        d_out,\n        scan_op,\n        initial_value,\n        num_items,\n        0,\n        true));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output array\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(OutputT) * num_items));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(\n        Int2Type<BACKEND>(),\n        Int2Type<Traits<OutputT>::PRIMITIVE>(),\n        1,\n        d_temp_storage_bytes,\n        d_cdp_error,\n        d_temp_storage,\n        temp_storage_bytes,\n        d_in,\n        d_out,\n        scan_op,\n        initial_value,\n        num_items,\n        0,\n        true));\n\n    // Check for correctness (and display results, if specified)\n    int compare = CompareDeviceResults(h_reference, d_out, num_items, true, g_verbose);\n    printf(\"\\t%s\", compare ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(),\n        Int2Type<Traits<OutputT>::PRIMITIVE>(),\n        g_timing_iterations,\n        d_temp_storage_bytes,\n        d_cdp_error,\n        d_temp_storage,\n        temp_storage_bytes,\n        d_in,\n        d_out,\n        scan_op,\n        initial_value,\n        num_items,\n        0,\n        false));\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis = elapsed_millis / g_timing_iterations;\n        float giga_rate = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth = giga_rate * (sizeof(InputT) + sizeof(OutputT));\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s, %.1f%% peak\", avg_millis, giga_rate, giga_bandwidth, giga_bandwidth / g_device_giga_bandwidth * 100.0);\n    }\n\n    printf(\"\\n\\n\");\n\n    // Cleanup\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare);\n}\n\n\n/**\n * Test DeviceScan on pointer type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        InputT,\n    typename        OutputT,\n    typename        ScanOpT,\n    typename        InitialValueT>\nvoid TestPointer(\n    int             num_items,\n    GenMode         gen_mode,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value)\n{\n    printf(\"\\nPointer %s %s cub::DeviceScan::%s %d items, %s->%s (%d->%d bytes) , gen-mode %s\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        (Equals<InitialValueT, NullType>::VALUE) ? \"Inclusive\" : \"Exclusive\",\n        (Equals<ScanOpT, Sum>::VALUE) ? \"Sum\" : \"Scan\",\n        num_items,\n        typeid(InputT).name(), typeid(OutputT).name(), (int) sizeof(InputT), (int) sizeof(OutputT),\n        (gen_mode == RANDOM) ? \"RANDOM\" : (gen_mode == INTEGER_SEED) ? \"SEQUENTIAL\" : \"HOMOGENOUS\");\n    fflush(stdout);\n\n    // Allocate host arrays\n    InputT*     h_in        = new InputT[num_items];\n    OutputT*    h_reference = new OutputT[num_items];\n\n    // Initialize problem and solution\n    Initialize(gen_mode, h_in, num_items);\n    Solve(h_in, h_reference, num_items, scan_op, initial_value);\n\n    // Allocate problem device arrays\n    InputT *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(InputT) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(InputT) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<BACKEND>(d_in, h_reference, num_items, scan_op, initial_value);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n}\n\n\n/**\n * Test DeviceScan on iterator type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        InputT,\n    typename        OutputT,\n    typename        ScanOpT,\n    typename        InitialValueT>\nvoid TestIterator(\n    int             num_items,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value)\n{\n    printf(\"\\nIterator %s %s cub::DeviceScan::%s %d items, %s->%s (%d->%d bytes)\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        (Equals<InitialValueT, NullType>::VALUE) ? \"Inclusive\" : \"Exclusive\",\n        (Equals<ScanOpT, Sum>::VALUE) ? \"Sum\" : \"Scan\",\n        num_items,\n        typeid(InputT).name(), typeid(OutputT).name(), (int) sizeof(InputT), (int) sizeof(OutputT));\n    fflush(stdout);\n\n    // Use a constant iterator as the input\n    InputT val = InputT();\n    ConstantInputIterator<InputT, int> h_in(val);\n\n    // Allocate host arrays\n    OutputT*  h_reference = new OutputT[num_items];\n\n    // Initialize problem and solution\n    Solve(h_in, h_reference, num_items, scan_op, initial_value);\n\n    // Run Test\n    Test<BACKEND>(h_in, h_reference, num_items, scan_op, initial_value);\n\n    // Cleanup\n    if (h_reference) delete[] h_reference;\n}\n\n\n/**\n * Test different gen modes\n */\ntemplate <\n    Backend         BACKEND,\n    typename        InputT,\n    typename        OutputT,\n    typename        ScanOpT,\n    typename        InitialValueT>\nvoid Test(\n    int             num_items,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value)\n{\n    TestPointer<BACKEND, InputT, OutputT>(  num_items, UNIFORM, scan_op, initial_value);\n    TestPointer<BACKEND, InputT, OutputT>(  num_items, RANDOM,  scan_op, initial_value);\n    TestIterator<BACKEND, InputT, OutputT>( num_items, scan_op, initial_value);\n}\n\n\n/**\n * Test different dispatch\n */\ntemplate <\n    typename        InputT,\n    typename        OutputT,\n    typename        ScanOpT,\n    typename        InitialValueT>\nvoid Test(\n    int             num_items,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value)\n{\n    Test<CUB, InputT, OutputT>(num_items, scan_op, initial_value);\n#ifdef CUB_CDP\n    Test<CDP, InputT, OutputT>(num_items, scan_op, initial_value);\n#endif\n}\n\n\n/**\n * Test different operators\n */\ntemplate <typename InputT, typename OutputT>\nvoid TestOp(\n    int             num_items,\n    OutputT         identity,\n    OutputT         initial_value)\n{\n    // Exclusive (use identity as initial value because it will dispatch to *Sum variants that don't take initial values)\n    Test<InputT, OutputT>(num_items, cub::Sum(), identity);\n    Test<InputT, OutputT>(num_items, cub::Max(), identity);\n\n    // Exclusive (non-specialized, so we can test initial-value)\n    Test<InputT, OutputT>(num_items, WrapperFunctor<cub::Sum>(cub::Sum()), initial_value);\n    Test<InputT, OutputT>(num_items, WrapperFunctor<cub::Max>(cub::Max()), initial_value);\n\n    // Inclusive (no initial value)\n    Test<InputT, OutputT>(num_items, cub::Sum(), NullType());\n    Test<InputT, OutputT>(num_items, cub::Max(), NullType());\n}\n\n\n/**\n * Test different input sizes\n */\ntemplate <\n    typename InputT,\n    typename OutputT>\nvoid TestSize(\n    int     num_items,\n    OutputT identity,\n    OutputT initial_value)\n{\n    if (num_items < 0)\n    {\n        TestOp<InputT>(0,        identity, initial_value);\n        TestOp<InputT>(1,        identity, initial_value);\n        TestOp<InputT>(100,      identity, initial_value);\n        TestOp<InputT>(10000,    identity, initial_value);\n        TestOp<InputT>(1000000,  identity, initial_value);\n\n        // Randomly select problem size between 1:10,000,000\n        unsigned int max_int = (unsigned int) -1;\n        for (int i = 0; i < 10; ++i)\n        {\n            unsigned int num_items;\n            RandomBits(num_items);\n            num_items = (unsigned int) ((double(num_items) * double(10000000)) / double(max_int));\n            num_items = CUB_MAX(1, num_items);\n            TestOp<InputT>(num_items,  identity, initial_value);\n        }\n    }\n    else\n    {\n        TestOp<InputT>(num_items, identity, initial_value);\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items = -1;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    g_device_giga_bandwidth = args.device_giga_bandwidth;\n    printf(\"\\n\");\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic CUB test\n    if (num_items < 0) num_items = 32000000;\n\n    TestPointer<CUB, char, int>(         num_items    , UNIFORM, Sum(), (int) (0));\n    TestPointer<CUB, int, int>(         num_items    , UNIFORM, Sum(), (int) (0));\n\n#elif defined(QUICK_TEST)\n\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get device SM version\n    int sm_version;\n    CubDebugExit(SmVersion(sm_version, device_ordinal));\n\n    // Compile/run quick tests\n    if (num_items < 0) num_items = 32000000;\n\n    TestPointer<CUB, char, char>(        num_items * ((sm_version <= 130) ? 1 : 4), UNIFORM, Sum(), char(0));\n    TestPointer<THRUST, char, char>(     num_items * ((sm_version <= 130) ? 1 : 4), UNIFORM, Sum(), char(0));\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, short, short>(       num_items * ((sm_version <= 130) ? 1 : 2), UNIFORM, Sum(), short(0));\n    TestPointer<THRUST, short, short>(    num_items * ((sm_version <= 130) ? 1 : 2), UNIFORM, Sum(), short(0));\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, int, int>(         num_items    , UNIFORM, Sum(), (int) (0));\n    TestPointer<THRUST, int, int>(      num_items    , UNIFORM, Sum(), (int) (0));\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, long long, long long>(   num_items / 2, UNIFORM, Sum(), (long long) (0));\n    TestPointer<THRUST, long long, long long>(num_items / 2, UNIFORM, Sum(), (long long) (0));\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, TestBar, TestBar>(     num_items / 4, UNIFORM, Sum(), TestBar());\n    TestPointer<THRUST, TestBar, TestBar>(  num_items / 4, UNIFORM, Sum(), TestBar());\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test different input+output data types\n        TestSize<unsigned char>(num_items,      (int) 0, (int) 99);\n\n        // Test same intput+output data types\n        TestSize<unsigned char>(num_items,      (unsigned char) 0,      (unsigned char) 99);\n        TestSize<char>(num_items,               (char) 0,               (char) 99);\n        TestSize<unsigned short>(num_items,     (unsigned short) 0,     (unsigned short)99);\n        TestSize<unsigned int>(num_items,       (unsigned int) 0,       (unsigned int) 99);\n        TestSize<unsigned long long>(num_items, (unsigned long long) 0, (unsigned long long) 99);\n\n        TestSize<uchar2>(num_items,     make_uchar2(0, 0),              make_uchar2(17, 21));\n        TestSize<char2>(num_items,      make_char2(0, 0),               make_char2(17, 21));\n        TestSize<ushort2>(num_items,    make_ushort2(0, 0),             make_ushort2(17, 21));\n        TestSize<uint2>(num_items,      make_uint2(0, 0),               make_uint2(17, 21));\n        TestSize<ulonglong2>(num_items, make_ulonglong2(0, 0),          make_ulonglong2(17, 21));\n        TestSize<uchar4>(num_items,     make_uchar4(0, 0, 0, 0),        make_uchar4(17, 21, 32, 85));\n        TestSize<char4>(num_items,      make_char4(0, 0, 0, 0),         make_char4(17, 21, 32, 85));\n\n        TestSize<ushort4>(num_items,    make_ushort4(0, 0, 0, 0),       make_ushort4(17, 21, 32, 85));\n        TestSize<uint4>(num_items,      make_uint4(0, 0, 0, 0),         make_uint4(17, 21, 32, 85));\n        TestSize<ulonglong4>(num_items, make_ulonglong4(0, 0, 0, 0),    make_ulonglong4(17, 21, 32, 85));\n\n        TestSize<TestFoo>(num_items,\n            TestFoo::MakeTestFoo(0, 0, 0, 0),\n            TestFoo::MakeTestFoo(1ll << 63, 1 << 31, short(1 << 15), char(1 << 7)));\n\n        TestSize<TestBar>(num_items,\n            TestBar(0, 0),\n            TestBar(1ll << 63, 1 << 31));\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_select_if.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceSelect::If and DevicePartition::If utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/copy.h>\n#include <thrust/partition.h>\n#include <thrust/iterator/reverse_iterator.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/device/device_select.cuh>\n#include <cub/device/device_partition.cuh>\n#include <cub/iterator/counting_input_iterator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose               = false;\nint                     g_timing_iterations     = 0;\nint                     g_repeat                = 0;\nfloat                   g_device_giga_bandwidth;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\n// Selection functor type\ntemplate <typename T>\nstruct LessThan\n{\n    T compare;\n\n    __host__ __device__ __forceinline__\n    LessThan(T compare) : compare(compare) {}\n\n    __host__ __device__ __forceinline__\n    bool operator()(const T &a) const {\n        return (a < compare);\n    }\n};\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB DeviceSelect entrypoints\n//---------------------------------------------------------------------\n\n\n/**\n * Dispatch to select if entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    Int2Type<false>             is_flagged,\n    Int2Type<false>             is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSelect::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to partition if entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    Int2Type<false>             is_flagged,\n    Int2Type<true>              is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DevicePartition::If(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, select_op, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to select flagged entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    Int2Type<true>              is_flagged,\n    Int2Type<false>             partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSelect::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n/**\n * Dispatch to partition flagged entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    Int2Type<true>              is_flagged,\n    Int2Type<true>              partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DevicePartition::Flagged(d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n/**\n * Dispatch to select if entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__host__ __forceinline__\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    Int2Type<false>             is_flagged,\n    Int2Type<false>             is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<OutputT>         d_out_wrapper_end;\n        thrust::device_ptr<InputT>          d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT>         d_out_wrapper(d_out);\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_wrapper_end = thrust::copy_if(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper, select_op);\n        }\n\n        OffsetT num_selected = OffsetT(d_out_wrapper_end - d_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_selected_out, &num_selected, sizeof(OffsetT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to partition if entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__host__ __forceinline__\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    Int2Type<false>             is_flagged,\n    Int2Type<true>              is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    typedef thrust::reverse_iterator<thrust::device_ptr<OutputT> > ReverseOutputIteratorT;\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::pair<thrust::device_ptr<OutputT>, ReverseOutputIteratorT> d_out_wrapper_end;\n\n        thrust::device_ptr<InputT>       d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT>       d_out_wrapper(d_out);\n\n        ReverseOutputIteratorT d_out_unselected(d_out_wrapper + num_items);\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_wrapper_end = thrust::partition_copy(\n                d_in_wrapper,\n                d_in_wrapper + num_items,\n                d_out_wrapper,\n                d_out_unselected,\n                select_op);\n        }\n\n        OffsetT num_selected = OffsetT(d_out_wrapper_end.first - d_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_selected_out, &num_selected, sizeof(OffsetT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to select flagged entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__host__ __forceinline__\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    Int2Type<true>              is_flagged,\n    Int2Type<false>             is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The flag type\n    typedef typename std::iterator_traits<FlagIteratorT>::value_type FlagT;\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<OutputT>     d_out_wrapper_end;\n        thrust::device_ptr<InputT>      d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT>     d_out_wrapper(d_out);\n        thrust::device_ptr<FlagT>       d_flags_wrapper(d_flags);\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_wrapper_end = thrust::copy_if(d_in_wrapper, d_in_wrapper + num_items, d_flags_wrapper, d_out_wrapper, CastOp<bool>());\n        }\n\n        OffsetT num_selected = OffsetT(d_out_wrapper_end - d_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_selected_out, &num_selected, sizeof(OffsetT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n/**\n * Dispatch to partition flagged entrypoint\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__host__ __forceinline__\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    Int2Type<true>              is_flagged,\n    Int2Type<true>              is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The flag type\n    typedef typename std::iterator_traits<FlagIteratorT>::value_type FlagT;\n\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    typedef thrust::reverse_iterator<thrust::device_ptr<OutputT> > ReverseOutputIteratorT;\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::pair<thrust::device_ptr<OutputT>, ReverseOutputIteratorT> d_out_wrapper_end;\n\n        thrust::device_ptr<InputT>  d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        thrust::device_ptr<FlagT>   d_flags_wrapper(d_flags);\n        ReverseOutputIteratorT      d_out_unselected(d_out_wrapper + num_items);\n\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_wrapper_end = thrust::partition_copy(\n                d_in_wrapper,\n                d_in_wrapper + num_items,\n                d_flags_wrapper,\n                d_out_wrapper,\n                d_out_unselected,\n                CastOp<bool>());\n        }\n\n        OffsetT num_selected = OffsetT(d_out_wrapper_end.first - d_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_selected_out, &num_selected, sizeof(OffsetT), cudaMemcpyHostToDevice));\n    }\n\n    return cudaSuccess;\n}\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceSelect\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT, typename IsFlaggedTag, typename IsPartitionTag>\n__global__ void CnpDispatchKernel(\n    IsFlaggedTag                is_flagged,\n    IsPartitionTag              is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t                      temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    bool                        debug_synchronous)\n{\n\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(Int2Type<CUB>(), is_flagged, is_partition, timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, select_op, 0, debug_synchronous);\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <typename InputIteratorT, typename FlagIteratorT, typename SelectOpT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT, typename IsFlaggedTag, typename IsPartitionTag>\ncudaError_t Dispatch(\n    Int2Type<CDP>               dispatch_to,\n    IsFlaggedTag                is_flagged,\n    IsPartitionTag              is_partition,\n    int                         timing_timing_iterations,\n    size_t*                     d_temp_storage_bytes,\n    cudaError_t*                d_cdp_error,\n\n    void*                       d_temp_storage,\n    size_t&                     temp_storage_bytes,\n    InputIteratorT              d_in,\n    FlagIteratorT               d_flags,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    SelectOpT                   select_op,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(is_flagged, is_partition, timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, select_op, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    T*  h_in,\n    int num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        // Initialize each item to a randomly selected value from [0..126]\n        unsigned int value;\n        RandomBits(value, 0, 0, 7);\n        if (value == 127)\n            value = 126;\n        InitValue(INTEGER_SEED, h_in[i], value);\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve selection problem (and set corresponding flags)\n */\ntemplate <\n    typename        InputIteratorT,\n    typename        FlagIteratorT,\n    typename        SelectOpT,\n    typename        T>\nint Solve(\n    InputIteratorT  h_in,\n    SelectOpT       select_op,\n    T*              h_reference,\n    FlagIteratorT   h_flags,\n    int             num_items)\n{\n    int num_selected = 0;\n    for (int i = 0; i < num_items; ++i)\n    {\n        if ((h_flags[i] = select_op(h_in[i])))\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n        else\n        {\n            h_reference[num_items - (i - num_selected) - 1] = h_in[i];\n        }\n    }\n\n    return num_selected;\n}\n\n\n\n/**\n * Test DeviceSelect for a given problem input\n */\ntemplate <\n    Backend             BACKEND,\n    bool                IS_FLAGGED,\n    bool                IS_PARTITION,\n    typename            DeviceInputIteratorT,\n    typename            FlagT,\n    typename            SelectOpT,\n    typename            T>\nvoid Test(\n    DeviceInputIteratorT    d_in,\n    FlagT*                  h_flags,\n    SelectOpT               select_op,\n    T*                      h_reference,\n    int                     num_selected,\n    int                     num_items)\n{\n    // Allocate device flags, output, and num-selected\n    FlagT*      d_flags = NULL;\n    T*          d_out = NULL;\n    int*        d_num_selected_out = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_flags, sizeof(FlagT) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate CDP device arrays\n    size_t*         d_temp_storage_bytes = NULL;\n    cudaError_t*    d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), Int2Type<IS_FLAGGED>(), Int2Type<IS_PARTITION>(), 1, d_temp_storage_bytes, d_cdp_error,\n    d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, select_op, 0, true));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Copy flags and clear device output array\n    CubDebugExit(cudaMemcpy(d_flags, h_flags, sizeof(FlagT) * num_items, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * num_items));\n    CubDebugExit(cudaMemset(d_num_selected_out, 0, sizeof(int)));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), Int2Type<IS_FLAGGED>(), Int2Type<IS_PARTITION>(), 1, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, select_op, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare1 = (IS_PARTITION) ?\n        CompareDeviceResults(h_reference, d_out, num_items, true, g_verbose) :\n        CompareDeviceResults(h_reference, d_out, num_selected, true, g_verbose);\n    printf(\"\\t Data %s\\n\", compare1 ? \"FAIL\" : \"PASS\");\n\n    int compare2 = CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s\\n\", compare2 ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), Int2Type<IS_FLAGGED>(), Int2Type<IS_PARTITION>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_flags, d_out, d_num_selected_out, num_items, select_op, 0, false));\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float   avg_millis          = elapsed_millis / g_timing_iterations;\n        float   giga_rate           = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        int     num_output_items    = (IS_PARTITION) ? num_items : num_selected;\n        int     num_flag_items      = (IS_FLAGGED) ? num_items : 0;\n        size_t  num_bytes           = sizeof(T) * (num_items + num_output_items) + sizeof(FlagT) * num_flag_items;\n        float   giga_bandwidth      = float(num_bytes) / avg_millis / 1000.0f / 1000.0f;\n\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s, %.1f%% peak\", avg_millis, giga_rate, giga_bandwidth, giga_bandwidth / g_device_giga_bandwidth * 100.0);\n    }\n    printf(\"\\n\\n\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Cleanup\n    if (d_flags) CubDebugExit(g_allocator.DeviceFree(d_flags));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare1 | compare2);\n}\n\n\n/**\n * Test on pointer type\n */\ntemplate <\n    Backend         BACKEND,\n    bool            IS_FLAGGED,\n    bool            IS_PARTITION,\n    typename        T>\nvoid TestPointer(\n    int             num_items,\n    float           select_ratio)\n{\n    typedef char FlagT;\n\n    // Allocate host arrays\n    T*      h_in        = new T[num_items];\n    FlagT*  h_flags     = new FlagT[num_items];\n    T*      h_reference = new T[num_items];\n\n    // Initialize input\n    Initialize(h_in, num_items);\n\n    // Select a comparison value that is select_ratio through the space of [0,127]\n    T compare;\n    if (select_ratio <= 0.0)\n        InitValue(INTEGER_SEED, compare, 0);        // select none\n    else if (select_ratio >= 1.0)\n        InitValue(INTEGER_SEED, compare, 127);      // select all\n    else\n        InitValue(INTEGER_SEED, compare, int(double(double(127) * select_ratio)));\n\n    LessThan<T> select_op(compare);\n    int num_selected = Solve(h_in, select_op, h_reference, h_flags, num_items);\n\n    if (g_verbose) std::cout << \"\\nComparison item: \" << compare << \"\\n\";\n    printf(\"\\nPointer %s cub::%s::%s %d items, %d selected (select ratio %.3f), %s %d-byte elements\\n\",\n        (IS_PARTITION) ? \"DevicePartition\" : \"DeviceSelect\",\n        (IS_FLAGGED) ? \"Flagged\" : \"If\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_selected, float(num_selected) / num_items, typeid(T).name(), (int) sizeof(T));\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    T *d_in = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<BACKEND, IS_FLAGGED, IS_PARTITION>(d_in, h_flags, select_op, h_reference, num_selected, num_items);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (h_flags) delete[] h_flags;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n}\n\n\n/**\n * Test on iterator type\n */\ntemplate <\n    Backend         BACKEND,\n    bool            IS_FLAGGED,\n    bool            IS_PARTITION,\n    typename        T>\nvoid TestIterator(\n    int             num_items,\n    float           select_ratio)\n{\n    typedef char FlagT;\n\n    // Allocate host arrays\n    T*      h_reference = new T[num_items];\n    FlagT*  h_flags = new FlagT[num_items];\n\n    // Use counting iterator as the input\n    CountingInputIterator<T, int> h_in(0);\n\n    // Select a comparison value that is select_ratio through the space of [0,127]\n    T compare;\n    if (select_ratio <= 0.0)\n        InitValue(INTEGER_SEED, compare, 0);        // select none\n    else if (select_ratio >= 1.0)\n        InitValue(INTEGER_SEED, compare, 127);      // select all\n    else\n        InitValue(INTEGER_SEED, compare, int(double(double(127) * select_ratio)));\n\n    LessThan<T> select_op(compare);\n    int num_selected = Solve(h_in, select_op, h_reference, h_flags, num_items);\n\n    if (g_verbose) std::cout << \"\\nComparison item: \" << compare << \"\\n\";\n    printf(\"\\nIterator %s cub::%s::%s %d items, %d selected (select ratio %.3f), %s %d-byte elements\\n\",\n        (IS_PARTITION) ? \"DevicePartition\" : \"DeviceSelect\",\n        (IS_FLAGGED) ? \"Flagged\" : \"If\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_selected, float(num_selected) / num_items, typeid(T).name(), (int) sizeof(T));\n    fflush(stdout);\n\n    // Run Test\n    Test<BACKEND, IS_FLAGGED, IS_PARTITION>(h_in, h_flags, select_op, h_reference, num_selected, num_items);\n\n    // Cleanup\n    if (h_reference) delete[] h_reference;\n    if (h_flags) delete[] h_flags;\n}\n\n\n/**\n * Test different selection ratios\n */\ntemplate <\n    Backend         BACKEND,\n    bool            IS_FLAGGED,\n    bool            IS_PARTITION,\n    typename        T>\nvoid Test(\n    int             num_items)\n{\n    for (float select_ratio = 0.0f; select_ratio <= 1.0f; select_ratio += 0.2f)\n    {\n        TestPointer<BACKEND, IS_FLAGGED, IS_PARTITION, T>(num_items, select_ratio);\n    }\n}\n\n\n/**\n * Test (select vs. partition) and (flagged vs. functor)\n */\ntemplate <\n    Backend         BACKEND,\n    typename        T>\nvoid TestMethod(\n    int             num_items)\n{\n    // Functor\n    Test<BACKEND, false, false, T>(num_items);\n    Test<BACKEND, false, true, T>(num_items);\n\n    // Flagged\n    Test<BACKEND, true, false, T>(num_items);\n    Test<BACKEND, true, true, T>(num_items);\n}\n\n\n/**\n * Test different dispatch\n */\ntemplate <\n    typename        T>\nvoid TestOp(\n    int             num_items)\n{\n    TestMethod<CUB, T>(num_items);\n#ifdef CUB_CDP\n    TestMethod<CDP, T>(num_items);\n#endif\n}\n\n\n/**\n * Test different input sizes\n */\ntemplate <typename T>\nvoid Test(\n    int             num_items)\n{\n    if (num_items < 0)\n    {\n        TestOp<T>(0);\n        TestOp<T>(1);\n        TestOp<T>(100);\n        TestOp<T>(10000);\n        TestOp<T>(1000000);\n    }\n    else\n    {\n        TestOp<T>(num_items);\n    }\n}\n\n/**\n * Test select/partition on pointer types\n */\ntemplate <typename T>\nvoid ComparePointer(\n    int             num_items,\n    float           select_ratio)\n{\n    printf(\"-- Select-if ----------------------------\\n\");\n    TestPointer<CUB, false, false, T>(num_items, select_ratio);\n    TestPointer<THRUST, false, false, T>(num_items, select_ratio);\n\n    printf(\"-- Partition-if ----------------------------\\n\");\n    TestPointer<CUB, false, true, T>(num_items, select_ratio);\n    TestPointer<THRUST, false, true, T>(num_items, select_ratio);\n\n    printf(\"-- Select-flagged ----------------------------\\n\");\n    TestPointer<CUB, true, false, T>(num_items, select_ratio);\n    TestPointer<THRUST, true, false, T>(num_items, select_ratio);\n\n    printf(\"-- Partition-flagged ----------------------------\\n\");\n    TestPointer<CUB, true, true, T>(num_items, select_ratio);\n    TestPointer<THRUST, true, true, T>(num_items, select_ratio);\n\n}\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = -1;\n    float select_ratio      = 0.5;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"ratio\", select_ratio);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--ratio=<selection ratio, default 0.5>] \"\n            \"[--repeat=<repetitions of entire test suite>] \"\n            \"[--v] \"\n            \"[--cdp] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    g_device_giga_bandwidth = args.device_giga_bandwidth;\n    printf(\"\\n\");\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic CUB test\n    if (num_items < 0) num_items = 32000000;\n\n    printf(\"-- Select-if ----------------------------\\n\");\n    TestPointer<CUB, false, false, int>(num_items, select_ratio);\n\n    printf(\"-- Partition-if ----------------------------\\n\");\n    TestPointer<CUB, false, true, int>(num_items, select_ratio);\n\n    printf(\"-- Select-flagged ----------------------------\\n\");\n    TestPointer<CUB, true, false, int>(num_items, select_ratio);\n\n    printf(\"-- Partition-flagged ----------------------------\\n\");\n    TestPointer<CUB, true, true, int>(num_items, select_ratio);\n\n\n#elif defined(QUICK_TEST)\n\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get device SM version\n    int sm_version;\n    CubDebugExit(SmVersion(sm_version, device_ordinal));\n\n    // Compile/run quick tests\n    if (num_items < 0) num_items = 32000000;\n\n    printf(\"-- Iterator ----------------------------\\n\");\n    TestIterator<CUB, false, false, int>(num_items, select_ratio);\n\n    ComparePointer<char>(       num_items * ((sm_version <= 130) ? 1 : 4),  select_ratio);\n    ComparePointer<short>(      num_items * ((sm_version <= 130) ? 1 : 2),  select_ratio);\n    ComparePointer<int>(        num_items,                                  select_ratio);\n    ComparePointer<long long>(  num_items / 2,                              select_ratio);\n    ComparePointer<TestFoo>(    num_items / 4,                              select_ratio);\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test different input types\n        Test<unsigned char>(num_items);\n        Test<unsigned short>(num_items);\n        Test<unsigned int>(num_items);\n        Test<unsigned long long>(num_items);\n\n        Test<uchar2>(num_items);\n        Test<ushort2>(num_items);\n        Test<uint2>(num_items);\n        Test<ulonglong2>(num_items);\n\n        Test<uchar4>(num_items);\n        Test<ushort4>(num_items);\n        Test<uint4>(num_items);\n        Test<ulonglong4>(num_items);\n\n        Test<TestFoo>(num_items);\n        Test<TestBar>(num_items);\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_device_select_unique.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of DeviceSelect::Unique utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <thrust/device_ptr.h>\n#include <thrust/unique.h>\n\n#include <cub/util_allocator.cuh>\n#include <cub/iterator/counting_input_iterator.cuh>\n#include <cub/device/device_select.cuh>\n\n#include <thrust/device_ptr.h>\n#include <thrust/unique.h>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose               = false;\nint                     g_timing_iterations     = 0;\nint                     g_repeat                = 0;\nfloat                   g_device_giga_bandwidth;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\n//---------------------------------------------------------------------\n// Dispatch to different CUB DeviceSelect entrypoints\n//---------------------------------------------------------------------\n\n\n/**\n * Dispatch to unique entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\nCUB_RUNTIME_FUNCTION __forceinline__\ncudaError_t Dispatch(\n    Int2Type<CUB>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    OutputIteratorT              d_out,\n    NumSelectedIteratorT         d_num_selected_out,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    cudaError_t error = cudaSuccess;\n    for (int i = 0; i < timing_timing_iterations; ++i)\n    {\n        error = DeviceSelect::Unique(d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, stream, debug_synchronous);\n    }\n    return error;\n}\n\n\n//---------------------------------------------------------------------\n// Dispatch to different Thrust entrypoints\n//---------------------------------------------------------------------\n\n\n/**\n * Dispatch to unique entrypoint\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__host__ __forceinline__\ncudaError_t Dispatch(\n    Int2Type<THRUST>            dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void                        *d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    OutputIteratorT             d_out,\n    NumSelectedIteratorT        d_num_selected_out,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // The input value type\n    typedef typename std::iterator_traits<InputIteratorT>::value_type InputT;\n\n    // The output value type\n    typedef typename If<(Equals<typename std::iterator_traits<OutputIteratorT>::value_type, void>::VALUE),  // OutputT =  (if output iterator's value type is void) ?\n        typename std::iterator_traits<InputIteratorT>::value_type,                                          // ... then the input iterator's value type,\n        typename std::iterator_traits<OutputIteratorT>::value_type>::Type OutputT;                          // ... else the output iterator's value type\n\n    if (d_temp_storage == 0)\n    {\n        temp_storage_bytes = 1;\n    }\n    else\n    {\n        thrust::device_ptr<OutputT> d_out_wrapper_end;\n        thrust::device_ptr<InputT> d_in_wrapper(d_in);\n        thrust::device_ptr<OutputT> d_out_wrapper(d_out);\n        for (int i = 0; i < timing_timing_iterations; ++i)\n        {\n            d_out_wrapper_end = thrust::unique_copy(d_in_wrapper, d_in_wrapper + num_items, d_out_wrapper);\n        }\n\n        OffsetT num_selected = OffsetT(d_out_wrapper_end - d_out_wrapper);\n        CubDebugExit(cudaMemcpy(d_num_selected_out, &num_selected, sizeof(OffsetT), cudaMemcpyHostToDevice));\n\n    }\n\n    return cudaSuccess;\n}\n\n\n\n//---------------------------------------------------------------------\n// CUDA Nested Parallelism Test Kernel\n//---------------------------------------------------------------------\n\n/**\n * Simple wrapper kernel to invoke DeviceSelect\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\n__global__ void CnpDispatchKernel(\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      temp_storage_bytes,\n    InputIteratorT              d_in,\n    OutputIteratorT              d_out,\n    NumSelectedIteratorT         d_num_selected_out,\n    OffsetT                     num_items,\n    bool                        debug_synchronous)\n{\n\n#ifndef CUB_CDP\n    *d_cdp_error = cudaErrorNotSupported;\n#else\n    *d_cdp_error = Dispatch(Int2Type<CUB>(), timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, 0, debug_synchronous);\n    *d_temp_storage_bytes = temp_storage_bytes;\n#endif\n}\n\n\n/**\n * Dispatch to CDP kernel\n */\ntemplate <typename InputIteratorT, typename OutputIteratorT, typename NumSelectedIteratorT, typename OffsetT>\ncudaError_t Dispatch(\n    Int2Type<CDP>               dispatch_to,\n    int                         timing_timing_iterations,\n    size_t                      *d_temp_storage_bytes,\n    cudaError_t                 *d_cdp_error,\n\n    void*               d_temp_storage,\n    size_t                      &temp_storage_bytes,\n    InputIteratorT              d_in,\n    OutputIteratorT              d_out,\n    NumSelectedIteratorT         d_num_selected_out,\n    OffsetT                     num_items,\n    cudaStream_t                stream,\n    bool                        debug_synchronous)\n{\n    // Invoke kernel to invoke device-side dispatch\n    CnpDispatchKernel<<<1,1>>>(timing_timing_iterations, d_temp_storage_bytes, d_cdp_error,\n        d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, debug_synchronous);\n\n    // Copy out temp_storage_bytes\n    CubDebugExit(cudaMemcpy(&temp_storage_bytes, d_temp_storage_bytes, sizeof(size_t) * 1, cudaMemcpyDeviceToHost));\n\n    // Copy out error\n    cudaError_t retval;\n    CubDebugExit(cudaMemcpy(&retval, d_cdp_error, sizeof(cudaError_t) * 1, cudaMemcpyDeviceToHost));\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Test generation\n//---------------------------------------------------------------------\n\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    int         entropy_reduction,\n    T           *h_in,\n    int         num_items,\n    int         max_segment)\n{\n    unsigned int max_int = (unsigned int) -1;\n\n    int key = 0;\n    int i = 0;\n    while (i < num_items)\n    {\n        // Select number of repeating occurrences for the current run\n        int repeat;\n        if (max_segment < 0)\n        {\n            repeat = num_items;\n        }\n        else if (max_segment < 2)\n        {\n            repeat = 1;\n        }\n        else\n        {\n            RandomBits(repeat, entropy_reduction);\n            repeat = (int) ((double(repeat) * double(max_segment)) / double(max_int));\n            repeat = CUB_MAX(1, repeat);\n        }\n\n        int j = i;\n        while (j < CUB_MIN(i + repeat, num_items))\n        {\n            InitValue(INTEGER_SEED, h_in[j], key);\n            j++;\n        }\n\n        i = j;\n        key++;\n    }\n\n    if (g_verbose)\n    {\n        printf(\"Input:\\n\");\n        DisplayResults(h_in, num_items);\n        printf(\"\\n\\n\");\n    }\n}\n\n\n/**\n * Solve unique problem\n */\ntemplate <\n    typename        InputIteratorT,\n    typename        T>\nint Solve(\n    InputIteratorT  h_in,\n    T               *h_reference,\n    int             num_items)\n{\n    int num_selected = 0;\n    if (num_items > 0)\n    {\n        h_reference[num_selected] = h_in[0];\n        num_selected++;\n    }\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        if (h_in[i] != h_in[i - 1])\n        {\n            h_reference[num_selected] = h_in[i];\n            num_selected++;\n        }\n    }\n\n    return num_selected;\n}\n\n\n\n/**\n * Test DeviceSelect for a given problem input\n */\ntemplate <\n    Backend             BACKEND,\n    typename            DeviceInputIteratorT,\n    typename            T>\nvoid Test(\n    DeviceInputIteratorT d_in,\n    T                   *h_reference,\n    int                 num_selected,\n    int                 num_items)\n{\n    // Allocate device output array and num selected\n    T       *d_out            = NULL;\n    int     *d_num_selected_out   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * num_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_num_selected_out, sizeof(int)));\n\n    // Allocate CDP device arrays\n    size_t          *d_temp_storage_bytes = NULL;\n    cudaError_t     *d_cdp_error = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_temp_storage_bytes,  sizeof(size_t) * 1));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_cdp_error,           sizeof(cudaError_t) * 1));\n\n    // Allocate temporary storage\n    void            *d_temp_storage = NULL;\n    size_t          temp_storage_bytes = 0;\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, 0, true));\n    CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n    // Clear device output array\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * num_items));\n    CubDebugExit(cudaMemset(d_num_selected_out, 0, sizeof(int)));\n\n    // Run warmup/correctness iteration\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), 1, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, 0, true));\n\n    // Check for correctness (and display results, if specified)\n    int compare1 = CompareDeviceResults(h_reference, d_out, num_selected, true, g_verbose);\n    printf(\"\\t Data %s \", compare1 ? \"FAIL\" : \"PASS\");\n\n    int compare2 = CompareDeviceResults(&num_selected, d_num_selected_out, 1, true, g_verbose);\n    printf(\"\\t Count %s \", compare2 ? \"FAIL\" : \"PASS\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Performance\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    CubDebugExit(Dispatch(Int2Type<BACKEND>(), g_timing_iterations, d_temp_storage_bytes, d_cdp_error, d_temp_storage, temp_storage_bytes, d_in, d_out, d_num_selected_out, num_items, 0, false));\n    gpu_timer.Stop();\n    float elapsed_millis = gpu_timer.ElapsedMillis();\n\n    // Display performance\n    if (g_timing_iterations > 0)\n    {\n        float avg_millis        = elapsed_millis / g_timing_iterations;\n        float giga_rate         = float(num_items) / avg_millis / 1000.0f / 1000.0f;\n        float giga_bandwidth    = float((num_items + num_selected) * sizeof(T)) / avg_millis / 1000.0f / 1000.0f;\n        printf(\", %.3f avg ms, %.3f billion items/s, %.3f logical GB/s, %.1f%% peak\", avg_millis, giga_rate, giga_bandwidth, giga_bandwidth / g_device_giga_bandwidth * 100.0);\n    }\n    printf(\"\\n\\n\");\n\n    // Flush any stdout/stderr\n    fflush(stdout);\n    fflush(stderr);\n\n    // Cleanup\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_num_selected_out) CubDebugExit(g_allocator.DeviceFree(d_num_selected_out));\n    if (d_temp_storage_bytes) CubDebugExit(g_allocator.DeviceFree(d_temp_storage_bytes));\n    if (d_cdp_error) CubDebugExit(g_allocator.DeviceFree(d_cdp_error));\n    if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n    // Correctness asserts\n    AssertEquals(0, compare1 | compare2);\n}\n\n\n/**\n * Test DeviceSelect on pointer type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        T>\nvoid TestPointer(\n    int             num_items,\n    int             entropy_reduction,\n    int             max_segment)\n{\n    // Allocate host arrays\n    T*  h_in        = new T[num_items];\n    T*  h_reference = new T[num_items];\n\n    // Initialize problem and solution\n    Initialize(entropy_reduction, h_in, num_items, max_segment);\n    int num_selected = Solve(h_in, h_reference, num_items);\n\n    printf(\"\\nPointer %s cub::DeviceSelect::Unique %d items, %d selected (avg run length %.3f), %s %d-byte elements, entropy_reduction %d\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_selected, float(num_items) / num_selected,\n        typeid(T).name(),\n        (int) sizeof(T),\n        entropy_reduction);\n    fflush(stdout);\n\n    // Allocate problem device arrays\n    T *d_in = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * num_items));\n\n    // Initialize device input\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * num_items, cudaMemcpyHostToDevice));\n\n    // Run Test\n    Test<BACKEND>(d_in, h_reference, num_selected, num_items);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n}\n\n\n/**\n * Test DeviceSelect on iterator type\n */\ntemplate <\n    Backend         BACKEND,\n    typename        T>\nvoid TestIterator(\n    int             num_items)\n{\n    // Use a counting iterator as the input\n    CountingInputIterator<T, int> h_in(0);\n\n    // Allocate host arrays\n    T*  h_reference = new T[num_items];\n\n    // Initialize problem and solution\n    int num_selected = Solve(h_in, h_reference, num_items);\n\n    printf(\"\\nIterator %s cub::DeviceSelect::Unique %d items, %d selected (avg run length %.3f), %s %d-byte elements\\n\",\n        (BACKEND == CDP) ? \"CDP CUB\" : (BACKEND == THRUST) ? \"Thrust\" : \"CUB\",\n        num_items, num_selected, float(num_items) / num_selected,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    // Run Test\n    Test<BACKEND>(h_in, h_reference, num_selected, num_items);\n\n    // Cleanup\n    if (h_reference) delete[] h_reference;\n}\n\n\n/**\n * Test different gen modes\n */\ntemplate <\n    Backend         BACKEND,\n    typename        T>\nvoid Test(\n    int             num_items)\n{\n    for (int max_segment = 1; ((max_segment > 0) && (max_segment < num_items)); max_segment *= 11)\n    {\n        TestPointer<BACKEND, T>(num_items, 0, max_segment);\n        TestPointer<BACKEND, T>(num_items, 2, max_segment);\n        TestPointer<BACKEND, T>(num_items, 7, max_segment);\n    }\n}\n\n\n/**\n * Test different dispatch\n */\ntemplate <\n    typename        T>\nvoid TestOp(\n    int             num_items)\n{\n    Test<CUB, T>(num_items);\n#ifdef CUB_CDP\n    Test<CDP, T>(num_items);\n#endif\n}\n\n\n/**\n * Test different input sizes\n */\ntemplate <typename T>\nvoid Test(\n    int             num_items)\n{\n    if (num_items < 0)\n    {\n        TestOp<T>(0);\n        TestOp<T>(1);\n        TestOp<T>(100);\n        TestOp<T>(10000);\n        TestOp<T>(1000000);\n    }\n    else\n    {\n        TestOp<T>(num_items);\n    }\n}\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    int num_items           = -1;\n    int entropy_reduction   = 0;\n    int maxseg              = 1000;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"n\", num_items);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n    args.GetCmdLineArgument(\"maxseg\", maxseg);\n    args.GetCmdLineArgument(\"entropy\", entropy_reduction);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--n=<input items> \"\n            \"[--i=<timing iterations> \"\n            \"[--device=<device-id>] \"\n            \"[--maxseg=<max segment length>]\"\n            \"[--entropy=<segment length bit entropy reduction rounds>]\"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"[--cdp]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n    g_device_giga_bandwidth = args.device_giga_bandwidth;\n    printf(\"\\n\");\n\n#ifdef QUICKER_TEST\n\n    // Compile/run basic CUB test\n    if (num_items < 0) num_items = 32000000;\n    TestPointer<CUB, int>(         num_items,                                 entropy_reduction, maxseg);\n\n#elif defined(QUICK_TEST)\n\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get device SM version\n    int sm_version;\n    CubDebugExit(SmVersion(sm_version, device_ordinal));\n\n    // Compile/run quick tests\n    if (num_items < 0) num_items = 32000000;\n\n    printf(\"-- Iterator ----------------------------\\n\");\n    TestIterator<CUB, int>(        num_items);\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, char>(        num_items * ((sm_version <= 130) ? 1 : 4), entropy_reduction, maxseg);\n    TestPointer<THRUST, char>(     num_items * ((sm_version <= 130) ? 1 : 4), entropy_reduction, maxseg);\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, short>(       num_items * ((sm_version <= 130) ? 1 : 2), entropy_reduction, maxseg);\n    TestPointer<THRUST, short>(    num_items * ((sm_version <= 130) ? 1 : 2), entropy_reduction, maxseg);\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, int>(         num_items,                                 entropy_reduction, maxseg);\n    TestPointer<THRUST, int>(      num_items,                                 entropy_reduction, maxseg);\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, long long>(   num_items / 2,                             entropy_reduction, maxseg);\n    TestPointer<THRUST, long long>(num_items / 2,                             entropy_reduction, maxseg);\n\n    printf(\"----------------------------\\n\");\n    TestPointer<CUB, TestFoo>(     num_items / 4,                             entropy_reduction, maxseg);\n    TestPointer<THRUST, TestFoo>(  num_items / 4,                             entropy_reduction, maxseg);\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test different input types\n        Test<unsigned char>(num_items);\n        Test<unsigned short>(num_items);\n        Test<unsigned int>(num_items);\n        Test<unsigned long long>(num_items);\n\n        Test<uchar2>(num_items);\n        Test<ushort2>(num_items);\n        Test<uint2>(num_items);\n        Test<ulonglong2>(num_items);\n\n        Test<uchar4>(num_items);\n        Test<ushort4>(num_items);\n        Test<uint4>(num_items);\n        Test<ulonglong4>(num_items);\n\n        Test<TestFoo>(num_items);\n        Test<TestBar>(num_items);\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_grid_barrier.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test evaluation for software global barrier throughput\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n\n#include <cub/grid/grid_barrier.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/**\n * Kernel that iterates through the specified number of software global barriers\n */\n__global__ void Kernel(\n    GridBarrier global_barrier,\n    int iterations)\n{\n    for (int i = 0; i < iterations; i++)\n    {\n        global_barrier.Sync();\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    cudaError_t retval = cudaSuccess;\n\n    // Defaults\n    int iterations = 10000;\n    int block_size = 128;\n    int grid_size = -1;\n\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n\n    // Get args\n    args.GetCmdLineArgument(\"i\", iterations);\n    args.GetCmdLineArgument(\"grid-size\", grid_size);\n    args.GetCmdLineArgument(\"block-size\", block_size);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>]\"\n            \"[--i=<iterations>]\"\n            \"[--grid-size<grid-size>]\"\n            \"[--block-size<block-size>]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get device SM version\n    int sm_version;\n    CubDebugExit(SmVersion(sm_version, device_ordinal));\n\n    // Get SM properties\n    int sm_count, max_block_threads, max_sm_occupancy;\n    CubDebugExit(cudaDeviceGetAttribute(&sm_count, cudaDevAttrMultiProcessorCount, device_ordinal));\n    CubDebugExit(cudaDeviceGetAttribute(&max_block_threads, cudaDevAttrMaxThreadsPerBlock, device_ordinal));\n    CubDebugExit(MaxSmOccupancy(max_sm_occupancy, EmptyKernel<void>, 32));\n\n    // Compute grid size and occupancy\n    int occupancy = CUB_MIN((max_block_threads / block_size), max_sm_occupancy);\n\n    if (grid_size == -1)\n    {\n        grid_size = occupancy * sm_count;\n    }\n    else\n    {\n        occupancy = grid_size / sm_count;\n    }\n\n    printf(\"Initializing software global barrier for Kernel<<<%d,%d>>> with %d occupancy\\n\",\n        grid_size, block_size, occupancy);\n    fflush(stdout);\n\n    // Init global barrier\n    GridBarrierLifetime global_barrier;\n    global_barrier.Setup(grid_size);\n\n    // Time kernel\n    GpuTimer gpu_timer;\n    gpu_timer.Start();\n    Kernel<<<grid_size, block_size>>>(global_barrier, iterations);\n    gpu_timer.Stop();\n\n    retval = CubDebug(cudaThreadSynchronize());\n\n    // Output timing results\n    float avg_elapsed = gpu_timer.ElapsedMillis() / float(iterations);\n    printf(\"%d iterations, %f total elapsed millis, %f avg elapsed millis\\n\",\n        iterations,\n        gpu_timer.ElapsedMillis(),\n        avg_elapsed);\n\n    return retval;\n}\n"
  },
  {
    "path": "external/cub/test/test_iterator.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of iterator utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <iterator>\n#include <stdio.h>\n#include <typeinfo>\n\n#include <cub/iterator/arg_index_input_iterator.cuh>\n#include <cub/iterator/cache_modified_input_iterator.cuh>\n#include <cub/iterator/cache_modified_output_iterator.cuh>\n#include <cub/iterator/constant_input_iterator.cuh>\n#include <cub/iterator/counting_input_iterator.cuh>\n#include <cub/iterator/tex_obj_input_iterator.cuh>\n#include <cub/iterator/tex_ref_input_iterator.cuh>\n#include <cub/iterator/transform_input_iterator.cuh>\n\n#include <cub/util_type.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\n#include <thrust/device_ptr.h>\n#include <thrust/copy.h>\n\nusing namespace cub;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose = false;\nCachingDeviceAllocator  g_allocator(true);\n\n// Dispatch types\nenum Backend\n{\n    CUB,        // CUB method\n    THRUST,     // Thrust method\n    CDP,        // GPU-based (dynamic parallelism) dispatch to CUB method\n};\n\n\ntemplate <typename T>\nstruct TransformOp\n{\n    // Increment transform\n    __host__ __device__ __forceinline__ T operator()(T input) const\n    {\n        T addend;\n        InitValue(INTEGER_SEED, addend, 1);\n        return input + addend;\n    }\n};\n\nstruct SelectOp\n{\n    template <typename T>\n    __host__ __device__ __forceinline__ bool operator()(T input)\n    {\n        return true;\n    }\n};\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/**\n * Test random access input iterator\n */\ntemplate <\n    typename InputIteratorT,\n    typename T>\n__global__ void Kernel(\n    InputIteratorT    d_in,\n    T                 *d_out,\n    InputIteratorT    *d_itrs)\n{\n    d_out[0] = *d_in;               // Value at offset 0\n    d_out[1] = d_in[100];           // Value at offset 100\n    d_out[2] = *(d_in + 1000);      // Value at offset 1000\n    d_out[3] = *(d_in + 10000);     // Value at offset 10000\n\n    d_in++;\n    d_out[4] = d_in[0];             // Value at offset 1\n\n    d_in += 20;\n    d_out[5] = d_in[0];             // Value at offset 21\n    d_itrs[0] = d_in;               // Iterator at offset 21\n\n    d_in -= 10;\n    d_out[6] = d_in[0];             // Value at offset 11;\n\n    d_in -= 11;\n    d_out[7] = d_in[0];             // Value at offset 0\n    d_itrs[1] = d_in;               // Iterator at offset 0\n}\n\n\n\n//---------------------------------------------------------------------\n// Host testing subroutines\n//---------------------------------------------------------------------\n\n\n/**\n * Run iterator test on device\n */\ntemplate <\n    typename        InputIteratorT,\n    typename        T,\n    int             TEST_VALUES>\nvoid Test(\n    InputIteratorT  d_in,\n    T               (&h_reference)[TEST_VALUES])\n{\n    // Allocate device arrays\n    T                 *d_out    = NULL;\n    InputIteratorT    *d_itrs   = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out,     sizeof(T) * TEST_VALUES));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_itrs,    sizeof(InputIteratorT) * 2));\n\n    int compare;\n\n    // Run unguarded kernel\n    Kernel<<<1, 1>>>(d_in, d_out, d_itrs);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Check results\n    compare = CompareDeviceResults(h_reference, d_out, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tValues: %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Check iterator at offset 21\n    InputIteratorT h_itr = d_in + 21;\n    compare = CompareDeviceResults(&h_itr, d_itrs, 1, g_verbose, g_verbose);\n    printf(\"\\tIterators: %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Check iterator at offset 0\n    compare = CompareDeviceResults(&d_in, d_itrs + 1, 1, g_verbose, g_verbose);\n    printf(\"\\tIterators: %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_itrs) CubDebugExit(g_allocator.DeviceFree(d_itrs));\n}\n\n\n/**\n * Test constant iterator\n */\ntemplate <typename T>\nvoid TestConstant(T base)\n{\n    printf(\"\\nTesting constant iterator on type %s (base: %lld)\\n\", typeid(T).name(), (unsigned long long) (base)); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    T h_reference[8] = {base, base, base, base, base, base, base, base};\n    ConstantInputIterator<T> d_itr(base);\n    Test(d_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    int copy_items  = 100;\n    T   *h_copy     = new T[copy_items];\n    T   *d_copy     = NULL;\n\n    for (int i = 0; i < copy_items; ++i)\n        h_copy[i] = d_itr[i];\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * copy_items));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n\n    thrust::copy_if(d_itr, d_itr + copy_items, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_copy, d_copy, copy_items, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    if (h_copy) delete[] h_copy;\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif // THRUST_VERSION\n}\n\n\n/**\n * Test counting iterator\n */\ntemplate <typename T>\nvoid TestCounting(T base)\n{\n    printf(\"\\nTesting counting iterator on type %s (base: %d) \\n\", typeid(T).name(), int(base)); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = base + 0;          // Value at offset 0\n    h_reference[1] = base + 100;        // Value at offset 100\n    h_reference[2] = base + 1000;       // Value at offset 1000\n    h_reference[3] = base + 10000;      // Value at offset 10000\n    h_reference[4] = base + 1;          // Value at offset 1\n    h_reference[5] = base + 21;         // Value at offset 21\n    h_reference[6] = base + 11;         // Value at offset 11\n    h_reference[7] = base + 0;          // Value at offset 0;\n\n    CountingInputIterator<T> d_itr(base);\n    Test(d_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    unsigned long long  max_items   = ((1ull << ((sizeof(T) * 8) - 1)) - 1);\n    size_t  copy_items              = (size_t) CUB_MIN(max_items - base, 100);     // potential issue with differencing overflows when T is a smaller type than can handle the offset\n    T                   *h_copy     = new T[copy_items];\n    T                   *d_copy     = NULL;\n\n    for (unsigned long long i = 0; i < copy_items; ++i)\n        h_copy[i] = d_itr[i];\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * copy_items));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n    thrust::copy_if(d_itr, d_itr + copy_items, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_copy, d_copy, copy_items, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    if (h_copy) delete[] h_copy;\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif // THRUST_VERSION\n}\n\n\n/**\n * Test modified iterator\n */\ntemplate <typename T, typename CastT>\nvoid TestModified()\n{\n    printf(\"\\nTesting cache-modified iterator on type %s\\n\", typeid(T).name()); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    const unsigned int TEST_VALUES = 11000;\n\n    T *h_data = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n    {\n        RandomBits(h_data[i]);\n    }\n\n    // Allocate device arrays\n    T *d_data = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(T) * TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_data, h_data, sizeof(T) * TEST_VALUES, cudaMemcpyHostToDevice));\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = h_data[0];          // Value at offset 0\n    h_reference[1] = h_data[100];        // Value at offset 100\n    h_reference[2] = h_data[1000];       // Value at offset 1000\n    h_reference[3] = h_data[10000];      // Value at offset 10000\n    h_reference[4] = h_data[1];          // Value at offset 1\n    h_reference[5] = h_data[21];         // Value at offset 21\n    h_reference[6] = h_data[11];         // Value at offset 11\n    h_reference[7] = h_data[0];          // Value at offset 0;\n\n    Test(CacheModifiedInputIterator<LOAD_DEFAULT, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_CA, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_CG, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_CS, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_CV, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_LDG, T>((CastT*) d_data), h_reference);\n    Test(CacheModifiedInputIterator<LOAD_VOLATILE, T>((CastT*) d_data), h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    T *d_copy = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * TEST_VALUES));\n\n    CacheModifiedInputIterator<LOAD_CG, T> d_in_itr((CastT*) d_data);\n    CacheModifiedOutputIterator<STORE_CG, T> d_out_itr((CastT*) d_copy);\n\n    thrust::copy_if(d_in_itr, d_in_itr + TEST_VALUES, d_out_itr, SelectOp());\n\n    int compare = CompareDeviceResults(h_data, d_copy, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif // THRUST_VERSION\n\n    if (h_data) delete[] h_data;\n    if (d_data) CubDebugExit(g_allocator.DeviceFree(d_data));\n}\n\n\n/**\n * Test transform iterator\n */\ntemplate <typename T, typename CastT>\nvoid TestTransform()\n{\n    printf(\"\\nTesting transform iterator on type %s\\n\", typeid(T).name()); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    const unsigned int TEST_VALUES = 11000;\n\n    T *h_data = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n    {\n        InitValue(INTEGER_SEED, h_data[i], i);\n    }\n\n    // Allocate device arrays\n    T *d_data = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(T) * TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_data, h_data, sizeof(T) * TEST_VALUES, cudaMemcpyHostToDevice));\n\n    TransformOp<T> op;\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = op(h_data[0]);          // Value at offset 0\n    h_reference[1] = op(h_data[100]);        // Value at offset 100\n    h_reference[2] = op(h_data[1000]);       // Value at offset 1000\n    h_reference[3] = op(h_data[10000]);      // Value at offset 10000\n    h_reference[4] = op(h_data[1]);          // Value at offset 1\n    h_reference[5] = op(h_data[21]);         // Value at offset 21\n    h_reference[6] = op(h_data[11]);         // Value at offset 11\n    h_reference[7] = op(h_data[0]);          // Value at offset 0;\n\n    TransformInputIterator<T, TransformOp<T>, CastT*> d_itr((CastT*) d_data, op);\n    Test(d_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    T *h_copy = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n        h_copy[i] = op(h_data[i]);\n\n    T *d_copy = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * TEST_VALUES));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n\n    thrust::copy_if(d_itr, d_itr + TEST_VALUES, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_copy, d_copy, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_copy) delete[] h_copy;\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif // THRUST_VERSION\n\n    if (h_data) delete[] h_data;\n    if (d_data) CubDebugExit(g_allocator.DeviceFree(d_data));\n}\n\n\n/**\n * Test tex-obj texture iterator\n */\ntemplate <typename T, typename CastT>\nvoid TestTexObj()\n{\n    printf(\"\\nTesting tex-obj iterator on type %s\\n\", typeid(T).name()); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    const unsigned int TEST_VALUES          = 11000;\n    const unsigned int DUMMY_OFFSET         = 500;\n    const unsigned int DUMMY_TEST_VALUES    = TEST_VALUES - DUMMY_OFFSET;\n\n    T *h_data = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n    {\n        RandomBits(h_data[i]);\n    }\n\n    // Allocate device arrays\n    T *d_data   = NULL;\n    T *d_dummy  = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(T) * TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_data, h_data, sizeof(T) * TEST_VALUES, cudaMemcpyHostToDevice));\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_dummy, sizeof(T) * DUMMY_TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_dummy, h_data + DUMMY_OFFSET, sizeof(T) * DUMMY_TEST_VALUES, cudaMemcpyHostToDevice));\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = h_data[0];          // Value at offset 0\n    h_reference[1] = h_data[100];        // Value at offset 100\n    h_reference[2] = h_data[1000];       // Value at offset 1000\n    h_reference[3] = h_data[10000];      // Value at offset 10000\n    h_reference[4] = h_data[1];          // Value at offset 1\n    h_reference[5] = h_data[21];         // Value at offset 21\n    h_reference[6] = h_data[11];         // Value at offset 11\n    h_reference[7] = h_data[0];          // Value at offset 0;\n\n    // Create and bind obj-based test iterator\n    TexObjInputIterator<T> d_obj_itr;\n    CubDebugExit(d_obj_itr.BindTexture((CastT*) d_data, sizeof(T) * TEST_VALUES));\n\n    Test(d_obj_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    T *d_copy = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * TEST_VALUES));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n\n    CubDebugExit(cudaMemset(d_copy, 0, sizeof(T) * TEST_VALUES));\n    thrust::copy_if(d_obj_itr, d_obj_itr + TEST_VALUES, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_data, d_copy, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    CubDebugExit(d_obj_itr.UnbindTexture());\n\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif  // THRUST_VERSION\n\n    if (h_data) delete[] h_data;\n    if (d_data) CubDebugExit(g_allocator.DeviceFree(d_data));\n    if (d_dummy) CubDebugExit(g_allocator.DeviceFree(d_dummy));\n}\n\n\n#if CUDA_VERSION >= 5050\n\n/**\n * Test tex-ref texture iterator\n */\ntemplate <typename T, typename CastT>\nvoid TestTexRef()\n{\n    printf(\"\\nTesting tex-ref iterator on type %s\\n\", typeid(T).name()); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    const unsigned int TEST_VALUES          = 11000;\n    const unsigned int DUMMY_OFFSET         = 500;\n    const unsigned int DUMMY_TEST_VALUES    = TEST_VALUES - DUMMY_OFFSET;\n\n    T *h_data = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n    {\n        RandomBits(h_data[i]);\n    }\n\n    // Allocate device arrays\n    T *d_data   = NULL;\n    T *d_dummy  = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(T) * TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_data, h_data, sizeof(T) * TEST_VALUES, cudaMemcpyHostToDevice));\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_dummy, sizeof(T) * DUMMY_TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_dummy, h_data + DUMMY_OFFSET, sizeof(T) * DUMMY_TEST_VALUES, cudaMemcpyHostToDevice));\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = h_data[0];          // Value at offset 0\n    h_reference[1] = h_data[100];        // Value at offset 100\n    h_reference[2] = h_data[1000];       // Value at offset 1000\n    h_reference[3] = h_data[10000];      // Value at offset 10000\n    h_reference[4] = h_data[1];          // Value at offset 1\n    h_reference[5] = h_data[21];         // Value at offset 21\n    h_reference[6] = h_data[11];         // Value at offset 11\n    h_reference[7] = h_data[0];          // Value at offset 0;\n\n    // Create and bind ref-based test iterator\n    TexRefInputIterator<T, __LINE__> d_ref_itr;\n    CubDebugExit(d_ref_itr.BindTexture((CastT*) d_data, sizeof(T) * TEST_VALUES));\n\n    // Create and bind dummy iterator of same type to check with interferance\n    TexRefInputIterator<T, __LINE__> d_ref_itr2;\n    CubDebugExit(d_ref_itr2.BindTexture((CastT*) d_dummy, sizeof(T) * DUMMY_TEST_VALUES));\n\n    Test(d_ref_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    T *d_copy = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * TEST_VALUES));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n\n    CubDebugExit(cudaMemset(d_copy, 0, sizeof(T) * TEST_VALUES));\n    thrust::copy_if(d_ref_itr, d_ref_itr + TEST_VALUES, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_data, d_copy, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif  // THRUST_VERSION\n\n    CubDebugExit(d_ref_itr.UnbindTexture());\n    CubDebugExit(d_ref_itr2.UnbindTexture());\n\n    if (h_data) delete[] h_data;\n    if (d_data) CubDebugExit(g_allocator.DeviceFree(d_data));\n    if (d_dummy) CubDebugExit(g_allocator.DeviceFree(d_dummy));\n}\n\n\n/**\n * Test texture transform iterator\n */\ntemplate <typename T, typename CastT>\nvoid TestTexTransform()\n{\n    printf(\"\\nTesting tex-transform iterator on type %s\\n\", typeid(T).name()); fflush(stdout);\n\n    //\n    // Test iterator manipulation in kernel\n    //\n\n    const unsigned int TEST_VALUES = 11000;\n\n    T *h_data = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n    {\n        InitValue(INTEGER_SEED, h_data[i], i);\n    }\n\n    // Allocate device arrays\n    T *d_data = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_data, sizeof(T) * TEST_VALUES));\n    CubDebugExit(cudaMemcpy(d_data, h_data, sizeof(T) * TEST_VALUES, cudaMemcpyHostToDevice));\n\n    TransformOp<T> op;\n\n    // Initialize reference data\n    T h_reference[8];\n    h_reference[0] = op(h_data[0]);          // Value at offset 0\n    h_reference[1] = op(h_data[100]);        // Value at offset 100\n    h_reference[2] = op(h_data[1000]);       // Value at offset 1000\n    h_reference[3] = op(h_data[10000]);      // Value at offset 10000\n    h_reference[4] = op(h_data[1]);          // Value at offset 1\n    h_reference[5] = op(h_data[21]);         // Value at offset 21\n    h_reference[6] = op(h_data[11]);         // Value at offset 11\n    h_reference[7] = op(h_data[0]);          // Value at offset 0;\n\n    // Create and bind texture iterator\n    typedef TexRefInputIterator<T, __LINE__> TextureIterator;\n\n    TextureIterator d_tex_itr;\n    CubDebugExit(d_tex_itr.BindTexture((CastT*) d_data, sizeof(T) * TEST_VALUES));\n\n    // Create transform iterator\n    TransformInputIterator<T, TransformOp<T>, TextureIterator> xform_itr(d_tex_itr, op);\n\n    Test(xform_itr, h_reference);\n\n#if (THRUST_VERSION >= 100700)  // Thrust 1.7 or newer\n\n    //\n    // Test with thrust::copy_if()\n    //\n\n    T *h_copy = new T[TEST_VALUES];\n    for (int i = 0; i < TEST_VALUES; ++i)\n        h_copy[i] = op(h_data[i]);\n\n    T *d_copy = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_copy, sizeof(T) * TEST_VALUES));\n    thrust::device_ptr<T> d_copy_wrapper(d_copy);\n\n    thrust::copy_if(xform_itr, xform_itr + TEST_VALUES, d_copy_wrapper, SelectOp());\n\n    int compare = CompareDeviceResults(h_copy, d_copy, TEST_VALUES, g_verbose, g_verbose);\n    printf(\"\\tthrust::copy_if(): %s\\n\", (compare) ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Cleanup\n    if (h_copy) delete[] h_copy;\n    if (d_copy) CubDebugExit(g_allocator.DeviceFree(d_copy));\n\n#endif  // THRUST_VERSION\n\n    CubDebugExit(d_tex_itr.UnbindTexture());\n    if (h_data) delete[] h_data;\n    if (d_data) CubDebugExit(g_allocator.DeviceFree(d_data));\n}\n\n#endif  // CUDA_VERSION\n\n\n\n\n/**\n * Run non-integer tests\n */\ntemplate <typename T, typename CastT>\nvoid Test(Int2Type<false> is_integer)\n{\n    TestModified<T, CastT>();\n    TestTransform<T, CastT>();\n\n#if CUB_CDP\n    // Test tex-obj iterators if CUDA dynamic parallelism enabled\n    TestTexObj<T, CastT>(type_string);\n#endif  // CUB_CDP\n\n#if CUDA_VERSION >= 5050\n    // Test tex-ref iterators for CUDA 5.5\n    TestTexRef<T, CastT>();\n    TestTexTransform<T, CastT>();\n#endif  // CUDA_VERSION\n}\n\n/**\n * Run integer tests\n */\ntemplate <typename T, typename CastT>\nvoid Test(Int2Type<true> is_integer)\n{\n    TestConstant<T>(0);\n    TestConstant<T>(99);\n\n    TestCounting<T>(0);\n    TestCounting<T>(99);\n\n    // Run non-integer tests\n    Test<T, CastT>(Int2Type<false>());\n}\n\n/**\n * Run tests\n */\ntemplate <typename T>\nvoid Test()\n{\n    enum {\n        IS_INTEGER = (Traits<T>::CATEGORY == SIGNED_INTEGER) || (Traits<T>::CATEGORY == UNSIGNED_INTEGER)\n    };\n\n    // Test non-const type\n    Test<T, T>(Int2Type<IS_INTEGER>());\n\n    // Test non-const type\n    Test<T, const T>(Int2Type<IS_INTEGER>());\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n    // Evaluate different data types\n    Test<char>();\n    Test<short>();\n    Test<int>();\n    Test<long>();\n    Test<long long>();\n    Test<float>();\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        Test<double>();\n\n    Test<char2>();\n    Test<short2>();\n    Test<int2>();\n    Test<long2>();\n    Test<longlong2>();\n    Test<float2>();\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        Test<double2>();\n\n    Test<char3>();\n    Test<short3>();\n    Test<int3>();\n    Test<long3>();\n    Test<longlong3>();\n    Test<float3>();\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        Test<double3>();\n\n    Test<char4>();\n    Test<short4>();\n    Test<int4>();\n    Test<long4>();\n    Test<longlong4>();\n    Test<float4>();\n    if (ptx_version > 120)                          // Don't check doubles on PTX120 or below because they're down-converted\n        Test<double4>();\n\n    Test<TestFoo>();\n    Test<TestBar>();\n\n    printf(\"\\nTest complete\\n\"); fflush(stdout);\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_util.h",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n * \n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n * \n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n\n#pragma once\n\n#if defined(_WIN32) || defined(_WIN64)\n    #include <windows.h>\n    #undef small            // Windows is terrible for polluting macro namespace\n#else\n    #include <sys/resource.h>\n#endif\n\n#include <cuda_runtime.h>\n\n#include <stdio.h>\n#include <math.h>\n#include <float.h>\n\n#include <string>\n#include <vector>\n#include <sstream>\n#include <iostream>\n#include <limits>\n\n#include \"mersenne.h\"\n\n#include \"cub/util_debug.cuh\"\n#include \"cub/util_device.cuh\"\n#include \"cub/util_type.cuh\"\n#include \"cub/util_macro.cuh\"\n\n/******************************************************************************\n * Assertion macros\n ******************************************************************************/\n\n/**\n * Assert equals\n */\n#define AssertEquals(a, b) if ((a) != (b)) { std::cerr << \"\\n(\" << __FILE__ << \": \" << __LINE__ << \")\\n\"; exit(1);}\n\n\n/******************************************************************************\n * Command-line parsing functionality\n ******************************************************************************/\n\n/**\n * Utility for parsing command line arguments\n */\nstruct CommandLineArgs\n{\n\n    std::vector<std::string>    keys;\n    std::vector<std::string>    values;\n    std::vector<std::string>    args;\n    cudaDeviceProp              deviceProp;\n    float                       device_giga_bandwidth;\n    size_t                      device_free_physmem;\n    size_t                      device_total_physmem;\n\n    /**\n     * Constructor\n     */\n    CommandLineArgs(int argc, char **argv) :\n        keys(10),\n        values(10)\n    {\n        using namespace std;\n\n        // Initialize mersenne generator\n        unsigned int mersenne_init[4]=  {0x123, 0x234, 0x345, 0x456};\n        mersenne::init_by_array(mersenne_init, 4);\n\n        for (int i = 1; i < argc; i++)\n        {\n            string arg = argv[i];\n\n            if ((arg[0] != '-') || (arg[1] != '-'))\n            {\n                args.push_back(arg);\n                continue;\n            }\n\n            string::size_type pos;\n            string key, val;\n            if ((pos = arg.find('=')) == string::npos) {\n                key = string(arg, 2, arg.length() - 2);\n                val = \"\";\n            } else {\n                key = string(arg, 2, pos - 2);\n                val = string(arg, pos + 1, arg.length() - 1);\n            }\n\n            keys.push_back(key);\n            values.push_back(val);\n        }\n    }\n\n\n    /**\n     * Checks whether a flag \"--<flag>\" is present in the commandline\n     */\n    bool CheckCmdLineFlag(const char* arg_name)\n    {\n        using namespace std;\n\n        for (int i = 0; i < int(keys.size()); ++i)\n        {\n            if (keys[i] == string(arg_name))\n                return true;\n        }\n        return false;\n    }\n\n\n    /**\n     * Returns number of naked (non-flag and non-key-value) commandline parameters\n     */\n    template <typename T>\n    int NumNakedArgs()\n    {\n        return args.size();\n    }\n\n\n    /**\n     * Returns the commandline parameter for a given index (not including flags)\n     */\n    template <typename T>\n    void GetCmdLineArgument(int index, T &val)\n    {\n        using namespace std;\n        if (index < args.size()) {\n            istringstream str_stream(args[index]);\n            str_stream >> val;\n        }\n    }\n\n    /**\n     * Returns the value specified for a given commandline parameter --<flag>=<value>\n     */\n    template <typename T>\n    void GetCmdLineArgument(const char *arg_name, T &val)\n    {\n        using namespace std;\n\n        for (int i = 0; i < int(keys.size()); ++i)\n        {\n            if (keys[i] == string(arg_name))\n            {\n                istringstream str_stream(values[i]);\n                str_stream >> val;\n            }\n        }\n    }\n\n\n    /**\n     * Returns the values specified for a given commandline parameter --<flag>=<value>,<value>*\n     */\n    template <typename T>\n    void GetCmdLineArguments(const char *arg_name, std::vector<T> &vals)\n    {\n        using namespace std;\n\n        if (CheckCmdLineFlag(arg_name))\n        {\n            // Clear any default values\n            vals.clear();\n\n            // Recover from multi-value string\n            for (int i = 0; i < keys.size(); ++i)\n            {\n                if (keys[i] == string(arg_name))\n                {\n                    string val_string(values[i]);\n                    istringstream str_stream(val_string);\n                    string::size_type old_pos = 0;\n                    string::size_type new_pos = 0;\n\n                    // Iterate comma-separated values\n                    T val;\n                    while ((new_pos = val_string.find(',', old_pos)) != string::npos)\n                    {\n                        if (new_pos != old_pos)\n                        {\n                            str_stream.width(new_pos - old_pos);\n                            str_stream >> val;\n                            vals.push_back(val);\n                        }\n\n                        // skip over comma\n                        str_stream.ignore(1);\n                        old_pos = new_pos + 1;\n                    }\n\n                    // Read last value\n                    str_stream >> val;\n                    vals.push_back(val);\n                }\n            }\n        }\n    }\n\n\n    /**\n     * The number of pairs parsed\n     */\n    int ParsedArgc()\n    {\n        return (int) keys.size();\n    }\n\n    /**\n     * Initialize device\n     */\n    cudaError_t DeviceInit(int dev = -1)\n    {\n        cudaError_t error = cudaSuccess;\n\n        do\n        {\n            int deviceCount;\n            error = CubDebug(cudaGetDeviceCount(&deviceCount));\n            if (error) break;\n\n            if (deviceCount == 0) {\n                fprintf(stderr, \"No devices supporting CUDA.\\n\");\n                exit(1);\n            }\n            if (dev < 0)\n            {\n                GetCmdLineArgument(\"device\", dev);\n            }\n            if ((dev > deviceCount - 1) || (dev < 0))\n            {\n                dev = 0;\n            }\n\n            error = CubDebug(cudaSetDevice(dev));\n            if (error) break;\n\n            CubDebugExit(cudaMemGetInfo(&device_free_physmem, &device_total_physmem));\n\n            int ptx_version;\n            error = CubDebug(cub::PtxVersion(ptx_version));\n            if (error) break;\n\n            error = CubDebug(cudaGetDeviceProperties(&deviceProp, dev));\n            if (error) break;\n\n            if (deviceProp.major < 1) {\n                fprintf(stderr, \"Device does not support CUDA.\\n\");\n                exit(1);\n            }\n\n            device_giga_bandwidth = float(deviceProp.memoryBusWidth) * deviceProp.memoryClockRate * 2 / 8 / 1000 / 1000;\n\n            if (!CheckCmdLineFlag(\"quiet\"))\n            {\n                printf(\n                        \"Using device %d: %s (PTX version %d, SM%d, %d SMs, \"\n                        \"%lld free / %lld total MB physmem, \"\n                        \"%.3f GB/s @ %d kHz mem clock, ECC %s)\\n\",\n                    dev,\n                    deviceProp.name,\n                    ptx_version,\n                    deviceProp.major * 100 + deviceProp.minor * 10,\n                    deviceProp.multiProcessorCount,\n                    (unsigned long long) device_free_physmem / 1024 / 1024,\n                    (unsigned long long) device_total_physmem / 1024 / 1024,\n                    device_giga_bandwidth,\n                    deviceProp.memoryClockRate,\n                    (deviceProp.ECCEnabled) ? \"on\" : \"off\");\n                fflush(stdout);\n            }\n\n        } while (0);\n\n        return error;\n    }\n};\n\n/******************************************************************************\n * Random bits generator\n ******************************************************************************/\n\nint g_num_rand_samples = 0;\n\n\ntemplate <typename T>\nbool IsNaN(T val) { return false; }\n\ntemplate<>\n__noinline__ bool IsNaN<float>(float val)\n{\n    volatile unsigned int bits = reinterpret_cast<unsigned int &>(val);\n\n    return (((bits >= 0x7F800001) && (bits <= 0x7FFFFFFF)) || \n        ((bits >= 0xFF800001) && (bits <= 0xFFFFFFFF)));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<float1>(float1 val)\n{\n    return (IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<float2>(float2 val)\n{\n    return (IsNaN(val.y) || IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<float3>(float3 val)\n{\n    return (IsNaN(val.z) || IsNaN(val.y) || IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<float4>(float4 val)\n{\n    return (IsNaN(val.y) || IsNaN(val.x) || IsNaN(val.w) || IsNaN(val.z));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<double>(double val)\n{\n    volatile unsigned long long bits = *reinterpret_cast<unsigned long long *>(&val);\n\n    return (((bits >= 0x7FF0000000000001) && (bits <= 0x7FFFFFFFFFFFFFFF)) || \n        ((bits >= 0xFFF0000000000001) && (bits <= 0xFFFFFFFFFFFFFFFF)));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<double1>(double1 val)\n{\n    return (IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<double2>(double2 val)\n{\n    return (IsNaN(val.y) || IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<double3>(double3 val)\n{\n    return (IsNaN(val.z) || IsNaN(val.y) || IsNaN(val.x));\n}\n\ntemplate<>\n__noinline__ bool IsNaN<double4>(double4 val)\n{\n    return (IsNaN(val.y) || IsNaN(val.x) || IsNaN(val.w) || IsNaN(val.z));\n}\n\n\n/**\n * Generates random keys.\n *\n * We always take the second-order byte from rand() because the higher-order\n * bits returned by rand() are commonly considered more uniformly distributed\n * than the lower-order bits.\n *\n * We can decrease the entropy level of keys by adopting the technique\n * of Thearling and Smith in which keys are computed from the bitwise AND of\n * multiple random samples:\n *\n * entropy_reduction    | Effectively-unique bits per key\n * -----------------------------------------------------\n * -1                   | 0\n * 0                    | 32\n * 1                    | 25.95 (81%)\n * 2                    | 17.41 (54%)\n * 3                    | 10.78 (34%)\n * 4                    | 6.42 (20%)\n * ...                  | ...\n *\n */\ntemplate <typename K>\nvoid RandomBits(\n    K &key,\n    int entropy_reduction = 0,\n    int begin_bit = 0,\n    int end_bit = sizeof(K) * 8)\n{\n    const int NUM_BYTES = sizeof(K);\n    const int WORD_BYTES = sizeof(unsigned int);\n    const int NUM_WORDS = (NUM_BYTES + WORD_BYTES - 1) / WORD_BYTES;\n\n    unsigned int word_buff[NUM_WORDS];\n\n    if (entropy_reduction == -1)\n    {\n        memset((void *) &key, 0, sizeof(key));\n        return;\n    }\n\n    if (end_bit < 0)\n        end_bit = sizeof(K) * 8;\n\n    while (true) \n    {\n        // Generate random word_buff\n        for (int j = 0; j < NUM_WORDS; j++)\n        {\n            int current_bit = j * WORD_BYTES * 8;\n\n            unsigned int word = 0xffffffff;\n            word &= 0xffffffff << CUB_MAX(0, begin_bit - current_bit);\n            word &= 0xffffffff >> CUB_MAX(0, (current_bit + (WORD_BYTES * 8)) - end_bit);\n\n            for (int i = 0; i <= entropy_reduction; i++)\n            {\n                // Grab some of the higher bits from rand (better entropy, supposedly)\n                word &= mersenne::genrand_int32();\n                g_num_rand_samples++;                \n            }\n\n            word_buff[j] = word;\n        }\n\n        memcpy(&key, word_buff, sizeof(K));\n\n        K copy = key;\n        if (!IsNaN(copy))\n            break;          // avoids NaNs when generating random floating point numbers\n    }\n}\n\n/// Randomly select number between [0:max)\ntemplate <typename T>\nT RandomValue(T max)\n{\n    unsigned int bits;\n    unsigned int max_int = (unsigned int) -1;\n    do {\n        RandomBits(bits);\n    } while (bits == max_int);\n\n    return (T) ((double(bits) / double(max_int)) * double(max));\n}\n\n\n/******************************************************************************\n * Console printing utilities\n ******************************************************************************/\n\n/**\n * Helper for casting character types to integers for cout printing\n */\ntemplate <typename T>\nT CoutCast(T val) { return val; }\n\nint CoutCast(char val) { return val; }\n\nint CoutCast(unsigned char val) { return val; }\n\nint CoutCast(signed char val) { return val; }\n\n\n\n/******************************************************************************\n * Test value initialization utilities\n ******************************************************************************/\n\n/**\n * Test problem generation options\n */\nenum GenMode\n{\n    UNIFORM,            // Assign to '2', regardless of integer seed\n    INTEGER_SEED,       // Assign to integer seed\n    RANDOM,             // Assign to random, regardless of integer seed\n};\n\n/**\n * Initialize value\n */\ntemplate <typename T>\n__host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, T &value, int index = 0)\n{\n    switch (gen_mode)\n    {\n#if (CUB_PTX_ARCH == 0)\n    case RANDOM:\n         RandomBits(value);\n         break;\n#endif\n     case UNIFORM:\n        value = 2;\n        break;\n    case INTEGER_SEED:\n    default:\n         value = (T) index;\n        break;\n    }\n}\n\n\n/**\n * Initialize value (bool)\n */\n__host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, bool &value, int index = 0)\n{\n    switch (gen_mode)\n    {\n#if (CUB_PTX_ARCH == 0)\n    case RANDOM:\n        char c;\n        RandomBits(c, 0, 0, 1);\n        value = (c > 0);\n        break;\n#endif\n     case UNIFORM:\n        value = true;\n        break;\n    case INTEGER_SEED:\n    default:\n        value = (index > 0);\n        break;\n    }\n}\n\n\n/**\n * cub::NullType test initialization\n */\n__host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, cub::NullType &value, int index = 0)\n{}\n\n\n/**\n * cub::KeyValuePair<OffsetT, ValueT>test initialization\n */\ntemplate <typename KeyT, typename ValueT>\n__host__ __device__ __forceinline__ void InitValue(\n    GenMode                             gen_mode,\n    cub::KeyValuePair<KeyT, ValueT>&    value,\n    int                                 index = 0)\n{\n    InitValue(gen_mode, value.value, index);\n\n    // Assign corresponding flag with a likelihood of the last bit being set with entropy-reduction level 3\n    RandomBits(value.key, 3);\n    value.key = (value.key & 0x1);\n}\n\n\n\n/******************************************************************************\n * Comparison and ostream operators\n ******************************************************************************/\n\n/**\n * KeyValuePair ostream operator\n */\ntemplate <typename Key, typename Value>\nstd::ostream& operator<<(std::ostream& os, const cub::KeyValuePair<Key, Value> &val)\n{\n    os << '(' << CoutCast(val.key) << ',' << CoutCast(val.value) << ')';\n    return os;\n}\n\n\n/******************************************************************************\n * Comparison and ostream operators for CUDA vector types\n ******************************************************************************/\n\n/**\n * Vector1 overloads\n */\n#define CUB_VEC_OVERLOAD_1(T, BaseT)                        \\\n    /* Ostream output */                                    \\\n    std::ostream& operator<<(                               \\\n        std::ostream& os,                                   \\\n        const T& val)                                       \\\n    {                                                       \\\n        os << '(' << CoutCast(val.x) << ')';                \\\n        return os;                                          \\\n    }                                                       \\\n    /* Inequality */                                        \\\n    __host__ __device__ __forceinline__ bool operator!=(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x != b.x);                                \\\n    }                                                       \\\n    /* Equality */                                          \\\n    __host__ __device__ __forceinline__ bool operator==(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x == b.x);                                \\\n    }                                                       \\\n    /* Test initialization */                               \\\n    __host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, T &value, int index = 0)   \\\n    {                                                       \\\n        InitValue(gen_mode, value.x, index);                \\\n    }                                                       \\\n    /* Max */                                               \\\n    __host__ __device__ __forceinline__ bool operator>(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x > b.x);                                 \\\n    }                                                       \\\n    /* Min */                                               \\\n    __host__ __device__ __forceinline__ bool operator<(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x < b.x);                                 \\\n    }                                                       \\\n    /* Summation (non-reference addends for VS2003 -O3 warpscan workaround */                       \\\n    __host__ __device__ __forceinline__ T operator+(        \\\n        T a,                                                \\\n        T b)                                                \\\n    {                                                       \\\n        T retval = make_##T(a.x + b.x);                     \\\n        return retval;                                      \\\n    }                                                       \\\n    namespace cub {                                         \\\n    template<>                                              \\\n    struct NumericTraits<T>                                 \\\n    {                                                       \\\n        static const Category CATEGORY = NOT_A_NUMBER;      \\\n        enum {                                              \\\n            PRIMITIVE       = false,                        \\\n            NULL_TYPE       = false,                        \\\n        };                                                  \\\n        static T Max()                                      \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Max()};               \\\n            return retval;                                  \\\n        }                                                   \\\n        static T Lowest()                                   \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Lowest()};            \\\n            return retval;                                  \\\n        }                                                   \\\n    };                                                      \\\n    } /* namespace std */\n\n\n\n/**\n * Vector2 overloads\n */\n#define CUB_VEC_OVERLOAD_2(T, BaseT)                        \\\n    /* Ostream output */                                    \\\n    std::ostream& operator<<(                               \\\n        std::ostream& os,                                   \\\n        const T& val)                                       \\\n    {                                                       \\\n        os << '('                                           \\\n            << CoutCast(val.x) << ','                       \\\n            << CoutCast(val.y) << ')';                      \\\n        return os;                                          \\\n    }                                                       \\\n    /* Inequality */                                        \\\n    __host__ __device__ __forceinline__ bool operator!=(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x != b.x) ||                              \\\n            (a.y != b.y);                                   \\\n    }                                                       \\\n    /* Equality */                                          \\\n    __host__ __device__ __forceinline__ bool operator==(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x == b.x) &&                              \\\n            (a.y == b.y);                                   \\\n    }                                                       \\\n    /* Test initialization */                               \\\n    __host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, T &value, int index = 0)   \\\n    {                                                       \\\n        InitValue(gen_mode, value.x, index);                \\\n        InitValue(gen_mode, value.y, index);                \\\n    }                                                       \\\n    /* Max */                                               \\\n    __host__ __device__ __forceinline__ bool operator>(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x > b.x) return true; else if (b.x > a.x) return false;   \\\n        return a.y > b.y;                                               \\\n    }                                                       \\\n    /* Min */                                               \\\n    __host__ __device__ __forceinline__ bool operator<(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x < b.x) return true; else if (b.x < a.x) return false;   \\\n        return a.y < b.y;                                               \\\n    }                                                       \\\n    /* Summation (non-reference addends for VS2003 -O3 warpscan workaround */                                         \\\n    __host__ __device__ __forceinline__ T operator+(        \\\n        T a,                                         \\\n        T b)                                         \\\n    {                                                       \\\n        T retval = make_##T(                                        \\\n            a.x + b.x,                                      \\\n            a.y + b.y);                                     \\\n        return retval;                                      \\\n    }                                                       \\\n    namespace cub {                                         \\\n    template<>                                              \\\n    struct NumericTraits<T>                                 \\\n    {                                                       \\\n        static const Category CATEGORY = NOT_A_NUMBER;      \\\n        enum {                                              \\\n            PRIMITIVE       = false,                        \\\n            NULL_TYPE       = false,                        \\\n        };                                                  \\\n        static T Max()                                      \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max()};               \\\n            return retval;                                  \\\n        }                                                   \\\n        static T Lowest()                                   \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest()};            \\\n            return retval;                                  \\\n        }                                                   \\\n    };                                                      \\\n    } /* namespace cub */\n\n\n\n/**\n * Vector3 overloads\n */\n#define CUB_VEC_OVERLOAD_3(T, BaseT)                        \\\n    /* Ostream output */                                    \\\n    std::ostream& operator<<(                               \\\n        std::ostream& os,                                   \\\n        const T& val)                                       \\\n    {                                                       \\\n        os << '('                                           \\\n            << CoutCast(val.x) << ','                       \\\n            << CoutCast(val.y) << ','                       \\\n            << CoutCast(val.z) << ')';                      \\\n        return os;                                          \\\n    }                                                       \\\n    /* Inequality */                                        \\\n    __host__ __device__ __forceinline__ bool operator!=(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x != b.x) ||                              \\\n            (a.y != b.y) ||                                 \\\n            (a.z != b.z);                                   \\\n    }                                                       \\\n    /* Equality */                                          \\\n    __host__ __device__ __forceinline__ bool operator==(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x == b.x) &&                              \\\n            (a.y == b.y) &&                                 \\\n            (a.z == b.z);                                   \\\n    }                                                       \\\n    /* Test initialization */                               \\\n    __host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, T &value, int index = 0)   \\\n    {                                                       \\\n        InitValue(gen_mode, value.x, index);                \\\n        InitValue(gen_mode, value.y, index);                \\\n        InitValue(gen_mode, value.z, index);                \\\n    }                                                       \\\n    /* Max */                                               \\\n    __host__ __device__ __forceinline__ bool operator>(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x > b.x) return true; else if (b.x > a.x) return false;   \\\n        if (a.y > b.y) return true; else if (b.y > a.y) return false;   \\\n        return a.z > b.z;                                               \\\n    }                                                       \\\n    /* Min */                                               \\\n    __host__ __device__ __forceinline__ bool operator<(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x < b.x) return true; else if (b.x < a.x) return false;   \\\n        if (a.y < b.y) return true; else if (b.y < a.y) return false;   \\\n        return a.z < b.z;                                               \\\n    }                                                       \\\n    /* Summation (non-reference addends for VS2003 -O3 warpscan workaround */                                         \\\n    __host__ __device__ __forceinline__ T operator+(        \\\n        T a,                                                \\\n        T b)                                                \\\n    {                                                       \\\n        T retval = make_##T(                                        \\\n            a.x + b.x,                                      \\\n            a.y + b.y,                                      \\\n            a.z + b.z);                                     \\\n        return retval;                                      \\\n    }                                                       \\\n    namespace cub {                                         \\\n    template<>                                              \\\n    struct NumericTraits<T>                                 \\\n    {                                                       \\\n        static const Category CATEGORY = NOT_A_NUMBER;      \\\n        enum {                                              \\\n            PRIMITIVE       = false,                        \\\n            NULL_TYPE       = false,                        \\\n        };                                                  \\\n        static T Max()                                      \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max()};               \\\n            return retval;                                  \\\n        }                                                   \\\n        static T Lowest()                                   \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest()};            \\\n            return retval;                                  \\\n        }                                                   \\\n    };                                                      \\\n    } /* namespace cub */\n\n\n/**\n * Vector4 overloads\n */\n#define CUB_VEC_OVERLOAD_4(T, BaseT)                        \\\n    /* Ostream output */                                    \\\n    std::ostream& operator<<(                               \\\n        std::ostream& os,                                   \\\n        const T& val)                                       \\\n    {                                                       \\\n        os << '('                                           \\\n            << CoutCast(val.x) << ','                       \\\n            << CoutCast(val.y) << ','                       \\\n            << CoutCast(val.z) << ','                       \\\n            << CoutCast(val.w) << ')';                      \\\n        return os;                                          \\\n    }                                                       \\\n    /* Inequality */                                        \\\n    __host__ __device__ __forceinline__ bool operator!=(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x != b.x) ||                              \\\n            (a.y != b.y) ||                                 \\\n            (a.z != b.z) ||                                 \\\n            (a.w != b.w);                                   \\\n    }                                                       \\\n    /* Equality */                                          \\\n    __host__ __device__ __forceinline__ bool operator==(    \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        return (a.x == b.x) &&                              \\\n            (a.y == b.y) &&                                 \\\n            (a.z == b.z) &&                                 \\\n            (a.w == b.w);                                   \\\n    }                                                       \\\n    /* Test initialization */                               \\\n    __host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, T &value, int index = 0)   \\\n    {                                                       \\\n        InitValue(gen_mode, value.x, index);                \\\n        InitValue(gen_mode, value.y, index);                \\\n        InitValue(gen_mode, value.z, index);                \\\n        InitValue(gen_mode, value.w, index);                \\\n    }                                                       \\\n    /* Max */                                               \\\n    __host__ __device__ __forceinline__ bool operator>(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x > b.x) return true; else if (b.x > a.x) return false;   \\\n        if (a.y > b.y) return true; else if (b.y > a.y) return false;   \\\n        if (a.z > b.z) return true; else if (b.z > a.z) return false;   \\\n        return a.w > b.w;                                               \\\n    }                                                       \\\n    /* Min */                                               \\\n    __host__ __device__ __forceinline__ bool operator<(     \\\n        const T &a,                                         \\\n        const T &b)                                         \\\n    {                                                       \\\n        if (a.x < b.x) return true; else if (b.x < a.x) return false;   \\\n        if (a.y < b.y) return true; else if (b.y < a.y) return false;   \\\n        if (a.z < b.z) return true; else if (b.z < a.z) return false;   \\\n        return a.w < b.w;                                               \\\n    }                                                       \\\n    /* Summation (non-reference addends for VS2003 -O3 warpscan workaround */                                         \\\n    __host__ __device__ __forceinline__ T operator+(        \\\n        T a,                                                \\\n        T b)                                                \\\n    {                                                       \\\n        T retval = make_##T(                                        \\\n            a.x + b.x,                                      \\\n            a.y + b.y,                                      \\\n            a.z + b.z,                                      \\\n            a.w + b.w);                                     \\\n        return retval;                                      \\\n    }                                                       \\\n    namespace cub {                                         \\\n    template<>                                              \\\n    struct NumericTraits<T>                                 \\\n    {                                                       \\\n        static const Category CATEGORY = NOT_A_NUMBER;      \\\n        enum {                                              \\\n            PRIMITIVE       = false,                        \\\n            NULL_TYPE       = false,                        \\\n        };                                                  \\\n        static T Max()                                      \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max(),                \\\n                NumericTraits<BaseT>::Max()};               \\\n            return retval;                                  \\\n        }                                                   \\\n        static T Lowest()                                   \\\n        {                                                   \\\n            T retval = {                                    \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest(),             \\\n                NumericTraits<BaseT>::Lowest()};            \\\n            return retval;                                  \\\n        }                                                   \\\n    };                                                      \\\n    } /* namespace cub */\n\n/**\n * All vector overloads\n */\n#define CUB_VEC_OVERLOAD(COMPONENT_T, BaseT)                    \\\n    CUB_VEC_OVERLOAD_1(COMPONENT_T##1, BaseT)                   \\\n    CUB_VEC_OVERLOAD_2(COMPONENT_T##2, BaseT)                   \\\n    CUB_VEC_OVERLOAD_3(COMPONENT_T##3, BaseT)                   \\\n    CUB_VEC_OVERLOAD_4(COMPONENT_T##4, BaseT)\n\n/**\n * Define for types\n */\nCUB_VEC_OVERLOAD(char, char)\nCUB_VEC_OVERLOAD(short, short)\nCUB_VEC_OVERLOAD(int, int)\nCUB_VEC_OVERLOAD(long, long)\nCUB_VEC_OVERLOAD(longlong, long long)\nCUB_VEC_OVERLOAD(uchar, unsigned char)\nCUB_VEC_OVERLOAD(ushort, unsigned short)\nCUB_VEC_OVERLOAD(uint, unsigned int)\nCUB_VEC_OVERLOAD(ulong, unsigned long)\nCUB_VEC_OVERLOAD(ulonglong, unsigned long long)\nCUB_VEC_OVERLOAD(float, float)\nCUB_VEC_OVERLOAD(double, double)\n\n\n//---------------------------------------------------------------------\n// Complex data type TestFoo\n//---------------------------------------------------------------------\n\n/**\n * TestFoo complex data type\n */\nstruct TestFoo\n{\n    long long   x;\n    int         y;\n    short       z;\n    char        w;\n\n    // Factory\n    static __host__ __device__ __forceinline__ TestFoo MakeTestFoo(long long x, int y, short z, char w)\n    {\n        TestFoo retval = {x, y, z, w};\n        return retval;\n    }\n\n    // Assignment from int operator\n    __host__ __device__ __forceinline__ TestFoo& operator =(int b)\n    {\n        x = b;\n        y = b;\n        z = b;\n        w = b;\n        return *this;\n    }\n\n    // Summation operator\n    __host__ __device__ __forceinline__ TestFoo operator+(const TestFoo &b) const\n    {\n        return MakeTestFoo(x + b.x, y + b.y, z + b.z, w + b.w);\n    }\n\n    // Inequality operator\n    __host__ __device__ __forceinline__ bool operator !=(const TestFoo &b) const\n    {\n        return (x != b.x) || (y != b.y) || (z != b.z) || (w != b.w);\n    }\n\n    // Equality operator\n    __host__ __device__ __forceinline__ bool operator ==(const TestFoo &b) const\n    {\n        return (x == b.x) && (y == b.y) && (z == b.z) && (w == b.w);\n    }\n\n    // Less than operator\n    __host__ __device__ __forceinline__ bool operator <(const TestFoo &b) const\n    {\n        if (x < b.x) return true; else if (b.x < x) return false;\n        if (y < b.y) return true; else if (b.y < y) return false;\n        if (z < b.z) return true; else if (b.z < z) return false;\n        return w < b.w;\n    }\n\n    // Greater than operator\n    __host__ __device__ __forceinline__ bool operator >(const TestFoo &b) const\n    {\n        if (x > b.x) return true; else if (b.x > x) return false;\n        if (y > b.y) return true; else if (b.y > y) return false;\n        if (z > b.z) return true; else if (b.z > z) return false;\n        return w > b.w;\n    }\n\n};\n\n/**\n * TestFoo ostream operator\n */\nstd::ostream& operator<<(std::ostream& os, const TestFoo& val)\n{\n    os << '(' << val.x << ',' << val.y << ',' << val.z << ',' << CoutCast(val.w) << ')';\n    return os;\n}\n\n/**\n * TestFoo test initialization\n */\n__host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, TestFoo &value, int index = 0)\n{\n    InitValue(gen_mode, value.x, index);\n    InitValue(gen_mode, value.y, index);\n    InitValue(gen_mode, value.z, index);\n    InitValue(gen_mode, value.w, index);\n}\n\n\n/// numeric_limits<TestFoo> specialization\nnamespace cub {\ntemplate<>\nstruct NumericTraits<TestFoo>\n{\n    static const Category CATEGORY = NOT_A_NUMBER;\n    enum {\n        PRIMITIVE       = false,\n        NULL_TYPE       = false,\n    };\n    static TestFoo Max()\n    {\n        return TestFoo::MakeTestFoo(\n            NumericTraits<long long>::Max(),\n            NumericTraits<int>::Max(),\n            NumericTraits<short>::Max(),\n            NumericTraits<char>::Max());\n    }\n\n    static TestFoo Lowest()\n    {\n        return TestFoo::MakeTestFoo(\n            NumericTraits<long long>::Lowest(),\n            NumericTraits<int>::Lowest(),\n            NumericTraits<short>::Lowest(),\n            NumericTraits<char>::Lowest());\n    }\n};\n} // namespace cub\n\n\n//---------------------------------------------------------------------\n// Complex data type TestBar (with optimizations for fence-free warp-synchrony)\n//---------------------------------------------------------------------\n\n/**\n * TestBar complex data type\n */\nstruct TestBar\n{\n    long long       x;\n    int             y;\n\n    // Constructor\n    __host__ __device__ __forceinline__ TestBar() : x(0), y(0)\n    {}\n\n    // Constructor\n    __host__ __device__ __forceinline__ TestBar(int b) : x(b), y(b)\n    {}\n\n    // Constructor\n    __host__ __device__ __forceinline__ TestBar(long long x, int y) : x(x), y(y)\n    {}\n\n    // Assignment from int operator\n    __host__ __device__ __forceinline__ TestBar& operator =(int b)\n    {\n        x = b;\n        y = b;\n        return *this;\n    }\n\n    // Summation operator\n    __host__ __device__ __forceinline__ TestBar operator+(const TestBar &b) const\n    {\n        return TestBar(x + b.x, y + b.y);\n    }\n\n    // Inequality operator\n    __host__ __device__ __forceinline__ bool operator !=(const TestBar &b) const\n    {\n        return (x != b.x) || (y != b.y);\n    }\n\n    // Equality operator\n    __host__ __device__ __forceinline__ bool operator ==(const TestBar &b) const\n    {\n        return (x == b.x) && (y == b.y);\n    }\n\n    // Less than operator\n    __host__ __device__ __forceinline__ bool operator <(const TestBar &b) const\n    {\n        if (x < b.x) return true; else if (b.x < x) return false;\n        return y < b.y;\n    }\n\n    // Greater than operator\n    __host__ __device__ __forceinline__ bool operator >(const TestBar &b) const\n    {\n        if (x > b.x) return true; else if (b.x > x) return false;\n        return y > b.y;\n    }\n\n};\n\n\n/**\n * TestBar ostream operator\n */\nstd::ostream& operator<<(std::ostream& os, const TestBar& val)\n{\n    os << '(' << val.x << ',' << val.y << ')';\n    return os;\n}\n\n/**\n * TestBar test initialization\n */\n__host__ __device__ __forceinline__ void InitValue(GenMode gen_mode, TestBar &value, int index = 0)\n{\n    InitValue(gen_mode, value.x, index);\n    InitValue(gen_mode, value.y, index);\n}\n\n/// numeric_limits<TestBar> specialization\nnamespace cub {\ntemplate<>\nstruct NumericTraits<TestBar>\n{\n    static const Category CATEGORY = NOT_A_NUMBER;\n    enum {\n        PRIMITIVE       = false,\n        NULL_TYPE       = false,\n    };\n    static TestBar Max()\n    {\n        return TestBar(\n            NumericTraits<long long>::Max(),\n            NumericTraits<int>::Max());\n    }\n\n    static TestBar Lowest()\n    {\n        return TestBar(\n            NumericTraits<long long>::Lowest(),\n            NumericTraits<int>::Lowest());\n    }\n};\n} // namespace cub\n\n\n/******************************************************************************\n * Helper routines for list comparison and display\n ******************************************************************************/\n\n\n/**\n * Compares the equivalence of two arrays\n */\ntemplate <typename S, typename T, typename OffsetT>\nint CompareResults(T* computed, S* reference, OffsetT len, bool verbose = true)\n{\n    for (OffsetT i = 0; i < len; i++)\n    {\n        if (computed[i] != reference[i])\n        {\n            if (verbose) std::cout << \"INCORRECT: [\" << i << \"]: \"\n                << CoutCast(computed[i]) << \" != \"\n                << CoutCast(reference[i]);\n            return 1;\n        }\n    }\n    return 0;\n}\n\n\n/**\n * Compares the equivalence of two arrays\n */\ntemplate <typename OffsetT>\nint CompareResults(float* computed, float* reference, OffsetT len, bool verbose = true)\n{\n    for (OffsetT i = 0; i < len; i++)\n    {\n        if (computed[i] != reference[i])\n        {\n            float difference = std::abs(computed[i]-reference[i]);\n            float fraction = difference / std::abs(reference[i]);\n\n            if (fraction > 0.0001)\n            {\n                if (verbose) std::cout << \"INCORRECT: [\" << i << \"]: \"\n                    << \"(computed) \" << CoutCast(computed[i]) << \" != \"\n                    << CoutCast(reference[i]) << \" (difference:\" << difference << \", fraction: \" << fraction << \")\";\n                return 1;\n            }\n        }\n    }\n    return 0;\n}\n\n\n/**\n * Compares the equivalence of two arrays\n */\ntemplate <typename OffsetT>\nint CompareResults(cub::NullType* computed, cub::NullType* reference, OffsetT len, bool verbose = true)\n{\n    return 0;\n}\n\n/**\n * Compares the equivalence of two arrays\n */\ntemplate <typename OffsetT>\nint CompareResults(double* computed, double* reference, OffsetT len, bool verbose = true)\n{\n    for (OffsetT i = 0; i < len; i++)\n    {\n        if (computed[i] != reference[i])\n        {\n            double difference = std::abs(computed[i]-reference[i]);\n            double fraction = difference / std::abs(reference[i]);\n\n            if (fraction > 0.0001)\n            {\n                if (verbose) std::cout << \"INCORRECT: [\" << i << \"]: \"\n                    << CoutCast(computed[i]) << \" != \"\n                    << CoutCast(reference[i]) << \" (difference:\" << difference << \", fraction: \" << fraction << \")\";\n                return 1;\n            }\n        }\n    }\n    return 0;\n}\n\n\n/**\n * Verify the contents of a device array match those\n * of a host array\n */\nint CompareDeviceResults(\n    cub::NullType *h_reference,\n    cub::NullType *d_data,\n    size_t num_items,\n    bool verbose = true,\n    bool display_data = false)\n{\n    return 0;\n}\n\n\n/**\n * Verify the contents of a device array match those\n * of a host array\n */\ntemplate <typename S, typename T>\nint CompareDeviceResults(\n    S *h_reference,\n    T *d_data,\n    size_t num_items,\n    bool verbose = true,\n    bool display_data = false)\n{\n    // Allocate array on host\n    T *h_data = (T*) malloc(num_items * sizeof(T));\n\n    // Copy data back\n    cudaMemcpy(h_data, d_data, sizeof(T) * num_items, cudaMemcpyDeviceToHost);\n\n    // Display data\n    if (display_data)\n    {\n        printf(\"Reference:\\n\");\n        for (int i = 0; i < int(num_items); i++)\n        {\n            std::cout << CoutCast(h_reference[i]) << \", \";\n        }\n        printf(\"\\n\\nComputed:\\n\");\n        for (int i = 0; i < int(num_items); i++)\n        {\n            std::cout << CoutCast(h_data[i]) << \", \";\n        }\n        printf(\"\\n\\n\");\n    }\n\n    // Check\n    int retval = CompareResults(h_data, h_reference, num_items, verbose);\n\n    // Cleanup\n    if (h_data) free(h_data);\n\n    return retval;\n}\n\n\n/**\n * Verify the contents of a device array match those\n * of a device array\n */\ntemplate <typename T>\nint CompareDeviceDeviceResults(\n    T *d_reference,\n    T *d_data,\n    size_t num_items,\n    bool verbose = true,\n    bool display_data = false)\n{\n    // Allocate array on host\n    T *h_reference = (T*) malloc(num_items * sizeof(T));\n    T *h_data = (T*) malloc(num_items * sizeof(T));\n\n    // Copy data back\n    cudaMemcpy(h_reference, d_reference, sizeof(T) * num_items, cudaMemcpyDeviceToHost);\n    cudaMemcpy(h_data, d_data, sizeof(T) * num_items, cudaMemcpyDeviceToHost);\n\n    // Display data\n    if (display_data) {\n        printf(\"Reference:\\n\");\n        for (int i = 0; i < num_items; i++)\n        {\n            std::cout << CoutCast(h_reference[i]) << \", \";\n        }\n        printf(\"\\n\\nComputed:\\n\");\n        for (int i = 0; i < num_items; i++)\n        {\n            std::cout << CoutCast(h_data[i]) << \", \";\n        }\n        printf(\"\\n\\n\");\n    }\n\n    // Check\n    int retval = CompareResults(h_data, h_reference, num_items, verbose);\n\n    // Cleanup\n    if (h_reference) free(h_reference);\n    if (h_data) free(h_data);\n\n    return retval;\n}\n\n\n/**\n * Print the contents of a host array\n */\nvoid DisplayResults(\n    cub::NullType   *h_data,\n    size_t          num_items)\n{}\n\n\n/**\n * Print the contents of a host array\n */\ntemplate <typename InputIteratorT>\nvoid DisplayResults(\n    InputIteratorT h_data,\n    size_t num_items)\n{\n    // Display data\n    for (int i = 0; i < int(num_items); i++)\n    {\n        std::cout << CoutCast(h_data[i]) << \", \";\n    }\n    printf(\"\\n\");\n}\n\n\n/**\n * Print the contents of a device array\n */\ntemplate <typename T>\nvoid DisplayDeviceResults(\n    T *d_data,\n    size_t num_items)\n{\n    // Allocate array on host\n    T *h_data = (T*) malloc(num_items * sizeof(T));\n\n    // Copy data back\n    cudaMemcpy(h_data, d_data, sizeof(T) * num_items, cudaMemcpyDeviceToHost);\n\n    DisplayResults(h_data, num_items);\n\n    // Cleanup\n    if (h_data) free(h_data);\n}\n\n\n/******************************************************************************\n * Segment descriptor generation\n ******************************************************************************/\n\n/**\n * Initialize segments\n */\nvoid InitializeSegments(\n    int     num_items,\n    int     num_segments,\n    int     *h_segment_offsets,\n    bool    verbose = false)\n{\n    if (num_segments <= 0)\n        return;\n\n    unsigned int expected_segment_length = (num_items + num_segments - 1) / num_segments;\n    int offset = 0;\n    for (int i = 0; i < num_segments; ++i)\n    {\n        h_segment_offsets[i] = offset;\n\n        unsigned int segment_length = RandomValue((expected_segment_length * 2) + 1);\n        offset += segment_length;\n        offset = CUB_MIN(offset, num_items);\n    }\n    h_segment_offsets[num_segments] = num_items;\n\n    if (verbose)\n    {\n        printf(\"Segment offsets: \");\n        DisplayResults(h_segment_offsets, num_segments + 1);\n    }\n}\n\n\n/******************************************************************************\n * Timing\n ******************************************************************************/\n\n\nstruct CpuTimer\n{\n#if defined(_WIN32) || defined(_WIN64)\n\n    LARGE_INTEGER ll_freq;\n    LARGE_INTEGER ll_start;\n    LARGE_INTEGER ll_stop;\n\n    CpuTimer()\n    {\n        QueryPerformanceFrequency(&ll_freq);\n    }\n\n    void Start()\n    {\n        QueryPerformanceCounter(&ll_start);\n    }\n\n    void Stop()\n    {\n        QueryPerformanceCounter(&ll_stop);\n    }\n\n    float ElapsedMillis()\n    {\n        double start = double(ll_start.QuadPart) / double(ll_freq.QuadPart);\n        double stop  = double(ll_stop.QuadPart) / double(ll_freq.QuadPart);\n\n        return float((stop - start) * 1000);\n    }\n\n#else\n\n    rusage start;\n    rusage stop;\n\n    void Start()\n    {\n        getrusage(RUSAGE_SELF, &start);\n    }\n\n    void Stop()\n    {\n        getrusage(RUSAGE_SELF, &stop);\n    }\n\n    float ElapsedMillis()\n    {\n        float sec = stop.ru_utime.tv_sec - start.ru_utime.tv_sec;\n        float usec = stop.ru_utime.tv_usec - start.ru_utime.tv_usec;\n\n        return (sec * 1000) + (usec / 1000);\n    }\n\n#endif\n};\n\nstruct GpuTimer\n{\n    cudaEvent_t start;\n    cudaEvent_t stop;\n\n    GpuTimer()\n    {\n        cudaEventCreate(&start);\n        cudaEventCreate(&stop);\n    }\n\n    ~GpuTimer()\n    {\n        cudaEventDestroy(start);\n        cudaEventDestroy(stop);\n    }\n\n    void Start()\n    {\n        cudaEventRecord(start, 0);\n    }\n\n    void Stop()\n    {\n        cudaEventRecord(stop, 0);\n    }\n\n    float ElapsedMillis()\n    {\n        float elapsed;\n        cudaEventSynchronize(stop);\n        cudaEventElapsedTime(&elapsed, start, stop);\n        return elapsed;\n    }\n};\n"
  },
  {
    "path": "external/cub/test/test_warp_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of WarpReduce utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <cub/warp/warp_reduce.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose       = false;\nint                     g_repeat        = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n/**\n * \\brief WrapperFunctor (for precluding test-specialized dispatch to *Sum variants)\n */\ntemplate<\n    typename    OpT,\n    int         LOGICAL_WARP_THREADS>\nstruct WrapperFunctor\n{\n    OpT op;\n    int num_valid;\n\n    inline __host__ __device__ WrapperFunctor(OpT op, int num_valid) : op(op), num_valid(num_valid) {}\n\n    template <typename T>\n    inline __host__ __device__ T operator()(const T &a, const T &b) const\n    {\n#if CUB_PTX_ARCH != 0\n        if ((cub::LaneId() % LOGICAL_WARP_THREADS) >= num_valid)\n            cub::ThreadTrap();\n#endif\n\n        return op(a, b);\n    }\n\n};\n\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/**\n * Generic reduction\n */\ntemplate <\n    typename    T,\n    typename    ReductionOp,\n    typename    WarpReduce,\n    bool        PRIMITIVE = Traits<T>::PRIMITIVE>\nstruct DeviceTest\n{\n    static __device__ __forceinline__ T Reduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        ReductionOp                         &reduction_op)\n    {\n        return WarpReduce(temp_storage).Reduce(data, reduction_op);\n    }\n\n    static __device__ __forceinline__ T Reduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        ReductionOp                         &reduction_op,\n        const int                           &valid_warp_threads)\n    {\n        return WarpReduce(temp_storage).Reduce(data, reduction_op, valid_warp_threads);\n    }\n\n    template <typename FlagT>\n    static __device__ __forceinline__ T HeadSegmentedReduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        FlagT                                &flag,\n        ReductionOp                         &reduction_op)\n    {\n        return WarpReduce(temp_storage).HeadSegmentedReduce(data, flag, reduction_op);\n    }\n\n    template <typename FlagT>\n    static __device__ __forceinline__ T TailSegmentedReduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        FlagT                                &flag,\n        ReductionOp                         &reduction_op)\n    {\n        return WarpReduce(temp_storage).TailSegmentedReduce(data, flag, reduction_op);\n    }\n\n};\n\n\n/**\n * Summation\n */\ntemplate <\n    typename    T,\n    typename    WarpReduce>\nstruct DeviceTest<T, Sum, WarpReduce, true>\n{\n    static __device__ __forceinline__ T Reduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        Sum                              &reduction_op)\n    {\n        return WarpReduce(temp_storage).Sum(data);\n    }\n\n    static __device__ __forceinline__ T Reduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        Sum                              &reduction_op,\n        const int                           &valid_warp_threads)\n    {\n        return WarpReduce(temp_storage).Sum(data, valid_warp_threads);\n    }\n\n    template <typename FlagT>\n    static __device__ __forceinline__ T HeadSegmentedReduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        FlagT                                &flag,\n        Sum                              &reduction_op)\n    {\n        return WarpReduce(temp_storage).HeadSegmentedSum(data, flag);\n    }\n\n    template <typename FlagT>\n    static __device__ __forceinline__ T TailSegmentedReduce(\n        typename WarpReduce::TempStorage    &temp_storage,\n        T                                   &data,\n        FlagT                                &flag,\n        Sum                              &reduction_op)\n    {\n        return WarpReduce(temp_storage).TailSegmentedSum(data, flag);\n    }\n\n};\n\n\n/**\n * Full-tile warp reduction kernel\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    ReductionOp>\n__global__ void FullWarpReduceKernel(\n    T               *d_in,\n    T               *d_out,\n    ReductionOp     reduction_op,\n    clock_t         *d_elapsed)\n{\n    // Cooperative warp-reduce utility type (1 warp)\n    typedef WarpReduce<T, LOGICAL_WARP_THREADS> WarpReduce;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename WarpReduce::TempStorage temp_storage[WARPS];\n\n    // Per-thread tile data\n    T input = d_in[threadIdx.x];\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Test warp reduce\n    int warp_id = threadIdx.x / LOGICAL_WARP_THREADS;\n\n    T output = DeviceTest<T, ReductionOp, WarpReduce>::Reduce(\n        temp_storage[warp_id], input, reduction_op);\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    *d_elapsed = stop - start;\n\n    // Store aggregate\n    d_out[threadIdx.x] = (threadIdx.x % LOGICAL_WARP_THREADS == 0) ?\n        output :\n        input;\n}\n\n/**\n * Partially-full warp reduction kernel\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    ReductionOp>\n__global__ void PartialWarpReduceKernel(\n    T           *d_in,\n    T           *d_out,\n    ReductionOp reduction_op,\n    clock_t     *d_elapsed,\n    int         valid_warp_threads)\n{\n    // Cooperative warp-reduce utility type\n    typedef WarpReduce<T, LOGICAL_WARP_THREADS> WarpReduce;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename WarpReduce::TempStorage temp_storage[WARPS];\n\n    // Per-thread tile data\n    T input = d_in[threadIdx.x];\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Test partial-warp reduce\n    int warp_id = threadIdx.x / LOGICAL_WARP_THREADS;\n    T output = DeviceTest<T, ReductionOp, WarpReduce>::Reduce(\n        temp_storage[warp_id], input, reduction_op, valid_warp_threads);\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    *d_elapsed = stop - start;\n\n    // Store aggregate\n    d_out[threadIdx.x] = (threadIdx.x % LOGICAL_WARP_THREADS == 0) ?\n        output :\n        input;\n}\n\n\n/**\n * Head-based segmented warp reduction test kernel\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    FlagT,\n    typename    ReductionOp>\n__global__ void WarpHeadSegmentedReduceKernel(\n    T           *d_in,\n    FlagT        *d_head_flags,\n    T           *d_out,\n    ReductionOp reduction_op,\n    clock_t     *d_elapsed)\n{\n    // Cooperative warp-reduce utility type\n    typedef WarpReduce<T, LOGICAL_WARP_THREADS> WarpReduce;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename WarpReduce::TempStorage temp_storage[WARPS];\n\n    // Per-thread tile data\n    T       input       = d_in[threadIdx.x];\n    FlagT   head_flag   = d_head_flags[threadIdx.x];\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Test segmented warp reduce\n    int warp_id = threadIdx.x / LOGICAL_WARP_THREADS;\n    T output = DeviceTest<T, ReductionOp, WarpReduce>::HeadSegmentedReduce(\n        temp_storage[warp_id], input, head_flag, reduction_op);\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    *d_elapsed = stop - start;\n\n    // Store aggregate\n    d_out[threadIdx.x] = ((threadIdx.x % LOGICAL_WARP_THREADS == 0) || head_flag) ?\n        output :\n        input;\n}\n\n\n/**\n * Tail-based segmented warp reduction test kernel\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    FlagT,\n    typename    ReductionOp>\n__global__ void WarpTailSegmentedReduceKernel(\n    T           *d_in,\n    FlagT       *d_tail_flags,\n    T           *d_out,\n    ReductionOp reduction_op,\n    clock_t     *d_elapsed)\n{\n    // Cooperative warp-reduce utility type\n    typedef WarpReduce<T, LOGICAL_WARP_THREADS> WarpReduce;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename WarpReduce::TempStorage temp_storage[WARPS];\n\n    // Per-thread tile data\n    T       input       = d_in[threadIdx.x];\n    FlagT    tail_flag   = d_tail_flags[threadIdx.x];\n    FlagT    head_flag   = (threadIdx.x == 0) ?\n                            0 :\n                            d_tail_flags[threadIdx.x - 1];\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Test segmented warp reduce\n    int warp_id = threadIdx.x / LOGICAL_WARP_THREADS;\n    T output = DeviceTest<T, ReductionOp, WarpReduce>::TailSegmentedReduce(\n        temp_storage[warp_id], input, tail_flag, reduction_op);\n\n    // Record elapsed clocks\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    *d_elapsed = stop - start;\n\n    // Store aggregate\n    d_out[threadIdx.x] = ((threadIdx.x % LOGICAL_WARP_THREADS == 0) || head_flag) ?\n        output :\n        input;\n}\n\n\n//---------------------------------------------------------------------\n// Host utility subroutines\n//---------------------------------------------------------------------\n\n/**\n * Initialize reduction problem (and solution)\n */\ntemplate <\n    typename    T,\n    typename    ReductionOp>\nvoid Initialize(\n    GenMode     gen_mode,\n    int         flag_entropy,\n    T           *h_in,\n    int         *h_flags,\n    int         warps,\n    int         warp_threads,\n    int         valid_warp_threads,\n    ReductionOp reduction_op,\n    T           *h_head_out,\n    T           *h_tail_out)\n{\n    for (int i = 0; i < warps * warp_threads; ++i)\n    {\n        // Sample a value for this item\n        InitValue(gen_mode, h_in[i], i);\n        h_head_out[i] = h_in[i];\n        h_tail_out[i] = h_in[i];\n\n        // Sample whether or not this item will be a segment head\n        char bits;\n        RandomBits(bits, flag_entropy);\n        h_flags[i] = bits & 0x1;\n    }\n\n    // Accumulate segments (lane 0 of each warp is implicitly a segment head)\n    for (int warp = 0; warp < warps; ++warp)\n    {\n        int warp_offset  = warp * warp_threads;\n        int item_offset = warp_offset + valid_warp_threads - 1;\n\n        // Last item in warp\n        T head_aggregate = h_in[item_offset];\n        T tail_aggregate = h_in[item_offset];\n\n        if (h_flags[item_offset])\n            h_head_out[item_offset] = head_aggregate;\n        item_offset--;\n\n        // Work backwards\n        while (item_offset >= warp_offset)\n        {\n            if (h_flags[item_offset + 1])\n            {\n                head_aggregate = h_in[item_offset];\n            }\n            else\n            {\n                head_aggregate = reduction_op(head_aggregate, h_in[item_offset]);\n            }\n\n            if (h_flags[item_offset])\n            {\n                h_head_out[item_offset] = head_aggregate;\n                h_tail_out[item_offset + 1] = tail_aggregate;\n                tail_aggregate = h_in[item_offset];\n            }\n            else\n            {\n                tail_aggregate = reduction_op(tail_aggregate, h_in[item_offset]);\n            }\n\n            item_offset--;\n        }\n\n        // Record last segment head_aggregate to head offset\n        h_head_out[warp_offset] = head_aggregate;\n        h_tail_out[warp_offset] = tail_aggregate;\n    }\n}\n\n\n/**\n * Test warp reduction\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    ReductionOp>\nvoid TestReduce(\n    GenMode     gen_mode,\n    ReductionOp reduction_op,\n    int         valid_warp_threads = LOGICAL_WARP_THREADS)\n{\n    const int BLOCK_THREADS = LOGICAL_WARP_THREADS * WARPS;\n\n    // Allocate host arrays\n    T   *h_in           = new T[BLOCK_THREADS];\n    int *h_flags        = new int[BLOCK_THREADS];\n    T   *h_out          = new T[BLOCK_THREADS];\n    T   *h_tail_out     = new T[BLOCK_THREADS];\n\n    // Initialize problem\n    Initialize(gen_mode, -1, h_in, h_flags, WARPS, LOGICAL_WARP_THREADS, valid_warp_threads, reduction_op, h_out, h_tail_out);\n\n    // Initialize/clear device arrays\n    T *d_in = NULL;\n    T *d_out = NULL;\n    clock_t *d_elapsed = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(clock_t)));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * BLOCK_THREADS, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * BLOCK_THREADS));\n\n    if (g_verbose)\n    {\n        printf(\"Data:\\n\");\n        for (int i = 0; i < WARPS; ++i)\n            DisplayResults(h_in + (i * LOGICAL_WARP_THREADS), valid_warp_threads);\n    }\n\n    // Run kernel\n    printf(\"\\nGen-mode %d, %d warps, %d warp threads, %d valid lanes, %s (%d bytes) elements:\\n\",\n        gen_mode,\n        WARPS,\n        LOGICAL_WARP_THREADS,\n        valid_warp_threads,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    if (valid_warp_threads == LOGICAL_WARP_THREADS)\n    {\n        // Run full-warp kernel\n        FullWarpReduceKernel<WARPS, LOGICAL_WARP_THREADS><<<1, BLOCK_THREADS>>>(\n            d_in,\n            d_out,\n            reduction_op,\n            d_elapsed);\n    }\n    else\n    {\n        // Run partial-warp kernel\n        PartialWarpReduceKernel<WARPS, LOGICAL_WARP_THREADS><<<1, BLOCK_THREADS>>>(\n            d_in,\n            d_out,\n            reduction_op,\n            d_elapsed,\n            valid_warp_threads);\n    }\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tReduction results: \");\n    int compare = CompareDeviceResults(h_out, d_out, BLOCK_THREADS, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_flags) delete[] h_flags;\n    if (h_out) delete[] h_out;\n    if (h_tail_out) delete[] h_tail_out;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Test warp segmented reduction\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    ReductionOp>\nvoid TestSegmentedReduce(\n    GenMode     gen_mode,\n    int         flag_entropy,\n    ReductionOp reduction_op)\n{\n    const int BLOCK_THREADS = LOGICAL_WARP_THREADS * WARPS;\n\n    // Allocate host arrays\n    int compare;\n    T   *h_in           = new T[BLOCK_THREADS];\n    int *h_flags        = new int[BLOCK_THREADS];\n    T   *h_head_out     = new T[BLOCK_THREADS];\n    T   *h_tail_out     = new T[BLOCK_THREADS];\n\n    // Initialize problem\n    Initialize(gen_mode, flag_entropy, h_in, h_flags, WARPS, LOGICAL_WARP_THREADS, LOGICAL_WARP_THREADS, reduction_op, h_head_out, h_tail_out);\n\n    // Initialize/clear device arrays\n    T           *d_in = NULL;\n    int         *d_flags = NULL;\n    T           *d_head_out = NULL;\n    T           *d_tail_out = NULL;\n    clock_t     *d_elapsed = NULL;\n\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_flags, sizeof(int) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_head_out, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_tail_out, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(clock_t)));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * BLOCK_THREADS, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemcpy(d_flags, h_flags, sizeof(int) * BLOCK_THREADS, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_head_out, 0, sizeof(T) * BLOCK_THREADS));\n    CubDebugExit(cudaMemset(d_tail_out, 0, sizeof(T) * BLOCK_THREADS));\n\n    if (g_verbose)\n    {\n        printf(\"Data:\\n\");\n        for (int i = 0; i < WARPS; ++i)\n            DisplayResults(h_in + (i * LOGICAL_WARP_THREADS), LOGICAL_WARP_THREADS);\n\n        printf(\"\\nFlags:\\n\");\n        for (int i = 0; i < WARPS; ++i)\n            DisplayResults(h_flags + (i * LOGICAL_WARP_THREADS), LOGICAL_WARP_THREADS);\n    }\n\n    printf(\"\\nGen-mode %d, head flag entropy reduction %d, %d warps, %d warp threads, %s (%d bytes) elements:\\n\",\n        gen_mode,\n        flag_entropy,\n        WARPS,\n        LOGICAL_WARP_THREADS,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    // Run head-based kernel\n    WarpHeadSegmentedReduceKernel<WARPS, LOGICAL_WARP_THREADS><<<1, BLOCK_THREADS>>>(\n        d_in,\n        d_flags,\n        d_head_out,\n        reduction_op,\n        d_elapsed);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tHead-based segmented reduction results: \");\n    compare = CompareDeviceResults(h_head_out, d_head_out, BLOCK_THREADS, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Run tail-based kernel\n    WarpTailSegmentedReduceKernel<WARPS, LOGICAL_WARP_THREADS><<<1, BLOCK_THREADS>>>(\n        d_in,\n        d_flags,\n        d_tail_out,\n        reduction_op,\n        d_elapsed);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tTail-based segmented reduction results: \");\n    compare = CompareDeviceResults(h_tail_out, d_tail_out, BLOCK_THREADS, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_flags) delete[] h_flags;\n    if (h_head_out) delete[] h_head_out;\n    if (h_tail_out) delete[] h_tail_out;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_flags) CubDebugExit(g_allocator.DeviceFree(d_flags));\n    if (d_head_out) CubDebugExit(g_allocator.DeviceFree(d_head_out));\n    if (d_tail_out) CubDebugExit(g_allocator.DeviceFree(d_tail_out));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Run battery of tests for different full and partial tile sizes\n */\ntemplate <\n    int         WARPS,\n    int         LOGICAL_WARP_THREADS,\n    typename    T,\n    typename    ReductionOp>\nvoid Test(\n    GenMode     gen_mode,\n    ReductionOp reduction_op)\n{\n    // Partial tiles\n    for (\n        int valid_warp_threads = 1;\n        valid_warp_threads < LOGICAL_WARP_THREADS;\n        valid_warp_threads += CUB_MAX(1, LOGICAL_WARP_THREADS / 5))\n    {\n        // Without wrapper (to test non-excepting PTX POD-op specializations)\n        TestReduce<WARPS, LOGICAL_WARP_THREADS, T>(gen_mode, reduction_op, valid_warp_threads);\n\n        // With wrapper to ensure no ops called on OOB lanes\n        WrapperFunctor<ReductionOp, LOGICAL_WARP_THREADS> wrapped_op(reduction_op, valid_warp_threads);\n        TestReduce<WARPS, LOGICAL_WARP_THREADS, T>(gen_mode, wrapped_op, valid_warp_threads);\n    }\n\n    // Full tile\n    TestReduce<WARPS, LOGICAL_WARP_THREADS, T>(gen_mode, reduction_op, LOGICAL_WARP_THREADS);\n\n    // Segmented reduction with different head flags\n    for (int flag_entropy = 0; flag_entropy < 10; ++flag_entropy)\n    {\n        TestSegmentedReduce<WARPS, LOGICAL_WARP_THREADS, T>(gen_mode, flag_entropy, reduction_op);\n    }\n}\n\n\n/**\n * Run battery of tests for different data types and reduce ops\n */\ntemplate <\n    int WARPS,\n    int LOGICAL_WARP_THREADS>\nvoid Test(GenMode gen_mode)\n{\n    // primitive\n    Test<WARPS, LOGICAL_WARP_THREADS, char>(                gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, short>(               gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, int>(                 gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, long long>(           gen_mode, Sum());\n\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned char>(       gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned short>(      gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned int>(        gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned long long>(  gen_mode, Sum());\n\n    if (gen_mode != RANDOM)\n    {\n        Test<WARPS, LOGICAL_WARP_THREADS, float>(           gen_mode, Sum());\n        Test<WARPS, LOGICAL_WARP_THREADS, double>(          gen_mode, Sum());\n    }\n\n    // primitive (alternative reduce op)\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned char>(       gen_mode, Max());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned short>(      gen_mode, Max());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned int>(        gen_mode, Max());\n    Test<WARPS, LOGICAL_WARP_THREADS, unsigned long long>(  gen_mode, Max());\n\n    // vec-1\n    Test<WARPS, LOGICAL_WARP_THREADS, uchar1>(              gen_mode, Sum());\n\n    // vec-2\n    Test<WARPS, LOGICAL_WARP_THREADS, uchar2>(              gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, ushort2>(             gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, uint2>(               gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, ulonglong2>(          gen_mode, Sum());\n\n    // vec-4\n    Test<WARPS, LOGICAL_WARP_THREADS, uchar4>(              gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, ushort4>(             gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, uint4>(               gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, ulonglong4>(          gen_mode, Sum());\n\n    // complex\n    Test<WARPS, LOGICAL_WARP_THREADS, TestFoo>(             gen_mode, Sum());\n    Test<WARPS, LOGICAL_WARP_THREADS, TestBar>(             gen_mode, Sum());\n}\n\n\n/**\n * Run battery of tests for different problem generation options\n */\ntemplate <\n    int WARPS,\n    int LOGICAL_WARP_THREADS>\nvoid Test()\n{\n    Test<WARPS, LOGICAL_WARP_THREADS>(UNIFORM);\n    Test<WARPS, LOGICAL_WARP_THREADS>(INTEGER_SEED);\n    Test<WARPS, LOGICAL_WARP_THREADS>(RANDOM);\n}\n\n\n/**\n * Run battery of tests for different number of active warps\n */\ntemplate <int LOGICAL_WARP_THREADS>\nvoid Test()\n{\n    Test<1, LOGICAL_WARP_THREADS>();\n\n    // Only power-of-two subwarps can be tiled\n    if ((LOGICAL_WARP_THREADS == 32) || PowerOfTwo<LOGICAL_WARP_THREADS>::VALUE)\n        Test<2, LOGICAL_WARP_THREADS>();\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#ifdef QUICK_TEST\n\n    // Compile/run quick tests\n    TestReduce<1, 32, int>(UNIFORM, Sum());\n\n    TestReduce<1, 32, double>(UNIFORM, Sum());\n    TestReduce<2, 16, TestBar>(UNIFORM, Sum());\n    TestSegmentedReduce<1, 32, int>(UNIFORM, 1, Sum());\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test logical warp sizes\n        Test<32>();\n        Test<16>();\n        Test<9>();\n        Test<7>();\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "external/cub/test/test_warp_scan.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Test of WarpScan utilities\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <stdio.h>\n#include <typeinfo>\n\n#include <cub/warp/warp_scan.cuh>\n#include <cub/util_allocator.cuh>\n\n#include \"test_util.h\"\n\nusing namespace cub;\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\nbool                    g_verbose       = false;\nint                     g_repeat        = 0;\nCachingDeviceAllocator  g_allocator(true);\n\n\n/**\n * Primitive variant to test\n */\nenum TestMode\n{\n    BASIC,\n    AGGREGATE,\n};\n\n\n\n/**\n * \\brief WrapperFunctor (for precluding test-specialized dispatch to *Sum variants)\n */\ntemplate<typename OpT>\nstruct WrapperFunctor\n{\n    OpT op;\n\n    WrapperFunctor(OpT op) : op(op) {}\n\n    template <typename T>\n    __host__ __device__ __forceinline__ T operator()(const T &a, const T &b) const\n    {\n        return op(a, b);\n    }\n};\n\n//---------------------------------------------------------------------\n// Test kernels\n//---------------------------------------------------------------------\n\n/// Exclusive scan basic\ntemplate <typename WarpScanT, typename T, typename ScanOpT, typename IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    T                               &initial_value,\n    ScanOpT                         &scan_op,\n    T                               &aggregate,\n    Int2Type<BASIC>                 test_mode,\n    IsPrimitiveT                    is_primitive)\n{\n    // Test basic warp scan\n    warp_scan.ExclusiveScan(data, data, initial_value, scan_op);\n}\n\n/// Exclusive scan aggregate\ntemplate <\n    typename    WarpScanT,\n    typename    T,\n    typename    ScanOpT,\n    typename    IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    T                               &initial_value,\n    ScanOpT                         &scan_op,\n    T                               &aggregate,\n    Int2Type<AGGREGATE>             test_mode,\n    IsPrimitiveT                    is_primitive)\n{\n    // Test with cumulative aggregate\n    warp_scan.ExclusiveScan(data, data, initial_value, scan_op, aggregate);\n}\n\n\n/// Exclusive sum basic\ntemplate <\n    typename    WarpScanT,\n    typename    T>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    T                               &initial_value,\n    Sum                             &scan_op,\n    T                               &aggregate,\n    Int2Type<BASIC>                 test_mode,\n    Int2Type<true>                  is_primitive)\n{\n    // Test basic warp scan\n    warp_scan.ExclusiveSum(data, data);\n}\n\n\n/// Exclusive sum aggregate\ntemplate <\n    typename    WarpScanT,\n    typename    T>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    T                               &initial_value,\n    Sum                             &scan_op,\n    T                               &aggregate,\n    Int2Type<AGGREGATE>             test_mode,\n    Int2Type<true>                  is_primitive)\n{\n    // Test with cumulative aggregate\n    warp_scan.ExclusiveSum(data, data, aggregate);\n}\n\n\n/// Inclusive scan basic\ntemplate <\n    typename    WarpScanT,\n    typename    T,\n    typename    ScanOpT,\n    typename    IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    NullType                        &initial_value,\n    ScanOpT                         &scan_op,\n    T                               &aggregate,\n    Int2Type<BASIC>                 test_mode,\n    IsPrimitiveT                    is_primitive)\n{\n    // Test basic warp scan\n    warp_scan.InclusiveScan(data, data, scan_op);\n}\n\n/// Inclusive scan aggregate\ntemplate <\n    typename    WarpScanT,\n    typename    T,\n    typename    ScanOpT,\n    typename    IsPrimitiveT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    NullType                        &initial_value,\n    ScanOpT                         &scan_op,\n    T                               &aggregate,\n    Int2Type<AGGREGATE>             test_mode,\n    IsPrimitiveT                    is_primitive)\n{\n    // Test with cumulative aggregate\n    warp_scan.InclusiveScan(data, data, scan_op, aggregate);\n}\n\n/// Inclusive sum basic\ntemplate <\n    typename    WarpScanT,\n    typename    T,\n    typename    InitialValueT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    NullType                        &initial_value,\n    Sum                             &scan_op,\n    T                               &aggregate,\n    Int2Type<BASIC>                 test_mode,\n    Int2Type<true>                  is_primitive)\n{\n    // Test basic warp scan\n    warp_scan.InclusiveSum(data, data);\n}\n\n/// Inclusive sum aggregate\ntemplate <\n    typename    WarpScanT,\n    typename    T,\n    typename    InitialValueT>\n__device__ __forceinline__ void DeviceTest(\n    WarpScanT                       &warp_scan,\n    T                               &data,\n    NullType                        &initial_value,\n    Sum                             &scan_op,\n    T                               &aggregate,\n    Int2Type<AGGREGATE>             test_mode,\n    Int2Type<true>                  is_primitive)\n{\n    // Test with cumulative aggregate\n    warp_scan.InclusiveSum(data, data, aggregate);\n}\n\n\n/**\n * WarpScan test kernel\n */\ntemplate <\n    int         LOGICAL_WARP_THREADS,\n    TestMode    TEST_MODE,\n    typename    T,\n    typename    ScanOpT,\n    typename    InitialValueT>\n__global__ void WarpScanKernel(\n    T               *d_in,\n    T               *d_out,\n    T               *d_aggregate,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value,\n    clock_t         *d_elapsed)\n{\n    // Cooperative warp-scan utility type (1 warp)\n    typedef WarpScan<T, LOGICAL_WARP_THREADS> WarpScanT;\n\n    // Allocate temp storage in shared memory\n    __shared__ typename WarpScanT::TempStorage temp_storage;\n\n    // Per-thread tile data\n    T data = d_in[threadIdx.x];\n\n    // Start cycle timer\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t start = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    T aggregate;\n\n    // Test scan\n    WarpScanT warp_scan(temp_storage);\n    DeviceTest(\n        warp_scan,\n        data,\n        initial_value,\n        scan_op,\n        aggregate,\n        Int2Type<TEST_MODE>(),\n        Int2Type<Traits<T>::PRIMITIVE>());\n\n    // Stop cycle timer\n    __threadfence_block();      // workaround to prevent clock hoisting\n    clock_t stop = clock();\n    __threadfence_block();      // workaround to prevent clock hoisting\n\n    // Store data\n    d_out[threadIdx.x] = data;\n\n    if (TEST_MODE != BASIC)\n    {\n        // Store aggregate\n        d_aggregate[threadIdx.x] = aggregate;\n    }\n\n    // Store time\n    if (threadIdx.x == 0)\n    {\n        *d_elapsed = (start > stop) ? start - stop : stop - start;\n    }\n}\n\n\n//---------------------------------------------------------------------\n// Host utility subroutines\n//---------------------------------------------------------------------\n\n/**\n * Initialize exclusive-scan problem (and solution)\n */\ntemplate <\n    typename        T,\n    typename        ScanOpT>\nT Initialize(\n    GenMode         gen_mode,\n    T               *h_in,\n    T               *h_reference,\n    int             num_items,\n    ScanOpT         scan_op,\n    T               initial_value)\n{\n    InitValue(gen_mode, h_in[0], 0);\n\n    T block_aggregate   = h_in[0];\n    h_reference[0]      = initial_value;\n    T inclusive         = scan_op(initial_value, h_in[0]);\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n        h_reference[i] = inclusive;\n        inclusive = scan_op(inclusive, h_in[i]);\n        block_aggregate = scan_op(block_aggregate, h_in[i]);\n    }\n\n    return block_aggregate;\n}\n\n\n/**\n * Initialize inclusive-scan problem (and solution)\n */\ntemplate <\n    typename    T,\n    typename    ScanOpT>\nT Initialize(\n    GenMode     gen_mode,\n    T           *h_in,\n    T           *h_reference,\n    int         num_items,\n    ScanOpT     scan_op,\n    NullType)\n{\n    InitValue(gen_mode, h_in[0], 0);\n\n    T block_aggregate   = h_in[0];\n    T inclusive         = h_in[0];\n    h_reference[0]      = inclusive;\n\n    for (int i = 1; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n        inclusive = scan_op(inclusive, h_in[i]);\n        block_aggregate = scan_op(block_aggregate, h_in[i]);\n        h_reference[i] = inclusive;\n    }\n\n    return block_aggregate;\n}\n\n\n/**\n * Test warp scan\n */\ntemplate <\n    int             LOGICAL_WARP_THREADS,\n    TestMode        TEST_MODE,\n    typename        T,\n    typename        ScanOpT,\n    typename        InitialValueT>        // NullType implies inclusive-scan, otherwise inclusive scan\nvoid Test(\n    GenMode         gen_mode,\n    ScanOpT         scan_op,\n    InitialValueT   initial_value)\n{\n    // Allocate host arrays\n    T *h_in = new T[LOGICAL_WARP_THREADS];\n    T *h_reference = new T[LOGICAL_WARP_THREADS];\n    T *h_aggregate = new T[LOGICAL_WARP_THREADS];\n\n    // Initialize problem\n    T aggregate = Initialize(\n        gen_mode,\n        h_in,\n        h_reference,\n        LOGICAL_WARP_THREADS,\n        scan_op,\n        initial_value);\n\n    if (g_verbose)\n    {\n        printf(\"Input: \\n\");\n        DisplayResults(h_in, LOGICAL_WARP_THREADS);\n        printf(\"\\n\");\n    }\n\n    for (int i = 0; i < LOGICAL_WARP_THREADS; ++i)\n    {\n        h_aggregate[i] = aggregate;\n    }\n\n    // Initialize/clear device arrays\n    T *d_in = NULL;\n    T *d_out = NULL;\n    T *d_aggregate = NULL;\n    clock_t *d_elapsed = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * LOGICAL_WARP_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * (LOGICAL_WARP_THREADS + 1)));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_aggregate, sizeof(T) * LOGICAL_WARP_THREADS));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_elapsed, sizeof(clock_t)));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * LOGICAL_WARP_THREADS, cudaMemcpyHostToDevice));\n    CubDebugExit(cudaMemset(d_out, 0, sizeof(T) * (LOGICAL_WARP_THREADS + 1)));\n    CubDebugExit(cudaMemset(d_aggregate, 0, sizeof(T) * LOGICAL_WARP_THREADS));\n\n    // Run kernel\n    printf(\"Test-mode %d (%s), gen-mode %d (%s), %s warpscan, %d warp threads, %s (%d bytes) elements:\\n\",\n        TEST_MODE, typeid(TEST_MODE).name(),\n        gen_mode, typeid(gen_mode).name(),\n        (Equals<InitialValueT, NullType>::VALUE) ? \"Inclusive\" : \"Exclusive\",\n        LOGICAL_WARP_THREADS,\n        typeid(T).name(),\n        (int) sizeof(T));\n    fflush(stdout);\n\n    // Run aggregate/prefix kernel\n    WarpScanKernel<LOGICAL_WARP_THREADS, TEST_MODE><<<1, LOGICAL_WARP_THREADS>>>(\n        d_in,\n        d_out,\n        d_aggregate,\n        scan_op,\n        initial_value,\n        d_elapsed);\n\n    printf(\"\\tElapsed clocks: \");\n    DisplayDeviceResults(d_elapsed, 1);\n\n    CubDebugExit(cudaPeekAtLastError());\n    CubDebugExit(cudaDeviceSynchronize());\n\n    // Copy out and display results\n    printf(\"\\tScan results: \");\n    int compare = CompareDeviceResults(h_reference, d_out, LOGICAL_WARP_THREADS, g_verbose, g_verbose);\n    printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n    AssertEquals(0, compare);\n\n    // Copy out and display aggregate\n    if (TEST_MODE == AGGREGATE)\n    {\n        printf(\"\\tScan aggregate: \");\n        compare = CompareDeviceResults(h_aggregate, d_aggregate, LOGICAL_WARP_THREADS, g_verbose, g_verbose);\n        printf(\"%s\\n\", compare ? \"FAIL\" : \"PASS\");\n        AssertEquals(0, compare);\n    }\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (h_reference) delete[] h_reference;\n    if (h_aggregate) delete[] h_aggregate;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n    if (d_aggregate) CubDebugExit(g_allocator.DeviceFree(d_aggregate));\n    if (d_elapsed) CubDebugExit(g_allocator.DeviceFree(d_elapsed));\n}\n\n\n/**\n * Run battery of tests for different primitive variants\n */\ntemplate <\n    int         LOGICAL_WARP_THREADS,\n    typename    ScanOpT,\n    typename    T>\nvoid Test(\n    GenMode     gen_mode,\n    ScanOpT     scan_op,\n    T           initial_value)\n{\n    // Exclusive\n    Test<LOGICAL_WARP_THREADS, BASIC, T>(gen_mode, scan_op, T());\n    Test<LOGICAL_WARP_THREADS, AGGREGATE, T>(gen_mode, scan_op, T());\n\n    // Exclusive (non-specialized, so we can use initial-value)\n    Test<LOGICAL_WARP_THREADS, BASIC, T>(gen_mode, WrapperFunctor<ScanOpT>(scan_op), initial_value);\n    Test<LOGICAL_WARP_THREADS, AGGREGATE, T>(gen_mode, WrapperFunctor<ScanOpT>(scan_op), initial_value);\n\n    // Inclusive\n    Test<LOGICAL_WARP_THREADS, BASIC, T>(gen_mode, scan_op, NullType());\n    Test<LOGICAL_WARP_THREADS, AGGREGATE, T>(gen_mode, scan_op, NullType());\n}\n\n\n/**\n * Run battery of tests for different data types and scan ops\n */\ntemplate <int LOGICAL_WARP_THREADS>\nvoid Test(GenMode gen_mode)\n{\n    // Get device ordinal\n    int device_ordinal;\n    CubDebugExit(cudaGetDevice(&device_ordinal));\n\n    // Get ptx version\n    int ptx_version;\n    CubDebugExit(PtxVersion(ptx_version));\n\n    // primitive\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (char) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (short) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (int) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (long) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (long long) 99);\n    if (gen_mode != RANDOM) {\n        // Only test numerically stable inputs\n        Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (float) 99);\n        if (ptx_version > 100)\n            Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), (double) 99);\n    }\n\n    // primitive (alternative scan op)\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Max(), (unsigned char) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Max(), (unsigned short) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Max(), (unsigned int) 99);\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Max(), (unsigned long long) 99);\n\n    // vec-2\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_uchar2(17, 21));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_ushort2(17, 21));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_uint2(17, 21));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_ulong2(17, 21));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_ulonglong2(17, 21));\n    if (gen_mode != RANDOM) {\n        // Only test numerically stable inputs\n        Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_float2(17, 21));\n        if (ptx_version > 100)\n            Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_double2(17, 21));\n    }\n\n    // vec-4\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_char4(17, 21, 32, 85));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_short4(17, 21, 32, 85));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_int4(17, 21, 32, 85));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_long4(17, 21, 32, 85));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_longlong4(17, 21, 32, 85));\n    if (gen_mode != RANDOM) {\n        // Only test numerically stable inputs\n        Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_float4(17, 21, 32, 85));\n        if (ptx_version > 100)\n            Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), make_double4(17, 21, 32, 85));\n    }\n\n    // complex\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), TestFoo::MakeTestFoo(17, 21, 32, 85));\n    Test<LOGICAL_WARP_THREADS>(gen_mode, Sum(), TestBar(17, 21));\n\n}\n\n\n/**\n * Run battery of tests for different problem generation options\n */\ntemplate <int LOGICAL_WARP_THREADS>\nvoid Test()\n{\n    Test<LOGICAL_WARP_THREADS>(UNIFORM);\n    Test<LOGICAL_WARP_THREADS>(INTEGER_SEED);\n    Test<LOGICAL_WARP_THREADS>(RANDOM);\n}\n\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    args.GetCmdLineArgument(\"repeat\", g_repeat);\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--repeat=<repetitions of entire test suite>]\"\n            \"[--v] \"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#ifdef QUICK_TEST\n\n    // Compile/run quick tests\n    Test<32, AGGREGATE, int>(UNIFORM, Sum(), (int) 0);\n    Test<32, AGGREGATE, float>(UNIFORM, Sum(), (float) 0);\n    Test<32, AGGREGATE, long long>(UNIFORM, Sum(), (long long) 0);\n    Test<32, AGGREGATE, double>(UNIFORM, Sum(), (double) 0);\n\n    typedef KeyValuePair<int, float> T;\n    cub::Sum sum_op;\n    Test<32, AGGREGATE, T>(UNIFORM, ReduceBySegmentOp<cub::Sum>(sum_op), T());\n\n#else\n\n    // Compile/run thorough tests\n    for (int i = 0; i <= g_repeat; ++i)\n    {\n        // Test logical warp sizes\n        Test<32>();\n        Test<16>();\n        Test<9>();\n        Test<7>();\n    }\n\n#endif\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "external/cub/tune/.gitignore",
    "content": "/bin\n"
  },
  {
    "path": "external/cub/tune/Makefile",
    "content": "#/******************************************************************************\n# * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n# * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n# * \n# * Redistribution and use in source and binary forms, with or without\n# * modification, are permitted provided that the following conditions are met:\n# *\t * Redistributions of source code must retain the above copyright\n# *\t   notice, this list of conditions and the following disclaimer.\n# *\t * Redistributions in binary form must reproduce the above copyright\n# *\t   notice, this list of conditions and the following disclaimer in the\n# *\t   documentation and/or other materials provided with the distribution.\n# *\t * Neither the name of the NVIDIA CORPORATION nor the\n# *\t   names of its contributors may be used to endorse or promote products\n# *\t   derived from this software without specific prior written permission.\n# * \n# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n# * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n# * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n# * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n# * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n# *\n#******************************************************************************/\n \n#-------------------------------------------------------------------------------\n# Build script for project\n#-------------------------------------------------------------------------------\n\nNVCC = \"$(shell which nvcc)\"\nNVCC_VERSION = $(strip $(shell nvcc --version | grep release | sed 's/.*release //' |  sed 's/,.*//'))\n\n# detect OS\nOSUPPER = $(shell uname -s 2>/dev/null | tr [:lower:] [:upper:])\n\n#-------------------------------------------------------------------------------\n# Libs\n#-------------------------------------------------------------------------------\n\n\n#-------------------------------------------------------------------------------\n# Includes\n#-------------------------------------------------------------------------------\n\nINC = -I. -I.. -I../test\n\n#-------------------------------------------------------------------------------\n# Libs\n#-------------------------------------------------------------------------------\n\nLIBS += -lcudart \n\n#-------------------------------------------------------------------------------\n# Defines\n#-------------------------------------------------------------------------------\n\nDEFINES = \n\n#-------------------------------------------------------------------------------\n# SM Arch\n#-------------------------------------------------------------------------------\n\nifdef sm\n\tSM_ARCH = $(sm)\nelse \n    SM_ARCH = 200\nendif\n\n# Only one arch per tuning binary\nifeq (350, $(findstring 350, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_35\n    SM_ARCH = 350\nendif\nifeq (300, $(findstring 300, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_30\n    SM_ARCH = 300\nendif\nifeq (200, $(findstring 200, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_20\n    SM_ARCH = 200\nendif\nifeq (130, $(findstring 130, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_13\n    SM_ARCH = 130\nendif\nifeq (110, $(findstring 110, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_11 \n    SM_ARCH = 110\nendif\nifeq (100, $(findstring 100, $(SM_ARCH)))\n    SM_TARGETS = -arch=sm_10 \n    SM_ARCH = 100\nendif\n\n\n#-------------------------------------------------------------------------------\n# Compiler Flags\n#-------------------------------------------------------------------------------\n\nNVCCFLAGS = -Xptxas -v -Xcudafe -\\#\n\n# Help the compiler/linker work with huge numbers of kernels on Windows\nifeq (WIN_NT, $(findstring WIN_NT, $(OSUPPER)))\n\tNVCCFLAGS += -Xcompiler /bigobj -Xcompiler /Zm500\nendif\n\n# 32/64-bit (32-bit device pointers by default) \nifeq ($(force32), 1)\n\tCPU_ARCH = -m32\n\tCPU_ARCH_SUFFIX = i386\nelse\n\tCPU_ARCH = -m64\n\tCPU_ARCH_SUFFIX = x86_64\nendif\n\n# CUDA ABI enable/disable (enabled by default) \nifneq ($(abi), 0)\n\tABI_SUFFIX = abi\nelse \n\tNVCCFLAGS += -Xptxas -abi=no\n\tABI_SUFFIX = noabi\nendif\n\n# NVVM/Open64 middle-end compiler (nvvm by default)\nifeq ($(open64), 1)\n\tNVCCFLAGS += -open64\n\tPTX_SUFFIX = open64\nelse \n\tPTX_SUFFIX = nvvm\nendif\n\n# Verbose toolchain output from nvcc\nifeq ($(verbose), 1)\n\tNVCCFLAGS += -v\nendif\n\n# Keep intermediate compilation artifacts\nifeq ($(keep), 1)\n\tNVCCFLAGS += -keep\nendif\n\n# Data type size to compile a schmoo binary for\nifdef tunesize\n    TUNE_SIZE = $(tunesize)\nelse \n\tTUNE_SIZE = 4\nendif\n\n\nSUFFIX = $(TUNE_SIZE)B_sm$(SM_ARCH)_$(PTX_SUFFIX)_$(NVCC_VERSION)_$(ABI_SUFFIX)_$(CPU_ARCH_SUFFIX)\n\n#-------------------------------------------------------------------------------\n# Dependency Lists\n#-------------------------------------------------------------------------------\n\nrwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))\n\nDEPS =\t ./Makefile \\\n\t\t../test/test_util.h \\\n\t\t$(call rwildcard,../cub/,*.cuh)\n\n\n#-------------------------------------------------------------------------------\n# make default\n#-------------------------------------------------------------------------------\n\ndefault:\n\n\n#-------------------------------------------------------------------------------\n# make clean\n#-------------------------------------------------------------------------------\n\nclean :\n\trm -f bin/*$(CPU_ARCH_SUFFIX)* \n\trm -f *.i* *.cubin *.cu.c *.cudafe* *.fatbin.c *.ptx *.hash *.cu.cpp *.o\n\n\n\n#-------------------------------------------------------------------------------\n# make tune_device_reduce\n#-------------------------------------------------------------------------------\n\ntune_device_reduce: bin/tune_device_reduce_$(SUFFIX)\n\nbin/tune_device_reduce_$(SUFFIX) : tune_device_reduce.cu $(DEPS)\n\tmkdir -p bin\n\t$(NVCC) $(DEFINES) $(SM_TARGETS) -o bin/tune_device_reduce_$(SUFFIX) tune_device_reduce.cu $(NVCCFLAGS) $(CPU_ARCH) $(INC) $(LIBS) -O3 -DTUNE_ARCH=$(SM_ARCH) -DTUNE_SIZE=$(TUNE_SIZE)\n\n"
  },
  {
    "path": "external/cub/tune/tune_device_reduce.cu",
    "content": "/******************************************************************************\n * Copyright (c) 2011, Duane Merrill.  All rights reserved.\n * Copyright (c) 2011-2017, NVIDIA CORPORATION.  All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are met:\n *     * Redistributions of source code must retain the above copyright\n *       notice, this list of conditions and the following disclaimer.\n *     * Redistributions in binary form must reproduce the above copyright\n *       notice, this list of conditions and the following disclaimer in the\n *       documentation and/or other materials provided with the distribution.\n *     * Neither the name of the NVIDIA CORPORATION nor the\n *       names of its contributors may be used to endorse or promote products\n *       derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n *\n ******************************************************************************/\n\n/******************************************************************************\n * Evaluates different tuning configurations of DeviceReduce.\n *\n * The best way to use this program:\n * (1) Find the best all-around single-block tune for a given arch.\n *     For example, 100 samples [1 ..512], 100 timing iterations per config per sample:\n *         ./bin/tune_device_reduce_sm200_nvvm_5.0_abi_i386 --i=100 --s=100 --n=512 --single --device=0\n * (2) Update the single tune in device_reduce.cuh\n * (3) Find the best all-around multi-block tune for a given arch.\n *     For example, 100 samples [single-block tile-size ..  50,331,648], 100 timing iterations per config per sample:\n *         ./bin/tune_device_reduce_sm200_nvvm_5.0_abi_i386 --i=100 --s=100 --device=0\n * (4) Update the multi-block tune in device_reduce.cuh\n *\n ******************************************************************************/\n\n// Ensure printing of CUDA runtime errors to console\n#define CUB_STDERR\n\n#include <vector>\n#include <algorithm>\n#include <stdio.h>\n#include <cub/cub.cuh>\n#include \"../test/test_util.h\"\n\nusing namespace cub;\nusing namespace std;\n\n\n//---------------------------------------------------------------------\n// Globals, constants and typedefs\n//---------------------------------------------------------------------\n\n#ifndef TUNE_ARCH\n#define TUNE_ARCH 100\n#endif\n\nint     g_max_items         = 48 * 1024 * 1024;\nint     g_samples           = 100;\nint     g_timing_iterations        = 2;\nbool    g_verbose           = false;\nbool    g_single            = false;\nbool    g_verify            = true;\nCachingDeviceAllocator  g_allocator;\n\n\n//---------------------------------------------------------------------\n// Host utility subroutines\n//---------------------------------------------------------------------\n\n/**\n * Initialize problem\n */\ntemplate <typename T>\nvoid Initialize(\n    GenMode         gen_mode,\n    T               *h_in,\n    int             num_items)\n{\n    for (int i = 0; i < num_items; ++i)\n    {\n        InitValue(gen_mode, h_in[i], i);\n    }\n}\n\n/**\n * Sequential reduction\n */\ntemplate <typename T, typename ReductionOp>\nT Reduce(\n    T               *h_in,\n    ReductionOp     reduction_op,\n    int             num_items)\n{\n    T retval = h_in[0];\n    for (int i = 1; i < num_items; ++i)\n        retval = reduction_op(retval, h_in[i]);\n\n    return retval;\n}\n\n\n\n//---------------------------------------------------------------------\n// Full tile test generation\n//---------------------------------------------------------------------\n\n\n\n/**\n * Wrapper structure for generating and running different tuning configurations\n */\ntemplate <\n    typename T,\n    typename OffsetT,\n    typename ReductionOp>\nstruct Schmoo\n{\n    //---------------------------------------------------------------------\n    // Types\n    //---------------------------------------------------------------------\n\n    /// Pairing of kernel function pointer and corresponding dispatch params\n    template <typename KernelPtr>\n    struct DispatchTuple\n    {\n        KernelPtr                           kernel_ptr;\n        DeviceReduce::KernelDispachParams   params;\n\n        float                               avg_throughput;\n        float                               best_avg_throughput;\n        OffsetT                              best_size;\n        float                               hmean_speedup;\n\n\n        DispatchTuple() :\n            kernel_ptr(0),\n            params(DeviceReduce::KernelDispachParams()),\n            avg_throughput(0.0),\n            best_avg_throughput(0.0),\n            hmean_speedup(0.0),\n            best_size(0)\n        {}\n    };\n\n    /**\n     * Comparison operator for DispatchTuple.avg_throughput\n     */\n    template <typename Tuple>\n    static bool MinSpeedup(const Tuple &a, const Tuple &b)\n    {\n        float delta = a.hmean_speedup - b.hmean_speedup;\n\n        return ((delta < 0.02) && (delta > -0.02)) ?\n            (a.best_avg_throughput < b.best_avg_throughput) :       // Negligible average performance differences: defer to best performance\n            (a.hmean_speedup < b.hmean_speedup);\n    }\n\n\n\n    /// Multi-block reduction kernel type and dispatch tuple type\n    typedef void (*MultiBlockDeviceReduceKernelPtr)(T*, T*, OffsetT, GridEvenShare<OffsetT>, GridQueue<OffsetT>, ReductionOp);\n    typedef DispatchTuple<MultiBlockDeviceReduceKernelPtr> MultiDispatchTuple;\n\n    /// Single-block reduction kernel type and dispatch tuple type\n    typedef void (*SingleBlockDeviceReduceKernelPtr)(T*, T*, OffsetT, ReductionOp);\n    typedef DispatchTuple<SingleBlockDeviceReduceKernelPtr> SingleDispatchTuple;\n\n\n    //---------------------------------------------------------------------\n    // Fields\n    //---------------------------------------------------------------------\n\n    vector<MultiDispatchTuple> multi_kernels;       // List of generated multi-block kernels\n    vector<SingleDispatchTuple> single_kernels;     // List of generated single-block kernels\n\n\n    //---------------------------------------------------------------------\n    // Kernel enumeration methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Must have smem that fits in the SM\n     * Must have vector load length that divides items per thread\n     */\n    template <typename TilesReducePolicy, typename ReductionOp>\n    struct SmemSize\n    {\n        enum\n        {\n            BYTES = sizeof(typename BlockReduceTiles<TilesReducePolicy, T*, OffsetT, ReductionOp>::TempStorage),\n            IS_OK = ((BYTES < ArchProps<TUNE_ARCH>::SMEM_BYTES) &&\n                     (TilesReducePolicy::ITEMS_PER_THREAD % TilesReducePolicy::VECTOR_LOAD_LENGTH == 0))\n        };\n    };\n\n\n    /**\n     * Specialization that allows kernel generation with the specified TilesReducePolicy\n     */\n    template <\n        typename    TilesReducePolicy,\n        bool        IsOk = SmemSize<TilesReducePolicy, ReductionOp>::IS_OK>\n    struct Ok\n    {\n        /// Enumerate multi-block kernel and add to the list\n        template <typename KernelsVector>\n        static void GenerateMulti(\n            KernelsVector &multi_kernels,\n            int subscription_factor)\n        {\n            MultiDispatchTuple tuple;\n            tuple.params.template Init<TilesReducePolicy>(subscription_factor);\n            tuple.kernel_ptr = ReducePrivatizedKernel<TilesReducePolicy, T*, T*, OffsetT, ReductionOp>;\n            multi_kernels.push_back(tuple);\n        }\n\n\n        /// Enumerate single-block kernel and add to the list\n        template <typename KernelsVector>\n        static void GenerateSingle(KernelsVector &single_kernels)\n        {\n            SingleDispatchTuple tuple;\n            tuple.params.template Init<TilesReducePolicy>();\n            tuple.kernel_ptr = ReduceSingleKernel<TilesReducePolicy, T*, T*, OffsetT, ReductionOp>;\n            single_kernels.push_back(tuple);\n        }\n    };\n\n    /**\n     * Specialization that rejects kernel generation with the specified TilesReducePolicy\n     */\n    template <typename TilesReducePolicy>\n    struct Ok<TilesReducePolicy, false>\n    {\n        template <typename KernelsVector>\n        static void GenerateMulti(KernelsVector &multi_kernels, int subscription_factor) {}\n\n        template <typename KernelsVector>\n        static void GenerateSingle(KernelsVector &single_kernels) {}\n    };\n\n\n    /// Enumerate block-scheduling variations\n    template <\n        int                     BLOCK_THREADS,\n        int                     ITEMS_PER_THREAD,\n        int                     VECTOR_LOAD_LENGTH,\n        BlockReduceAlgorithm    BLOCK_ALGORITHM,\n        CacheLoadModifier      LOAD_MODIFIER>\n    void Enumerate()\n    {\n        // Multi-block kernels\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_RAKE> >::GenerateMulti(multi_kernels, 1);\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_RAKE> >::GenerateMulti(multi_kernels, 2);\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_RAKE> >::GenerateMulti(multi_kernels, 4);\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_RAKE> >::GenerateMulti(multi_kernels, 8);\n#if TUNE_ARCH >= 200\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_DYNAMIC> >::GenerateMulti(multi_kernels, 1);\n#endif\n\n        // Single-block kernels\n        Ok<BlockReduceTilesPolicy<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_MODIFIER, GRID_MAPPING_RAKE> >::GenerateSingle(single_kernels);\n    }\n\n\n    /// Enumerate load modifier variations\n    template <\n        int                     BLOCK_THREADS,\n        int                     ITEMS_PER_THREAD,\n        int                     VECTOR_LOAD_LENGTH,\n        BlockReduceAlgorithm    BLOCK_ALGORITHM>\n    void Enumerate()\n    {\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_DEFAULT>();\n#if TUNE_ARCH >= 350\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_ALGORITHM, LOAD_LDG>();\n#endif\n    }\n\n\n    /// Enumerate block algorithms\n    template <\n        int BLOCK_THREADS,\n        int ITEMS_PER_THREAD,\n        int VECTOR_LOAD_LENGTH>\n    void Enumerate()\n    {\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_REDUCE_RAKING>();\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, VECTOR_LOAD_LENGTH, BLOCK_REDUCE_WARP_REDUCTIONS>();\n    }\n\n\n    /// Enumerate vectorization variations\n    template <\n        int BLOCK_THREADS,\n        int ITEMS_PER_THREAD>\n    void Enumerate()\n    {\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, 1>();\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, 2>();\n        Enumerate<BLOCK_THREADS, ITEMS_PER_THREAD, 4>();\n    }\n\n\n    /// Enumerate thread-granularity variations\n    template <int BLOCK_THREADS>\n    void Enumerate()\n    {\n        Enumerate<BLOCK_THREADS, 7>();\n        Enumerate<BLOCK_THREADS, 8>();\n        Enumerate<BLOCK_THREADS, 9>();\n\n        Enumerate<BLOCK_THREADS, 11>();\n        Enumerate<BLOCK_THREADS, 12>();\n        Enumerate<BLOCK_THREADS, 13>();\n\n        Enumerate<BLOCK_THREADS, 15>();\n        Enumerate<BLOCK_THREADS, 16>();\n        Enumerate<BLOCK_THREADS, 17>();\n\n        Enumerate<BLOCK_THREADS, 19>();\n        Enumerate<BLOCK_THREADS, 20>();\n        Enumerate<BLOCK_THREADS, 21>();\n\n        Enumerate<BLOCK_THREADS, 23>();\n        Enumerate<BLOCK_THREADS, 24>();\n        Enumerate<BLOCK_THREADS, 25>();\n    }\n\n\n    /// Enumerate block size variations\n    void Enumerate()\n    {\n        printf(\"\\nEnumerating kernels\\n\"); fflush(stdout);\n\n        Enumerate<32>();\n        Enumerate<64>();\n        Enumerate<96>();\n        Enumerate<128>();\n        Enumerate<160>();\n        Enumerate<192>();\n        Enumerate<256>();\n        Enumerate<512>();\n    }\n\n\n    //---------------------------------------------------------------------\n    // Test methods\n    //---------------------------------------------------------------------\n\n    /**\n     * Test a configuration\n     */\n    void TestConfiguration(\n        MultiDispatchTuple      &multi_dispatch,\n        SingleDispatchTuple     &single_dispatch,\n        T*                      d_in,\n        T*                      d_out,\n        T*                      h_reference,\n        OffsetT                  num_items,\n        ReductionOp             reduction_op)\n    {\n        // Clear output\n        if (g_verify) CubDebugExit(cudaMemset(d_out, 0, sizeof(T)));\n\n        // Allocate temporary storage\n        void            *d_temp_storage = NULL;\n        size_t          temp_storage_bytes = 0;\n        CubDebugExit(DeviceReduce::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            multi_dispatch.kernel_ptr,\n            single_dispatch.kernel_ptr,\n            FillAndResetDrainKernel<OffsetT>,\n            multi_dispatch.params,\n            single_dispatch.params,\n            d_in,\n            d_out,\n            num_items,\n            reduction_op));\n        CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n        // Warmup/correctness iteration\n        CubDebugExit(DeviceReduce::Dispatch(\n            d_temp_storage,\n            temp_storage_bytes,\n            multi_dispatch.kernel_ptr,\n            single_dispatch.kernel_ptr,\n            FillAndResetDrainKernel<OffsetT>,\n            multi_dispatch.params,\n            single_dispatch.params,\n            d_in,\n            d_out,\n            num_items,\n            reduction_op));\n\n        if (g_verify) CubDebugExit(cudaDeviceSynchronize());\n\n        // Copy out and display results\n        int compare = (g_verify) ?\n            CompareDeviceResults(h_reference, d_out, 1, true, false) :\n            0;\n\n        // Performance\n        GpuTimer gpu_timer;\n        float elapsed_millis = 0.0;\n        for (int i = 0; i < g_timing_iterations; i++)\n        {\n            gpu_timer.Start();\n\n            CubDebugExit(DeviceReduce::Dispatch(\n                d_temp_storage,\n                temp_storage_bytes,\n                multi_dispatch.kernel_ptr,\n                single_dispatch.kernel_ptr,\n                FillAndResetDrainKernel<OffsetT>,\n                multi_dispatch.params,\n                single_dispatch.params,\n                d_in,\n                d_out,\n                num_items,\n                reduction_op));\n\n            gpu_timer.Stop();\n            elapsed_millis += gpu_timer.ElapsedMillis();\n        }\n\n        // Mooch\n        CubDebugExit(cudaDeviceSynchronize());\n\n        float avg_elapsed = elapsed_millis / g_timing_iterations;\n        float avg_throughput = float(num_items) / avg_elapsed / 1000.0 / 1000.0;\n        float avg_bandwidth = avg_throughput * sizeof(T);\n\n        multi_dispatch.avg_throughput = CUB_MAX(avg_throughput, multi_dispatch.avg_throughput);\n        if (avg_throughput > multi_dispatch.best_avg_throughput)\n        {\n            multi_dispatch.best_avg_throughput = avg_throughput;\n            multi_dispatch.best_size = num_items;\n        }\n\n        single_dispatch.avg_throughput = CUB_MAX(avg_throughput, single_dispatch.avg_throughput);\n        if (avg_throughput > single_dispatch.best_avg_throughput)\n        {\n            single_dispatch.best_avg_throughput = avg_throughput;\n            single_dispatch.best_size = num_items;\n        }\n\n        if (g_verbose)\n        {\n            printf(\"\\t%.2f GB/s, multi_dispatch( \", avg_bandwidth);\n            multi_dispatch.params.Print();\n            printf(\" ), single_dispatch( \");\n            single_dispatch.params.Print();\n            printf(\" )\\n\");\n            fflush(stdout);\n        }\n\n        AssertEquals(0, compare);\n\n        // Cleanup temporaries\n        if (d_temp_storage) CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n    }\n\n\n    /**\n     * Evaluate multi-block configurations\n     */\n    void TestMulti(\n        T*                      h_in,\n        T*                      d_in,\n        T*                      d_out,\n        ReductionOp             reduction_op)\n    {\n        // Simple single kernel tuple for use with multi kernel sweep\n        typedef typename DeviceReduce::TunedPolicies<T, OffsetT, TUNE_ARCH>::SinglePolicy SimpleSinglePolicy;\n        SingleDispatchTuple simple_single_tuple;\n        simple_single_tuple.params.template Init<SimpleSinglePolicy>();\n        simple_single_tuple.kernel_ptr = ReduceSingleKernel<SimpleSinglePolicy, T*, T*, OffsetT, ReductionOp>;\n\n        double max_exponent      = log2(double(g_max_items));\n        double min_exponent      = log2(double(simple_single_tuple.params.tile_size));\n        unsigned int max_int     = (unsigned int) -1;\n\n        for (int sample = 0; sample < g_samples; ++sample)\n        {\n            printf(\"\\nMulti-block sample %d, \", sample);\n\n            int num_items;\n            if (sample == 0)\n            {\n                // First sample: use max items\n                num_items = g_max_items;\n                printf(\"num_items: %d\", num_items); fflush(stdout);\n            }\n            else\n            {\n                // Sample a problem size from [2^g_min_exponent, g_max_items].  First 2/3 of the samples are log-distributed, the other 1/3 are uniformly-distributed.\n                unsigned int bits;\n                RandomBits(bits);\n                double scale = double(bits) / max_int;\n\n                if (sample < g_samples / 2)\n                {\n                    // log bias\n                    double exponent = ((max_exponent - min_exponent) * scale) + min_exponent;\n                    num_items = pow(2.0, exponent);\n                    num_items = CUB_MIN(num_items, g_max_items);\n                    printf(\"num_items: %d (2^%.2f)\", num_items, exponent); fflush(stdout);\n                }\n                else\n                {\n                    // uniform bias\n                    num_items = CUB_MAX(pow(2.0, min_exponent), scale * g_max_items);\n                    num_items = CUB_MIN(num_items, g_max_items);\n                    printf(\"num_items: %d (%.2f * %d)\", num_items, scale, g_max_items); fflush(stdout);\n                }\n            }\n            if (g_verbose)\n                printf(\"\\n\");\n            else\n                printf(\", \");\n\n            // Compute reference\n            T h_reference = Reduce(h_in, reduction_op, num_items);\n\n            // Run test on each multi-kernel configuration\n            float best_avg_throughput = 0.0;\n            for (int j = 0; j < multi_kernels.size(); ++j)\n            {\n                multi_kernels[j].avg_throughput = 0.0;\n\n                TestConfiguration(multi_kernels[j], simple_single_tuple, d_in, d_out, &h_reference, num_items, reduction_op);\n\n                best_avg_throughput = CUB_MAX(best_avg_throughput, multi_kernels[j].avg_throughput);\n            }\n\n            // Print best throughput for this problem size\n            printf(\"Best: %.2fe9 items/s (%.2f GB/s)\\n\", best_avg_throughput, best_avg_throughput * sizeof(T));\n\n            // Accumulate speedup (inverse for harmonic mean)\n            for (int j = 0; j < multi_kernels.size(); ++j)\n                multi_kernels[j].hmean_speedup += best_avg_throughput / multi_kernels[j].avg_throughput;\n        }\n\n        // Find max overall throughput and compute hmean speedups\n        float overall_max_throughput = 0.0;\n        for (int j = 0; j < multi_kernels.size(); ++j)\n        {\n            overall_max_throughput = CUB_MAX(overall_max_throughput, multi_kernels[j].best_avg_throughput);\n            multi_kernels[j].hmean_speedup = float(g_samples) / multi_kernels[j].hmean_speedup;\n        }\n\n        // Sort by cumulative speedup\n        sort(multi_kernels.begin(), multi_kernels.end(), MinSpeedup<MultiDispatchTuple>);\n\n        // Print ranked multi configurations\n        printf(\"\\nRanked multi_kernels:\\n\");\n        for (int j = 0; j < multi_kernels.size(); ++j)\n        {\n            printf(\"\\t (%d) params( \", multi_kernels.size() - j);\n            multi_kernels[j].params.Print();\n            printf(\" ) hmean speedup: %.3f, best throughput %.2f @ %d elements (%.2f GB/s, %.2f%%)\\n\",\n                multi_kernels[j].hmean_speedup,\n                multi_kernels[j].best_avg_throughput,\n                (int) multi_kernels[j].best_size,\n                multi_kernels[j].best_avg_throughput * sizeof(T),\n                multi_kernels[j].best_avg_throughput / overall_max_throughput);\n        }\n\n        printf(\"\\nMax multi-block throughput %.2f (%.2f GB/s)\\n\", overall_max_throughput, overall_max_throughput * sizeof(T));\n    }\n\n\n    /**\n     * Evaluate single-block configurations\n     */\n    void TestSingle(\n        T*                      h_in,\n        T*                      d_in,\n        T*                      d_out,\n        ReductionOp             reduction_op)\n     {\n        // Construct a NULL-ptr multi-kernel tuple that forces a single-kernel pass\n        MultiDispatchTuple multi_tuple;\n\n        double max_exponent     = log2(double(g_max_items));\n        unsigned int max_int    = (unsigned int) -1;\n\n        for (int sample = 0; sample < g_samples; ++sample)\n        {\n            printf(\"\\nSingle-block sample %d, \", sample);\n\n            int num_items;\n            if (sample == 0)\n            {\n                // First sample: use max items\n                num_items = g_max_items;\n                printf(\"num_items: %d\", num_items); fflush(stdout);\n            }\n            else\n            {\n                // Sample a problem size from [2, g_max_items], log-distributed\n                unsigned int bits;\n                RandomBits(bits);\n                double scale = double(bits) / max_int;\n                double exponent = ((max_exponent - 1) * scale) + 1;\n                num_items = pow(2.0, exponent);\n                printf(\"num_items: %d (2^%.2f)\", num_items, exponent); fflush(stdout);\n            }\n\n            if (g_verbose)\n                printf(\"\\n\");\n            else\n                printf(\", \");\n\n            // Compute reference\n            T h_reference = Reduce(h_in, reduction_op, num_items);\n\n            // Run test on each single-kernel configuration (pick first multi-config to use, which shouldn't be\n            float best_avg_throughput = 0.0;\n            for (int j = 0; j < single_kernels.size(); ++j)\n            {\n                single_kernels[j].avg_throughput = 0.0;\n\n                TestConfiguration(multi_tuple, single_kernels[j], d_in, d_out, &h_reference, num_items, reduction_op);\n\n                best_avg_throughput = CUB_MAX(best_avg_throughput, single_kernels[j].avg_throughput);\n            }\n\n            // Print best throughput for this problem size\n            printf(\"Best: %.2fe9 items/s (%.2f GB/s)\\n\", best_avg_throughput, best_avg_throughput * sizeof(T));\n\n            // Accumulate speedup (inverse for harmonic mean)\n            for (int j = 0; j < single_kernels.size(); ++j)\n                single_kernels[j].hmean_speedup += best_avg_throughput / single_kernels[j].avg_throughput;\n        }\n\n        // Find max overall throughput and compute hmean speedups\n        float overall_max_throughput = 0.0;\n        for (int j = 0; j < single_kernels.size(); ++j)\n        {\n            overall_max_throughput = CUB_MAX(overall_max_throughput, single_kernels[j].best_avg_throughput);\n            single_kernels[j].hmean_speedup = float(g_samples) / single_kernels[j].hmean_speedup;\n        }\n\n        // Sort by cumulative speedup\n        sort(single_kernels.begin(), single_kernels.end(), MinSpeedup<SingleDispatchTuple>);\n\n        // Print ranked single configurations\n        printf(\"\\nRanked single_kernels:\\n\");\n        for (int j = 0; j < single_kernels.size(); ++j)\n        {\n            printf(\"\\t (%d) params( \", single_kernels.size() - j);\n            single_kernels[j].params.Print();\n            printf(\" ) hmean speedup: %.3f, best throughput %.2f @ %d elements (%.2f GB/s, %.2f%%)\\n\",\n                single_kernels[j].hmean_speedup,\n                single_kernels[j].best_avg_throughput,\n                (int) single_kernels[j].best_size,\n                single_kernels[j].best_avg_throughput * sizeof(T),\n                single_kernels[j].best_avg_throughput / overall_max_throughput);\n        }\n\n        printf(\"\\nMax single-block throughput %.2f (%.2f GB/s)\\n\", overall_max_throughput, overall_max_throughput * sizeof(T));\n    }\n\n};\n\n\n\n//---------------------------------------------------------------------\n// Main\n//---------------------------------------------------------------------\n\n/**\n * Main\n */\nint main(int argc, char** argv)\n{\n    // Initialize command line\n    CommandLineArgs args(argc, argv);\n    args.GetCmdLineArgument(\"n\", g_max_items);\n    args.GetCmdLineArgument(\"s\", g_samples);\n    args.GetCmdLineArgument(\"i\", g_timing_iterations);\n    g_verbose = args.CheckCmdLineFlag(\"v\");\n    g_single = args.CheckCmdLineFlag(\"single\");\n    g_verify = !args.CheckCmdLineFlag(\"noverify\");\n\n    // Print usage\n    if (args.CheckCmdLineFlag(\"help\"))\n    {\n        printf(\"%s \"\n            \"[--device=<device-id>] \"\n            \"[--n=<max items>]\"\n            \"[--s=<samples>]\"\n            \"[--i=<timing iterations>]\"\n            \"[--single]\"\n            \"[--v]\"\n            \"[--noverify]\"\n            \"\\n\", argv[0]);\n        exit(0);\n    }\n\n    // Initialize device\n    CubDebugExit(args.DeviceInit());\n\n#if (TUNE_SIZE == 1)\n    typedef unsigned char T;\n#elif (TUNE_SIZE == 2)\n    typedef unsigned short T;\n#elif (TUNE_SIZE == 4)\n    typedef unsigned int T;\n#elif (TUNE_SIZE == 8)\n    typedef unsigned long long T;\n#else\n    // Default\n    typedef unsigned int T;\n#endif\n\n    typedef unsigned int OffsetT;\n    Sum reduction_op;\n\n    // Enumerate kernels\n    Schmoo<T, OffsetT, Sum > schmoo;\n    schmoo.Enumerate();\n\n    // Allocate host arrays\n    T *h_in = new T[g_max_items];\n\n    // Initialize problem\n    Initialize(UNIFORM, h_in, g_max_items);\n\n    // Initialize device arrays\n    T *d_in = NULL;\n    T *d_out = NULL;\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_in, sizeof(T) * g_max_items));\n    CubDebugExit(g_allocator.DeviceAllocate((void**)&d_out, sizeof(T) * 1));\n    CubDebugExit(cudaMemcpy(d_in, h_in, sizeof(T) * g_max_items, cudaMemcpyHostToDevice));\n\n    // Test kernels\n    if (g_single)\n        schmoo.TestSingle(h_in, d_in, d_out, reduction_op);\n    else\n        schmoo.TestMulti(h_in, d_in, d_out, reduction_op);\n\n    // Cleanup\n    if (h_in) delete[] h_in;\n    if (d_in) CubDebugExit(g_allocator.DeviceFree(d_in));\n    if (d_out) CubDebugExit(g_allocator.DeviceFree(d_out));\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "src/bitonicTopK.cuh",
    "content": "#pragma once\n\n#include <cuda.h>\n#include <cub/util_allocator.cuh>\n#include <algorithm>\n\n#include \"sharedmem.cuh\"\n\nusing namespace std;\nusing namespace cub;\n\n#define NUM_ELEM_PT 16\n#define NUM_ELEM_BITSHIFT 4\n\n//#define K 32\n//#define KLog2 5\n\n#define ORDERV(x,a,b) { bool swap = reverse ^ (x[a]<x[b]); \\\n      T auxa = x[a]; \\\n      if (swap) { x[a] = x[b]; x[b] = auxa; } }\n      //T auxa = x[a]; T auxb = x[b]; \\\n      //x[a] = (swap)?auxb:auxa; x[b] = (swap)?auxa:auxb;}\n\n#define B2V(x,a) { ORDERV(x,a,a+1) }\n#define B4V(x,a) { for (int i4=0;i4<2;i4++) { ORDERV(x,a+i4,a+i4+2) } B2V(x,a) B2V(x,a+2) }\n#define B8V(x,a) { for (int i8=0;i8<4;i8++) { ORDERV(x,a+i8,a+i8+4) } B4V(x,a) B4V(x,a+4) }\n#define B16V(x,a) { for (int i16=0;i16<8;i16++) { ORDERV(x,a+i16,a+i16+8) } B8V(x,a) B8V(x,a+8) }\n#define B32V(x,a) { for (int i32=0;i32<16;i32++) { ORDERV(x,a+i32,a+i32+16) } B16V(x,a) B16V(x,a+16) }\n#define B64V(x,a) { for (int i64=0;i64<32;i64++) { ORDERV(x,a+i64,a+i64+32) } B32V(x,a) B32V(x,a+32) }\n\ntemplate<typename T>\n__forceinline__\n__device__  T get(T* sdata, int i) {\n  return sdata[i + (i>>5)];\n}\n\n#define set(a,b,c) { int tempIndex = b; a[tempIndex + (tempIndex >> 5)] = c;  }\n\n#define NUM_GROUPS (NUM_ELEM_PT/2)\n#define NUM_GROUPS_BITSHIFT (NUM_ELEM_BITSHIFT-1)\n\n#define RUN_64(X) { \\\n  inc >>= 5; \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 6) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(32 * X); j++) { \\\n    for (int i=0; i<64; i++) x[i] = get(sdata, tCur+i*inc); \\\n    B64V(x,0); \\\n    for (int i=0; i<64; i++) set(sdata, tCur+i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define RUN_32(X) { \\\n  inc >>= 4; \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 5) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(16 * X); j++) { \\\n    for (int i=0; i<32; i++) x[i] = get(sdata, tCur+i*inc); \\\n    B32V(x,0); \\\n    for (int i=0; i<32; i++) set(sdata, tCur+i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define RUN_16(X) { \\\n  inc >>= 3; \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 4) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(8 * X); j++) { \\\n    for (int i=0; i<16; i++) x[i] = get(sdata, tCur+i*inc); \\\n    B16V(x,0); \\\n    for (int i=0; i<16; i++) set(sdata, tCur+i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define RUN_8(X) { \\\n  inc >>= 2; \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 3) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(4 * X); j++) { \\\n    for (int i=0; i<8; i++) x[i] = get(sdata, tCur+i*inc); \\\n    B8V(x,0); \\\n    for (int i=0; i<8; i++) set(sdata, tCur+i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define RUN_4(X) { \\\n  inc >>= 1; \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 2) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(2 * X); j++) { \\\n    for (int i=0;i<4;i++) x[i] = get(sdata, 4*wg*j + tCur + i*inc); \\\n    B4V(x,0); \\\n    for (int i=0;i<4;i++) set(sdata, 4*wg*j + tCur + i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define RUN_2(X) { \\\n  low = t & (inc - 1); \\\n  tCur = ((t - low) << 1) + low; \\\n  reverse = ((dir & tCur) == 0); \\\n  for (int j=0; j<NUM_GROUPS/(X); j++) { \\\n    for (int i=0;i<2;i++) x[i] = get(sdata, 2*wg*j + tCur + i*inc); \\\n    B2V(x,0); \\\n    for (int i=0;i<2;i++) set(sdata, 2*wg*j + tCur + i*inc, x[i]); \\\n  } \\\n  inc >>= 1; \\\n}\n\n#define REDUCE(X) { \\\n  tCur = ((t >> klog2) << (klog2 + 1)) + (t & (k-1)); \\\n  for(int j=0; j<NUM_GROUPS/(X); j++) { \\\n    x[j] = max(get(sdata, 2*wg*j + tCur), get(sdata, 2*wg*j + tCur + k)); \\\n  } \\\n  __syncthreads(); \\\n  for(int j=0; j<NUM_GROUPS/(X); j++) { \\\n    set(sdata, wg*j + t, x[j]); \\\n  } \\\n}\n\ntemplate<typename T>\n__global__ void Bitonic_TopKLocalSortInPlace(T* __restrict__ in, T* __restrict__ out,\n  const int k, const int klog2)\n{\n/*  const int k = K;*/\n  /*const int klog2 = KLog2;*/\n\n  // Shared mem size is determined by the host app at run time.\n  // For n elements, we have n * 33/32 shared memory.\n  // We use this to break bank conflicts.\n  SharedMemory<T> smem;\n  T* sdata = smem.getPointer();\n\n  const int t = threadIdx.x; // index in workgroup\n  const int wg = blockDim.x; // workgroup size = block size, power of 2\n  const int gid = blockIdx.x;\n\n  int length = min(NUM_GROUPS, k >> 1);\n  int inc = length;\n  inc >>= NUM_GROUPS_BITSHIFT;\n  int low = t & (inc - 1);\n  int dir = length << 1;\n  bool reverse;\n\n  T x[NUM_ELEM_PT];\n\n  // Move IN, OUT to block start\n  in += NUM_ELEM_PT * gid * wg;\n\n  int tCur = t << NUM_ELEM_BITSHIFT;\n  for (int i=0; i<NUM_ELEM_PT; i++) x[i] = in[tCur + i];\n\n  for (int i=0; i<NUM_ELEM_PT; i+=2) {\n    reverse = ((i >> 1) + 1)&1;\n    B2V(x,i);\n  }\n  if (k > 2) {\n#if NUM_ELEM_PT > 4\n    for (int i=0; i<NUM_ELEM_PT; i+=4) {\n      reverse = ((i >> 2) + 1)&1;\n      B4V(x,i);\n    }\n    if (k > 4) {\n#if NUM_ELEM_PT > 8\n      for (int i=0; i<NUM_ELEM_PT; i+=8) {\n        reverse = ((i >> 3) + 1)&1;\n        B8V(x,i);\n      }\n      if (k > 8) {\n#if NUM_ELEM_PT > 16\n        for (int i=0; i<NUM_ELEM_PT; i+=16) {\n          reverse = ((i >> 4) + 1)&1;\n          B16V(x,i);\n        }\n        if (k > 16) {\n#if NUM_ELEM_PT > 32\n          for (int i=0; i<NUM_ELEM_PT; i+=32) {\n            reverse = ((i >> 5) + 1)&1;\n            B32V(x,i);\n          }\n          if (k > 32) {\n            reverse = ((dir & tCur) == 0); B64V(x,0);\n          }\n#else\n          reverse = ((dir & tCur) == 0); B32V(x,0);\n#endif\n        }\n#else\n        reverse = ((dir & tCur) == 0); B16V(x,0);\n#endif\n      }\n#else\n      reverse = ((dir & tCur) == 0); B8V(x,0);\n#endif\n    }\n#else\n    reverse = ((dir & tCur) == 0); B4V(x,0);\n#endif\n  }\n\n  for (int i=0; i<NUM_ELEM_PT; i++) set(sdata, tCur+i, x[i]);\n\n  __syncthreads();\n\n  // Complete the remaining steps to create sorted sequences of length k.\n  int mod;\n  unsigned int mask;\n\n  for (length=NUM_ELEM_PT; length<k; length<<=1)\n  {\n    dir = length << 1;\n    // Loop on comparison distance (between keys)\n    inc = length;\n    mod = inc;\n    mask = ~(NUM_ELEM_PT/(1) - 1);\n    while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 0);\n\n    if (mod & 1)\n    {\n      RUN_2(1)\n      __syncthreads();\n    }\n    if (mod & 2)\n    {\n      RUN_4(1)\n      __syncthreads();\n    }\n#if NUM_ELEM_PT > 8\n    if (mod & 4)\n    {\n      RUN_8(1)\n      __syncthreads();\n    }\n#if NUM_ELEM_PT > 16\n    if (mod & 8)\n    {\n      RUN_16(1)\n      __syncthreads();\n    }\n    while (inc > 8)\n    {\n      RUN_32(1)\n      __syncthreads();\n    }\n#else\n    while (inc > 4)\n    {\n      RUN_16(1)\n      __syncthreads();\n    }\n#endif // NUM_ELEM_PT > 16\n#else\n    while (inc > 2)\n    {\n      RUN_8(1)\n      __syncthreads();\n    }\n#endif // NUM_ELEM_PT > 8\n  }\n\n  // Step 2: Reduce the size by factor 2 by pairwise comparing adjacent sequences.\n  REDUCE(1)\n  __syncthreads();\n  // End of Step 2;\n\n  // Step 3: Construct sorted sequence of length k from bitonic sequence of length k.\n  // We now have n/2 elements.\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(1) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 0);\n\n  if (mod & 1)\n  {\n    RUN_2(2)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 4\n  if (mod & 2)\n  {\n    RUN_4(2)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 8\n  if (mod & 4)\n  {\n    RUN_8(2)\n    __syncthreads();\n  }\n  while (inc > 4)\n  {\n    if (t < (wg >> 1)) {\n      RUN_16(1)\n    } else {\n      inc >>= 4;\n    }\n    __syncthreads();\n  }\n#else\n  while (inc > 2)\n  {\n    RUN_8(2)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 16\n#else\n  while (inc > 1)\n  {\n    RUN_4(2)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 8\n\n  // Step 4: Reduce size again by 2.\n  REDUCE(2)\n  __syncthreads();\n  // End of Step 1;\n\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(2) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 1);\n\n#if NUM_ELEM_PT > 4\n  if (mod & 1)\n  {\n    RUN_2(4)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 8\n  if (mod & 2)\n  {\n    RUN_4(4)\n    __syncthreads();\n  }\n  while (inc > 2)\n  {\n    if (t < (wg >> 1)) {\n      RUN_8(2)\n    } else {\n      inc >>= 3;\n    }\n    __syncthreads();\n  }\n#else\n  while (inc > 1)\n  {\n    RUN_4(4)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 16\n#else\n  while (inc > 0)\n  {\n    RUN_2(4)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 8 while (inc > 0)\n\n  // Step 4: Reduce size again by 2.\n  REDUCE(4)\n  __syncthreads();\n  // End of Step 1;\n\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(4) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 2);\n\n  if (mod & 1)\n  {\n    RUN_2(8)\n    __syncthreads();\n  }\n  while (inc > 0)\n  {\n    if (t < (wg >> 1)) {\n      RUN_4(4)\n    } else {\n      inc >>= 2;\n    }\n    __syncthreads();\n  }\n\n  out += (NUM_ELEM_PT/16) * gid * wg;\n  tCur = ((t >> klog2) << (klog2+1)) + (t&(k-1));\n  for (int j=0; j<NUM_GROUPS/8; j++) {\n    T x0 = get(sdata, 2*wg*j + tCur);\n    T x1 = get(sdata, 2*wg*j + tCur + k);\n    out[wg*j + t] = max(x0, x1);\n  }\n\n/*  out += (NUM_ELEM_PT/8) * gid * wg;*/\n  //tCur = ((t >> klog2) << (klog2+1)) + (t&(k-1));\n  //for (int j=0; j<NUM_GROUPS/4; j++) {\n    //T x0 = get(sdata, 2*wg*j + tCur);\n    //T x1 = get(sdata, 2*wg*j + tCur + k);\n    //out[wg*j + t] = max(x0, x1);\n  /*}*/\n}\n\ntemplate<typename T>\n__global__ void Bitonic_TopKReduce(T* __restrict__ in, T* __restrict__ out,\n  const int k, const int klog2)\n{\n/*  const int k = K;*/\n  /*const int klog2 = KLog2;*/\n\n  // Shared mem size is determined by the host app at run time.\n  // For n elements, we have n * 33/32 shared memory.\n  // We use this to break bank conflicts.\n  SharedMemory<T> smem;\n  T* sdata = smem.getPointer();\n\n  const int t = threadIdx.x; // index in workgroup\n  const int wg = blockDim.x; // workgroup size = block size, power of 2\n  const int gid = blockIdx.x;\n\n  int length = min(NUM_GROUPS, k >> 1);\n  int inc = length;\n  inc >>= NUM_GROUPS_BITSHIFT;\n  int low = t & (inc - 1);\n  int dir = length << 1;\n  bool reverse;\n\n  T x[NUM_ELEM_PT];\n\n  // Move IN, OUT to block start\n  in += NUM_ELEM_PT * gid * wg;\n\n  int tCur = t << NUM_ELEM_BITSHIFT;\n  for (int i=0; i<NUM_ELEM_PT; i++) x[i] = in[tCur + i];\n  for (int i=0; i<NUM_ELEM_PT; i++) set(sdata, tCur+i, x[i]);\n\n  __syncthreads();\n\n  // Complete the remaining steps to create sorted sequences of length k.\n  int mod;\n  unsigned int mask;\n\n    length = (k >> 1);\n    dir = length << 1;\n    // Loop on comparison distance (between keys)\n    inc = length;\n    mod = inc;\n    mask = ~(NUM_ELEM_PT/(1) - 1);\n    while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 0);\n\n    if (mod & 1)\n    {\n      RUN_2(1)\n      __syncthreads();\n    }\n    if (mod & 2)\n    {\n      RUN_4(1)\n      __syncthreads();\n    }\n#if NUM_ELEM_PT > 8\n    if (mod & 4)\n    {\n      RUN_8(1)\n      __syncthreads();\n    }\n#if NUM_ELEM_PT > 16\n    if (mod & 8)\n    {\n      RUN_16(1)\n      __syncthreads();\n    }\n    while (inc > 8)\n    {\n      RUN_32(1)\n      __syncthreads();\n    }\n#else\n    while (inc > 4)\n    {\n      RUN_16(1)\n      __syncthreads();\n    }\n#endif // NUM_ELEM_PT > 16\n#else\n    while (inc > 2)\n    {\n      RUN_8(1)\n      __syncthreads();\n    }\n#endif // NUM_ELEM_PT > 8\n\n  // Step 2: Reduce the size by factor 2 by pairwise comparing adjacent sequences.\n  REDUCE(1)\n  __syncthreads();\n  // End of Step 2;\n\n  // Step 3: Construct sorted sequence of length k from bitonic sequence of length k.\n  // We now have n/2 elements.\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(1) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 0);\n\n  if (mod & 1)\n  {\n    RUN_2(2)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 4\n  if (mod & 2)\n  {\n    RUN_4(2)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 8\n  if (mod & 4)\n  {\n    RUN_8(2)\n    __syncthreads();\n  }\n  while (inc > 4)\n  {\n    if (t < (wg >> 1)) {\n      RUN_16(1)\n    } else {\n      inc >>= 4;\n    }\n    __syncthreads();\n  }\n#else\n  while (inc > 2)\n  {\n    RUN_8(2)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 16\n#else\n  while (inc > 1)\n  {\n    RUN_4(2)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 8\n\n  // Step 4: Reduce size again by 2.\n  REDUCE(2)\n  __syncthreads();\n  // End of Step 1;\n\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(2) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 1);\n\n#if NUM_ELEM_PT > 4\n  if (mod & 1)\n  {\n    RUN_2(4)\n    __syncthreads();\n  }\n#if NUM_ELEM_PT > 8\n  if (mod & 2)\n  {\n    RUN_4(4)\n    __syncthreads();\n  }\n  while (inc > 2)\n  {\n    if (t < (wg >> 1)) {\n      RUN_8(2)\n    } else {\n      inc >>= 3;\n    }\n    __syncthreads();\n  }\n#else\n  while (inc > 1)\n  {\n    RUN_4(4)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 16\n#else\n  while (inc > 0)\n  {\n    RUN_2(4)\n    __syncthreads();\n  }\n#endif // NUM_ELEM_PT > 8 while (inc > 0)\n\n  // Step 4: Reduce size again by 2.\n  REDUCE(4)\n  __syncthreads();\n  // End of Step 1;\n\n  length = k >> 1;\n  dir = length << 1;\n  // Loop on comparison distance (between keys)\n  inc = length;\n  mod = inc;\n  mask = ~(NUM_ELEM_PT/(4) - 1);\n  while ((mod & mask) != 0) mod >>= (NUM_ELEM_BITSHIFT - 2);\n\n  if (mod & 1)\n  {\n    RUN_2(8)\n    __syncthreads();\n  }\n  while (inc > 0)\n  {\n    if (t < (wg >> 1)) {\n      RUN_4(4)\n    } else {\n      inc >>= 2;\n    }\n    __syncthreads();\n  }\n\n  out += (NUM_ELEM_PT/16) * gid * wg;\n  tCur = ((t >> klog2) << (klog2+1)) + (t&(k-1));\n  for (int j=0; j<NUM_GROUPS/8; j++) {\n    T x0 = get(sdata, 2*wg*j + tCur);\n    T x1 = get(sdata, 2*wg*j + tCur + k);\n    out[wg*j + t] = max(x0, x1);\n  }\n}\n\nconst int tab32[32] = {\n     0,  9,  1, 10, 13, 21,  2, 29,\n    11, 14, 16, 18, 22, 25,  3, 30,\n     8, 12, 20, 28, 15, 17, 24,  7,\n    19, 27, 23,  6, 26,  5,  4, 31};\n\nint log2_32 (uint value)\n{\n  value |= value >> 1;\n  value |= value >> 2;\n  value |= value >> 4;\n  value |= value >> 8;\n  value |= value >> 16;\n  return tab32[(uint)(value*0x07C4ACDD) >> 27];\n}\n\ntemplate<typename KeyT>\ncudaError_t bitonicTopK(KeyT *d_keys_in, unsigned int num_items, unsigned int k, KeyT *d_keys_out,\n    CachingDeviceAllocator&  g_allocator) {\n  if (k < 16) k = 16;\n\n  int klog2 = log2_32(k);\n\n  DoubleBuffer<KeyT> d_keys;\n  d_keys.d_buffers[0] = d_keys_in;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(KeyT) * num_items));\n\n  int current = 0;\n  int numThreads = num_items;\n\n  int wg_size = max(64,k);\n\n  numThreads >>= 1; // Each thread processes 2 elements.\n  numThreads >>= NUM_GROUPS_BITSHIFT;\n  Bitonic_TopKLocalSortInPlace<KeyT><<<numThreads/wg_size, wg_size, ((2*NUM_GROUPS*wg_size*33)/32)*sizeof(KeyT)>>>(d_keys.Current(), d_keys.Alternate(), k, klog2);\n  current = 1-current;\n\n  // Toggle the buffer index in the double buffer\n  d_keys.selector = d_keys.selector ^ 1;\n\n  numThreads >>= (1 + NUM_GROUPS_BITSHIFT);\n\n  while (numThreads >= wg_size)\n  {\n    Bitonic_TopKReduce<KeyT><<<numThreads/wg_size, wg_size, ((2*NUM_GROUPS*wg_size*33)/32)*sizeof(KeyT)>>>(d_keys.Current(), d_keys.Alternate(), k, klog2);\n\n    // Toggle the buffer index in the double buffer\n    d_keys.selector = d_keys.selector ^ 1;\n\n    numThreads >>= (1 + NUM_GROUPS_BITSHIFT);\n  }\n\n  KeyT* res_vec = (KeyT*) malloc(sizeof(KeyT) * 2 * numThreads * NUM_GROUPS);\n  cudaMemcpy(res_vec, d_keys.Current(), 2 * numThreads * NUM_GROUPS * sizeof(KeyT), cudaMemcpyDeviceToHost);\n  std::sort(res_vec, res_vec + 2*numThreads*NUM_GROUPS, std::greater<KeyT>());\n  cudaMemcpy(d_keys_out, res_vec, k * sizeof(KeyT), cudaMemcpyHostToDevice);\n\n  if (d_keys.d_buffers[1])\n    CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[1]));\n\n  return cudaSuccess;\n}\n\n\n"
  },
  {
    "path": "src/radixSelectTopK.cuh",
    "content": "#include <cuda.h>\n#include <cub/device/device_radix_sort.cuh>\n#include <cub/util_allocator.cuh>\n\nusing namespace cub;\nusing namespace std;\n\n/**\n * Computes the histogram over the digit values of an array of keys that MUST have a length of an integer multiple of (KPT * blockDim.x).\n * The padding to the integer multiple can be done by adding 0's at the end and subtracting the number of padded 0's from the final result's 0 bin.\n * The 2^NUM_BITS possible counts (0..2^NUM_BITSNUM_BITS-1) will be placed in global_histo.\n * @param keys            [IN]  The keys for which to compute the histogram\n * @param digit           [IN]\n * @param global_histo        [OUT] The array of element counts, MUST be 256 in size.\n * @param per_block_histo     [OUT]\n */\ntemplate<\n  typename KeyT,    // Data type of the keys within device memory. Data will be twiddled (if necessary) to unsigned type\n  typename IndexT,  // Data type used for key's offsets and counters (limits number of supported keys, uint = 2^32)\n  int NUM_BITS,     // Number of bits being sorted at a time\n  int KPT,          // Number of keys per thread\n  int TPB,          // Number of threads per block\n  int PRE_SORT_RUNS_LENGTH // For values greater than 1, this causes to sort a thread's keys by runs of a given length to improve run-length encoded updates to shared memory.\n>\n__global__ void rdxsrt_histogram(KeyT *__restrict__ keys, const uint digit, IndexT *global_histo)\n{\n  /*** TYPEDEFs***/\n  typedef Traits<KeyT>                        KeyTraits;\n  typedef typename KeyTraits::UnsignedBits    UnsignedBits;\n  /*typedef LoadUnit<IndexT, RDXSRT_LOAD_STRIDE_WARP, KPT, TPB> KeyLoader;*/\n\n  /*** DECLARATIONS ***/\n  UnsignedBits tloc_keys[KPT];\n  uint tloc_masked[KPT];\n  __shared__ uint shared_bins[0x01<<NUM_BITS];\n\n  /*** INIT SHARED HISTO ***/\n  if(threadIdx.x < 32){\n    #pragma unroll\n    for(int i=0;i<(0x01<<NUM_BITS);i+=32){\n      shared_bins[i+threadIdx.x] = 0;\n    }\n  }\n  __syncthreads();\n\n  /*** GET KEYS & PREPARE KEYS FOR HISTO ***/\n  // Bucket index used to determine the memory offset of the bucket's global histogram\n  const uint bucket_idx = 0;\n  // This thread block's keys memory offset, pointing to the index of its first key\n  const IndexT block_offset = (blockDim.x * blockIdx.x * KPT);\n\n  // Load keys\n  // KeyLoader(block_offset, threadIdx.x).template LoadStrided<UnsignedBits, KeyT, 0, KPT>(keys, tloc_keys);\n  #pragma unroll\n  for (int i=0; i<KPT; i++) {\n    tloc_keys[i] = reinterpret_cast<UnsignedBits*>(keys)[block_offset + threadIdx.x + blockDim.x * i];\n  }\n\n#if true || USE_RLE_HISTO\n  // Mask\n  #pragma unroll\n  for (int i=0; i<KPT; i++) {\n    tloc_keys[i] = KeyTraits::TwiddleIn(tloc_keys[i]);\n    tloc_masked[i] = (tloc_keys[i]>>((sizeof(KeyT)*8)-(NUM_BITS*(digit+1))))&((0x01<<NUM_BITS)-1);\n  }\n\n#if 0\n  /*** SORT RUNS ***/\n  if(PRE_SORT_RUNS_LENGTH>1){\n    SortingNetwork<uint>::sort_runs<PRE_SORT_RUNS_LENGTH>(tloc_masked);\n  }\n#endif\n\n  /*** COMPUTE HISTO ***/\n  uint rle = 1;\n  #pragma unroll\n  for(int i=1; i<KPT; i++){\n    if(tloc_masked[i] == tloc_masked[i-1])\n      rle++;\n    else{\n      atomicAdd(&shared_bins[tloc_masked[i-1]], rle);\n      rle=1;\n    }\n  }\n  atomicAdd(&shared_bins[tloc_masked[KPT-1]], rle);\n#else\n  #pragma unroll\n  for(int i=0; i<KPT; i++){\n    tloc_masked[i] = (tloc_keys[i]>>((sizeof(KeyT)*8)-(NUM_BITS*(digit+1))))&((0x01<<NUM_BITS)-1);\n    atomicAdd(&shared_bins[tloc_masked[i]], 1);\n  }\n#endif\n\n  // Make sure we've got the counts from all threads\n  __syncthreads();\n\n  /*** Write shared histo to global histo ***/\n  if(threadIdx.x < 32){\n    for(int i=0;i<(0x01<<NUM_BITS);i+=32){\n      atomicAdd(&global_histo[(0x01<<NUM_BITS)*bucket_idx+i+threadIdx.x], shared_bins[i+threadIdx.x]);\n      // per_block_histo[blockIdx.x*(0x01<<NUM_BITS)+i+threadIdx.x] = shared_bins[i+threadIdx.x];\n    }\n  }\n}\n\ntemplate<\n  typename KeyT,    // Data type of the keys within device memory. Data will be twiddled (if necessary) to unsigned type\n  typename IndexT,  // Data type used for key's offsets and counters (limits number of supported keys, uint = 2^32)\n  int NUM_BITS,     // Number of bits being sorted at a time\n  int KPT,          // Number of keys per thread\n  int TPB,          // Number of threads per block\n  int PRE_SORT_RUNS_LENGTH // For values greater than 1, this causes to sort a thread's keys by runs of a given length to improve run-length encoded updates to shared memory.\n>\n__global__ void rdxsrt_histogram_with_guards(KeyT *__restrict__ keys, const uint digit, IndexT *global_histo, const IndexT total_keys, const int block_index_offset)\n{\n  /*** TYPEDEFs***/\n  typedef Traits<KeyT>                        KeyTraits;\n  typedef typename KeyTraits::UnsignedBits    UnsignedBits;\n  /*typedef LoadUnit<IndexT, RDXSRT_LOAD_STRIDE_WARP, KPT, TPB> KeyLoader;*/\n\n  /*** DECLARATIONS ***/\n  UnsignedBits tloc_keys[KPT];\n  uint tloc_masked[KPT];\n  __shared__ uint shared_bins[(0x01<<NUM_BITS) + 1];\n\n  /*** INIT SHARED HISTO ***/\n  if (threadIdx.x < 32) {\n    #pragma unroll\n    for(int i=0;i<(0x01<<NUM_BITS);i+=32){\n      shared_bins[i+threadIdx.x] = 0;\n    }\n  }\n  __syncthreads();\n\n  /*** GET KEYS & PREPARE KEYS FOR HISTO ***/\n  // Bucket index used to determine the memory offset of the bucket's global histogram\n  const uint bucket_idx = 0;\n  // This thread block's keys memory offset, pointing to the index of its first key\n  const IndexT block_offset = (blockDim.x * (block_index_offset + blockIdx.x) * KPT);\n\n  // Maximum number of keys the block may fetch\n  const IndexT block_max_num_keys = total_keys - block_offset;\n  // KeyLoader(block_offset, threadIdx.x).template LoadStridedWithGuards<UnsignedBits, KeyT, 0, KPT>(keys, tloc_keys, block_max_num_keys);\n  #pragma unroll\n  for (int i=0; i<KPT; i++) {\n    if ((threadIdx.x + blockDim.x * i) < block_max_num_keys) {\n      tloc_keys[i] = reinterpret_cast<UnsignedBits*>(keys)[block_offset + threadIdx.x + blockDim.x * i];\n    }\n  }\n\n  #pragma unroll\n  for(int i=0; i<KPT; i++){\n    // if(KeyLoader(block_offset, threadIdx.x).ThreadIndexInBounds(block_max_num_keys, i)){\n    if ((threadIdx.x + blockDim.x * i) < block_max_num_keys) {\n      tloc_keys[i] = KeyTraits::TwiddleIn(tloc_keys[i]);\n      tloc_masked[i] = (tloc_keys[i]>>((sizeof(KeyT)*8)-(NUM_BITS*(digit+1))))&((0x01<<NUM_BITS)-1);\n      atomicAdd(&shared_bins[tloc_masked[i]], 1);\n    }\n  }\n\n  // Make sure we've got the counts from all threads\n  __syncthreads();\n\n  /*** Write shared histo to global histo ***/\n  if(threadIdx.x < 32){\n    for(int i=0;i<(0x01<<NUM_BITS);i+=32){\n      atomicAdd(&global_histo[(0x01<<NUM_BITS)*bucket_idx+i+threadIdx.x], shared_bins[i+threadIdx.x]);\n      // per_block_histo[(block_index_offset + blockIdx.x)*(0x01<<NUM_BITS)+i+threadIdx.x] = shared_bins[i+threadIdx.x];\n    }\n  }\n}\n\n/**\n * Makes a single pass over the input array to find entries whose digit is equal to selected digit value and greater than\n * digit value. Entries equal to digit value are written to keys_buffer for future processing, entries greater\n * are written to output array.\n * @param d_keys_in        [IN] The keys for which to compute the histogram\n * @param digit            [IN] Digit index (0 => highest digit, 3 => lowest digit for 32-bit)\n * @param digit_val        [IN] Digit value.\n * @param num_items        [IN] Number of entries.\n * @param d_keys_buffer    [OUT] Entries with x[digit] > digit_val.\n * @param d_keys_out       [OUT] Entries with x[digit] > digit_val.\n * @param d_index_buffer   [OUT] Index into d_keys_buffer.\n * @param d_index_out      [OUT] Index into d_keys_out.\n */\ntemplate<\n  typename KeyT,    // Data type of the keys within device memory. Data will be twiddled (if necessary) to unsigned type\n  typename IndexT,  // Data type used for key's offsets and counters (limits number of supported keys, uint = 2^32)\n  int NUM_BITS,     // Number of bits being sorted at a time\n  int KPT,          // Number of keys per thread\n  int TPB           // Number of threads per block\n>\n__global__ void select_kth_bucket(KeyT* d_keys_in, const uint digit, const uint digit_val, uint num_items,\n    KeyT* d_keys_buffer, KeyT* d_keys_out, uint* d_index_buffer, uint* d_index_out)\n{\n  typedef Traits<KeyT>                        KeyTraits;\n  typedef typename KeyTraits::UnsignedBits    UnsignedBits;\n\n  // Specialize BlockLoad for a 1D block of TPB threads owning KPT integer items each\n  typedef cub::BlockLoad<UnsignedBits, TPB, KPT, BLOCK_LOAD_TRANSPOSE> BlockLoadT;\n\n  // Specialize BlockScan type for our thread block\n  typedef BlockScan<int, TPB, BLOCK_SCAN_RAKING> BlockScanT;\n\n  const int tile_size = TPB * KPT;\n  int tile_idx = blockIdx.x;    // Current tile index\n  int tile_offset = tile_idx * tile_size;\n\n  // Allocate shared memory for BlockLoad\n  __shared__ union TempStorage\n  {\n    typename BlockLoadT::TempStorage    load_items;\n    typename BlockScanT::TempStorage    scan;\n    int offset[1];\n    UnsignedBits raw_exchange[2 * TPB * KPT];\n  } temp_storage;\n\n  // Load a segment of consecutive items that are blocked across threads\n  UnsignedBits key_entries[KPT];\n  /*float payload_entries[KPT];*/\n  int selection_flags[KPT];\n  int selection_indices[KPT];\n\n  int num_tiles = (num_items + tile_size - 1) / tile_size;\n  int num_tile_items = tile_size;\n  bool is_last_tile = false;\n  if (tile_idx == num_tiles - 1) {\n    num_tile_items = num_items - tile_offset;\n    is_last_tile = true;\n  }\n\n  // Load keys\n  if (is_last_tile)\n    BlockLoadT(temp_storage.load_items).Load(reinterpret_cast<UnsignedBits*>(d_keys_in) + tile_offset, key_entries, num_tile_items);\n  else\n    BlockLoadT(temp_storage.load_items).Load(reinterpret_cast<UnsignedBits*>(d_keys_in) + tile_offset, key_entries);\n\n\n#if 0\n  if (is_last_tile)\n    BlockLoadT(temp_storage.load_items).Load(payload + tile_offset, payload_entries, num_tile_items);\n  else\n    BlockLoadT(temp_storage.load_items).Load(payload + tile_offset, payload_entries);\n#endif\n\n  __syncthreads();\n\n  /*** Step 1: Find keys with digit value to selected digit value ***/\n  #pragma unroll\n  for (int ITEM = 0; ITEM < KPT; ++ITEM)\n  {\n    // Out-of-bounds items are selection_flags\n    selection_flags[ITEM] = 0;\n\n    if (!is_last_tile || (int(threadIdx.x * KPT) + ITEM < num_tile_items)) {\n      UnsignedBits key = KeyTraits::TwiddleIn(key_entries[ITEM]);\n      uint masked_key = (key>>((sizeof(KeyT)*8)-(NUM_BITS*(digit+1))))&((0x01<<NUM_BITS)-1);\n      selection_flags[ITEM] = (masked_key > digit_val);\n    }\n  }\n\n  __syncthreads();\n\n  // Compute exclusive prefix sum\n  int num_selected;\n  BlockScanT(temp_storage.scan).ExclusiveSum(selection_flags, selection_indices, num_selected);\n\n  __syncthreads();\n\n  if (num_selected > 0) {\n    int index_out;\n    if (threadIdx.x == 0) {\n      // Find index into keys_out array\n      index_out = atomicAdd(d_index_out, num_selected);\n      temp_storage.offset[0] = index_out;\n    }\n\n    __syncthreads();\n\n    index_out = temp_storage.offset[0];\n\n    __syncthreads();\n\n    // Compact and scatter items\n    #pragma unroll\n    for (int ITEM = 0; ITEM < KPT; ++ITEM)\n    {\n      int local_scatter_offset = selection_indices[ITEM];\n      if (selection_flags[ITEM])\n      {\n        temp_storage.raw_exchange[local_scatter_offset] = key_entries[ITEM];\n        /*temp_storage.raw_exchange[tile_size + local_scatter_offset] = payload_entries[ITEM];*/\n      }\n    }\n\n    __syncthreads();\n\n    // Write out matched entries to output array\n    for (int item = threadIdx.x; item < num_selected; item += TPB)\n    {\n      reinterpret_cast<UnsignedBits*>(d_keys_out)[index_out + item] = temp_storage.raw_exchange[item];\n    }\n\n    __syncthreads();\n\n#if 0\n    for (int item = threadIdx.x; item < num_selected; item += TPB)\n    {\n      payload_out[num_selections_prefix + item] = temp_storage.raw_exchange[tile_size + item];\n    }\n#endif\n  }\n\n  /*** Step 2: Find entries that have digit equal to digit value ***/\n  #pragma unroll\n  for (int ITEM = 0; ITEM < KPT; ++ITEM)\n  {\n    // Out-of-bounds items are selection_flags\n    selection_flags[ITEM] = 0;\n\n    if (!is_last_tile || (int(threadIdx.x * KPT) + ITEM < num_tile_items)) {\n      UnsignedBits key = KeyTraits::TwiddleIn(key_entries[ITEM]);\n      uint masked_key = (key>>((sizeof(KeyT)*8)-(NUM_BITS*(digit+1))))&((0x01<<NUM_BITS)-1);\n      selection_flags[ITEM] = (masked_key == digit_val);\n    }\n  }\n\n  __syncthreads();\n\n  // Compute exclusive prefix sum\n  BlockScanT(temp_storage.scan).ExclusiveSum(selection_flags, selection_indices, num_selected);\n\n  __syncthreads();\n\n  if (num_selected > 0) {\n    int index_buffer;\n    if (threadIdx.x == 0) {\n      index_buffer = atomicAdd(d_index_buffer, num_selected);\n      temp_storage.offset[0] = index_buffer;\n    }\n\n    __syncthreads();\n\n    index_buffer = temp_storage.offset[0];\n\n    __syncthreads();\n\n    // Compact and scatter items\n    #pragma unroll\n    for (int ITEM = 0; ITEM < KPT; ++ITEM)\n    {\n      int local_scatter_offset = selection_indices[ITEM];\n      if (selection_flags[ITEM])\n      {\n        temp_storage.raw_exchange[local_scatter_offset] = key_entries[ITEM];\n        /*temp_storage.raw_exchange[tile_size + local_scatter_offset] = payload_entries[ITEM];*/\n      }\n    }\n\n    __syncthreads();\n\n    // Write out output entries\n    for (int item = threadIdx.x; item < num_selected; item += TPB)\n    {\n      reinterpret_cast<UnsignedBits*>(d_keys_buffer)[index_buffer + item] = temp_storage.raw_exchange[item];\n    }\n\n    __syncthreads();\n  }\n}\n\n#define KPT 16\n#define TPB 384\n#define DIGIT_BITS 8\ntemplate<typename KeyT>\ncudaError_t radixSelectTopK(KeyT *d_keys_in, uint num_items, uint k, KeyT *d_keys_out,\n    CachingDeviceAllocator&  g_allocator) {\n  cudaError error = cudaSuccess;\n\n  DoubleBuffer<KeyT> d_keys;\n  d_keys.d_buffers[0] = d_keys_in;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(KeyT) * num_items));\n\n  uint* d_histogram;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_histogram, sizeof(uint) * num_items));\n\n  // We allocate two indices, one that maintains index into output array (this goes till K)\n  // second maintains index into the output buffer containing reduced set of top-k candidates.\n  uint* d_index_out;\n  uint* d_index_buffer;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_index_out, sizeof(uint)));\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_index_buffer, sizeof(uint)));\n\n  // Set the index into output array to 0.\n  cudaMemset(d_index_out, 0, 4);\n\n  uint* h_histogram = new uint[256];\n\n  uint KPB = KPT * TPB;\n\n  for (uint digit = 0; digit < 4; digit++) {\n    uint num_blocks = num_items / KPB;// Pass-0 rough processing blocks (floor on purpose)\n    uint processed_elements = num_blocks * KPB;// Pass-0 number of rough processed elements\n    uint remaining_elements = num_items - processed_elements;// Do the remaining elements with a check in the inner loop\n    uint remainder_blocks = (KPB-1+remaining_elements) / KPB;// Number of blocks required for remaining elements (typically 0 or 1)\n\n    // Zero out the histogram\n    cudaMemset(d_histogram, 0, 256 * 4);\n\n    if (num_blocks > 0)\n      rdxsrt_histogram<KeyT, uint, DIGIT_BITS, KPT, TPB, 9><<<num_blocks, TPB, 0>>>(d_keys.Current(), digit, d_histogram);\n    if (remaining_elements > 0)\n      rdxsrt_histogram_with_guards<KeyT, uint, DIGIT_BITS, KPT, TPB, 9><<<remainder_blocks, TPB, 0>>>(d_keys.Current(), digit, d_histogram, num_items, num_blocks);\n\n    cudaMemcpy(h_histogram, d_histogram, 256 * sizeof(uint), cudaMemcpyDeviceToHost);\n\n    // Check for failure to launch\n    CubDebugExit(error = cudaPeekAtLastError());\n\n    cudaMemcpy(h_histogram, d_histogram, 256 * sizeof(uint), cudaMemcpyDeviceToHost);\n    uint rolling_sum = 0;\n    uint digit_val;\n    for (int i=255; i>=0; i--) {\n      if ((rolling_sum + h_histogram[i]) > k) {\n        digit_val = i;\n        k -= rolling_sum;\n        break;\n      }\n      rolling_sum += h_histogram[i];\n    }\n\n    cudaMemset(d_index_buffer, 0, 4);\n\n    select_kth_bucket<KeyT, uint, DIGIT_BITS, KPT, TPB><<<num_blocks + remainder_blocks, TPB>>>(d_keys.Current(), digit, digit_val, num_items, d_keys.Alternate(), d_keys_out, d_index_buffer, d_index_out);\n\n    CubDebugExit(error = cudaPeekAtLastError());\n\n    uint h_index_out;\n    uint h_index_buffer;\n\n    cudaMemcpy(&h_index_out, d_index_out, sizeof(uint), cudaMemcpyDeviceToHost);\n    cudaMemcpy(&h_index_buffer, d_index_buffer, sizeof(uint), cudaMemcpyDeviceToHost);\n\n    // Update number of items to reflect reduced number of elements.\n    num_items = h_index_buffer;\n\n    if (k == 0) break;\n    else if (k != 0 && digit == 3) {\n      // We are at last digit and k != 4 implies that kth value has repetition.\n      // Copy any of the repeated values to out array to complete the array.\n      cudaMemcpy(d_keys_out + h_index_out, d_keys.Alternate(), k * sizeof(KeyT), cudaMemcpyDeviceToDevice);\n      k -= k;\n    }\n\n    // Toggle the buffer index in the double buffer\n    d_keys.selector = d_keys.selector ^ 1;\n  }\n\n  // Cleanup\n  if (d_keys.d_buffers[1])\n    CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[1]));\n  if (d_histogram)\n    CubDebugExit(g_allocator.DeviceFree(d_histogram));\n  if (d_index_buffer)\n    CubDebugExit(g_allocator.DeviceFree(d_index_buffer));\n  if (d_index_out)\n    CubDebugExit(g_allocator.DeviceFree(d_index_out));\n\n  return error;\n}\n\n"
  },
  {
    "path": "src/sharedmem.cuh",
    "content": "/*\n * Copyright 1993-2014 NVIDIA Corporation.  All rights reserved.\n *\n * Please refer to the NVIDIA end user license agreement (EULA) associated\n * with this source code for terms and conditions that govern your use of\n * this software. Any use, reproduction, disclosure, or distribution of\n * this software and related documentation outside the terms of the EULA\n * is strictly prohibited.\n *\n */\n\n#ifndef _SHAREDMEM_H_\n#define _SHAREDMEM_H_\n\n//****************************************************************************\n// Because dynamically sized shared memory arrays are declared \"extern\",\n// we can't templatize them directly.  To get around this, we declare a\n// simple wrapper struct that will declare the extern array with a different\n// name depending on the type.  This avoids compiler errors about duplicate\n// definitions.\n//\n// To use dynamically allocated shared memory in a templatized __global__ or\n// __device__ function, just replace code like this:\n//\n//\n//  template<class T>\n//  __global__ void\n//  foo( T* g_idata, T* g_odata)\n//  {\n//      // Shared mem size is determined by the host app at run time\n//      extern __shared__  T sdata[];\n//      ...\n//      doStuff(sdata);\n//      ...\n//   }\n//\n//   With this\n//  template<class T>\n//  __global__ void\n//  foo( T* g_idata, T* g_odata)\n//  {\n//      // Shared mem size is determined by the host app at run time\n//      SharedMemory<T> smem;\n//      T* sdata = smem.getPointer();\n//      ...\n//      doStuff(sdata);\n//      ...\n//   }\n//****************************************************************************\n\n// This is the un-specialized struct.  Note that we prevent instantiation of this\n// struct by putting an undefined symbol in the function body so it won't compile.\ntemplate <typename T>\nstruct SharedMemory\n{\n    // Ensure that we won't compile any un-specialized types\n    __device__ T *getPointer()\n    {\n        extern __device__ void error(void);\n        error();\n        return NULL;\n    }\n};\n\n// Following are the specializations for the following types.\n// int, uint, char, uchar, short, ushort, long, ulong, bool, float, and double\n// One could also specialize it for user-defined types.\n\ntemplate <>\nstruct SharedMemory <int>\n{\n    __device__ int *getPointer()\n    {\n        extern __shared__ int s_int[];\n        return s_int;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <unsigned int>\n{\n    __device__ unsigned int *getPointer()\n    {\n        extern __shared__ unsigned int s_uint[];\n        return s_uint;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <char>\n{\n    __device__ char *getPointer()\n    {\n        extern __shared__ char s_char[];\n        return s_char;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <unsigned char>\n{\n    __device__ unsigned char *getPointer()\n    {\n        extern __shared__ unsigned char s_uchar[];\n        return s_uchar;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <short>\n{\n    __device__ short *getPointer()\n    {\n        extern __shared__ short s_short[];\n        return s_short;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <unsigned short>\n{\n    __device__ unsigned short *getPointer()\n    {\n        extern __shared__ unsigned short s_ushort[];\n        return s_ushort;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <long>\n{\n    __device__ long *getPointer()\n    {\n        extern __shared__ long s_long[];\n        return s_long;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <unsigned long>\n{\n    __device__ unsigned long *getPointer()\n    {\n        extern __shared__ unsigned long s_ulong[];\n        return s_ulong;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <bool>\n{\n    __device__ bool *getPointer()\n    {\n        extern __shared__ bool s_bool[];\n        return s_bool;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <float>\n{\n    __device__ float *getPointer()\n    {\n        extern __shared__ float s_float[];\n        return s_float;\n    }\n};\n\ntemplate <>\nstruct SharedMemory <double>\n{\n    __device__ double *getPointer()\n    {\n        extern __shared__ double s_double[];\n        return s_double;\n    }\n};\n\n\n#endif //_SHAREDMEM_H_\n"
  },
  {
    "path": "src/sortTopK.cuh",
    "content": "#include <cuda.h>\n#include <cub/device/device_radix_sort.cuh>\n#include <cub/util_allocator.cuh>\n\nusing namespace std;\nusing namespace cub;\n\ntemplate<typename KeyT>\ncudaError_t sortTopK(KeyT *d_keys_in, unsigned int num_items, unsigned int k, KeyT *d_keys_out,\n    CachingDeviceAllocator&  g_allocator) {\n  // Allocate device memory for input/output\n  DoubleBuffer<KeyT> d_keys;\n  d_keys.d_buffers[0] = d_keys_in;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(KeyT) * num_items));\n\n  // Allocate temporary storage\n  size_t  temp_storage_bytes  = 0;\n  void    *d_temp_storage     = NULL;\n  CubDebugExit(DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys, num_items));\n  CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n  // Sort\n  CubDebugExit(DeviceRadixSort::SortKeysDescending(d_temp_storage, temp_storage_bytes, d_keys, num_items));\n\n  // Copy results for verification. GPU-side part is done.\n  CubDebugExit(cudaMemcpy(d_keys_out, d_keys.Current(), sizeof(KeyT) * k, cudaMemcpyDeviceToDevice));\n\n  // Cleanup\n  if (d_keys.d_buffers[1])\n    CubDebugExit(g_allocator.DeviceFree(d_keys.d_buffers[1]));\n  if (d_temp_storage)\n    CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n  return cudaSuccess;\n}\n\n"
  },
  {
    "path": "src/sortingNetwork.cuh",
    "content": "template<typename KeyT>\nstruct SortingNetwork\n{\n  enum { NETWORK_MAX_NUM_ITEMS = 18 };\n\nprivate:\n  static __device__ __forceinline__ void compare_and_swap(KeyT *keys, int low_idx, int high_idx)\n  {\n    if(keys[low_idx]>keys[high_idx]){\n      KeyT tmp = keys[low_idx];\n      keys[low_idx] = keys[high_idx];\n      keys[high_idx] = tmp;\n    }\n  }\n\n  template<int NUM_ITEMS, int DUMMY>\n  struct SortingNetworkAgent\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys){\n#if __cplusplus >= 199711\n    static_assert(NUM_ITEMS<=NETWORK_MAX_NUM_ITEMS, \"Sorting network of given size not supported.\");\n#endif\n    }\n  };\n\n  /*** SORTING NETWORK 1 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<1, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys){}\n  };\n\n  /*** SORTING NETWORK 2 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<2, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys){\n      compare_and_swap(keys, 0, 1);\n    }\n  };\n\n  /*** SORTING NETWORK 3 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<3, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 0, 1);\n    }\n  };\n\n  /*** SORTING NETWORK 4 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<4, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 1, 2);\n    }\n  };\n\n  /*** SORTING NETWORK 5 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<5, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 0, 3);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 1, 2);\n    }\n  };\n\n  /*** SORTING NETWORK 6 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<6, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 0, 3);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 2, 3);\n    }\n  };\n\n  /*** SORTING NETWORK 7 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<7, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 0, 3);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 2, 3);\n    }\n  };\n\n  /*** SORTING NETWORK 8 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<8, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 3, 6);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 3, 4);\n    }\n  };\n\n  /*** SORTING NETWORK 9 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<9, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 0, 3);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 1, 6);\n      compare_and_swap(keys, 0, 5);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 4, 7);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n    }\n  };\n\n  /*** SORTING NETWORK 10 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<10, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 4, 9);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 2, 7);\n      compare_and_swap(keys, 1, 6);\n      compare_and_swap(keys, 0, 5);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 0, 3);\n      compare_and_swap(keys, 5, 8);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 3, 6);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 4, 7);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 4, 5);\n    }\n  };\n\n\n  /*** SORTING NETWORK 11 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<11, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 6, 10);\n      compare_and_swap(keys, 5, 9);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 6, 10);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 7, 10);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 3, 4);\n    }\n  };\n\n  /*** SORTING NETWORK 12 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<12, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 6, 10);\n      compare_and_swap(keys, 5, 9);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 6, 10);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 7, 10);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 7, 8);\n    }\n  };\n\n  /*** SORTING NETWORK 13 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<13, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 1, 7);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 8);\n      compare_and_swap(keys, 0, 12);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 11);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 5, 9);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 6, 12);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 4, 9);\n      compare_and_swap(keys, 6, 10);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 1, 7);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 4, 7);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 0, 5);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n    }\n  };\n\n  /*** SORTING NETWORK 14 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<14, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 12, 13);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 8, 12);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 9, 13);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 0, 8);\n      compare_and_swap(keys, 1, 9);\n      compare_and_swap(keys, 2, 10);\n      compare_and_swap(keys, 3, 11);\n      compare_and_swap(keys, 4, 12);\n      compare_and_swap(keys, 5, 13);\n      compare_and_swap(keys, 5, 10);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 3, 12);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 7, 13);\n      compare_and_swap(keys, 2, 8);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 13);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 10, 12);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n    }\n  };\n\n  /*** SORTING NETWORK 15 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<15, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 12, 13);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 12, 14);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 8, 12);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 9, 13);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 10, 14);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 0, 8);\n      compare_and_swap(keys, 1, 9);\n      compare_and_swap(keys, 2, 10);\n      compare_and_swap(keys, 3, 11);\n      compare_and_swap(keys, 4, 12);\n      compare_and_swap(keys, 5, 13);\n      compare_and_swap(keys, 6, 14);\n      compare_and_swap(keys, 5, 10);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 3, 12);\n      compare_and_swap(keys, 13, 14);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 7, 13);\n      compare_and_swap(keys, 2, 8);\n      compare_and_swap(keys, 11, 14);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 13);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 10, 12);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n    }\n  };\n\n  /*** SORTING NETWORK 16 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<16, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 12, 13);\n      compare_and_swap(keys, 14, 15);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 12, 14);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 13, 15);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 8, 12);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 9, 13);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 10, 14);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 11, 15);\n      compare_and_swap(keys, 0, 8);\n      compare_and_swap(keys, 1, 9);\n      compare_and_swap(keys, 2, 10);\n      compare_and_swap(keys, 3, 11);\n      compare_and_swap(keys, 4, 12);\n      compare_and_swap(keys, 5, 13);\n      compare_and_swap(keys, 6, 14);\n      compare_and_swap(keys, 7, 15);\n      compare_and_swap(keys, 5, 10);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 3, 12);\n      compare_and_swap(keys, 13, 14);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 7, 13);\n      compare_and_swap(keys, 2, 8);\n      compare_and_swap(keys, 11, 14);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 13);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 10, 12);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 8, 9);\n    }\n  };\n\n  /*** SORTING NETWORK 17 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<17, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 2, 6);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 3, 6);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 8, 9);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 12, 13);\n      compare_and_swap(keys, 15, 16);\n      compare_and_swap(keys, 14, 16);\n      compare_and_swap(keys, 14, 15);\n      compare_and_swap(keys, 12, 15);\n      compare_and_swap(keys, 12, 14);\n      compare_and_swap(keys, 13, 16);\n      compare_and_swap(keys, 13, 15);\n      compare_and_swap(keys, 13, 14);\n      compare_and_swap(keys, 8, 13);\n      compare_and_swap(keys, 8, 12);\n      compare_and_swap(keys, 9, 14);\n      compare_and_swap(keys, 9, 13);\n      compare_and_swap(keys, 9, 12);\n      compare_and_swap(keys, 10, 15);\n      compare_and_swap(keys, 11, 16);\n      compare_and_swap(keys, 11, 15);\n      compare_and_swap(keys, 10, 13);\n      compare_and_swap(keys, 10, 12);\n      compare_and_swap(keys, 11, 14);\n      compare_and_swap(keys, 11, 13);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 0, 9);\n      compare_and_swap(keys, 0, 8);\n      compare_and_swap(keys, 1, 10);\n      compare_and_swap(keys, 1, 9);\n      compare_and_swap(keys, 1, 8);\n      compare_and_swap(keys, 2, 11);\n      compare_and_swap(keys, 3, 12);\n      compare_and_swap(keys, 3, 11);\n      compare_and_swap(keys, 2, 9);\n      compare_and_swap(keys, 2, 8);\n      compare_and_swap(keys, 3, 10);\n      compare_and_swap(keys, 3, 9);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 4, 13);\n      compare_and_swap(keys, 5, 14);\n      compare_and_swap(keys, 5, 13);\n      compare_and_swap(keys, 6, 15);\n      compare_and_swap(keys, 7, 16);\n      compare_and_swap(keys, 7, 15);\n      compare_and_swap(keys, 6, 13);\n      compare_and_swap(keys, 7, 14);\n      compare_and_swap(keys, 7, 13);\n      compare_and_swap(keys, 4, 9);\n      compare_and_swap(keys, 4, 8);\n      compare_and_swap(keys, 5, 10);\n      compare_and_swap(keys, 5, 9);\n      compare_and_swap(keys, 5, 8);\n      compare_and_swap(keys, 6, 11);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 7, 10);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 7, 8);\n    }\n  };\n\n  /*** SORTING NETWORK 18 ***/\n  template<int DUMMY>\n  struct SortingNetworkAgent<18, DUMMY>\n  {\n    static __device__ __forceinline__ void sort(KeyT *keys)\n    {\n      compare_and_swap(keys, 0, 1);\n      compare_and_swap(keys, 2, 3);\n      compare_and_swap(keys, 0, 2);\n      compare_and_swap(keys, 1, 3);\n      compare_and_swap(keys, 1, 2);\n      compare_and_swap(keys, 4, 5);\n      compare_and_swap(keys, 7, 8);\n      compare_and_swap(keys, 6, 8);\n      compare_and_swap(keys, 6, 7);\n      compare_and_swap(keys, 4, 7);\n      compare_and_swap(keys, 4, 6);\n      compare_and_swap(keys, 5, 8);\n      compare_and_swap(keys, 5, 7);\n      compare_and_swap(keys, 5, 6);\n      compare_and_swap(keys, 0, 5);\n      compare_and_swap(keys, 0, 4);\n      compare_and_swap(keys, 1, 6);\n      compare_and_swap(keys, 1, 5);\n      compare_and_swap(keys, 1, 4);\n      compare_and_swap(keys, 2, 7);\n      compare_and_swap(keys, 3, 8);\n      compare_and_swap(keys, 3, 7);\n      compare_and_swap(keys, 2, 5);\n      compare_and_swap(keys, 2, 4);\n      compare_and_swap(keys, 3, 6);\n      compare_and_swap(keys, 3, 5);\n      compare_and_swap(keys, 3, 4);\n      compare_and_swap(keys, 9, 10);\n      compare_and_swap(keys, 11, 12);\n      compare_and_swap(keys, 9, 11);\n      compare_and_swap(keys, 10, 12);\n      compare_and_swap(keys, 10, 11);\n      compare_and_swap(keys, 13, 14);\n      compare_and_swap(keys, 16, 17);\n      compare_and_swap(keys, 15, 17);\n      compare_and_swap(keys, 15, 16);\n      compare_and_swap(keys, 13, 16);\n      compare_and_swap(keys, 13, 15);\n      compare_and_swap(keys, 14, 17);\n      compare_and_swap(keys, 14, 16);\n      compare_and_swap(keys, 14, 15);\n      compare_and_swap(keys, 9, 14);\n      compare_and_swap(keys, 9, 13);\n      compare_and_swap(keys, 10, 15);\n      compare_and_swap(keys, 10, 14);\n      compare_and_swap(keys, 10, 13);\n      compare_and_swap(keys, 11, 16);\n      compare_and_swap(keys, 12, 17);\n      compare_and_swap(keys, 12, 16);\n      compare_and_swap(keys, 11, 14);\n      compare_and_swap(keys, 11, 13);\n      compare_and_swap(keys, 12, 15);\n      compare_and_swap(keys, 12, 14);\n      compare_and_swap(keys, 12, 13);\n      compare_and_swap(keys, 0, 9);\n      compare_and_swap(keys, 1, 10);\n      compare_and_swap(keys, 1, 9);\n      compare_and_swap(keys, 2, 11);\n      compare_and_swap(keys, 3, 12);\n      compare_and_swap(keys, 3, 11);\n      compare_and_swap(keys, 2, 9);\n      compare_and_swap(keys, 3, 10);\n      compare_and_swap(keys, 3, 9);\n      compare_and_swap(keys, 4, 13);\n      compare_and_swap(keys, 5, 14);\n      compare_and_swap(keys, 5, 13);\n      compare_and_swap(keys, 6, 15);\n      compare_and_swap(keys, 7, 16);\n      compare_and_swap(keys, 8, 17);\n      compare_and_swap(keys, 8, 16);\n      compare_and_swap(keys, 7, 15);\n      compare_and_swap(keys, 8, 15);\n      compare_and_swap(keys, 6, 13);\n      compare_and_swap(keys, 7, 14);\n      compare_and_swap(keys, 8, 14);\n      compare_and_swap(keys, 7, 13);\n      compare_and_swap(keys, 8, 13);\n      compare_and_swap(keys, 4, 9);\n      compare_and_swap(keys, 5, 10);\n      compare_and_swap(keys, 5, 9);\n      compare_and_swap(keys, 6, 11);\n      compare_and_swap(keys, 7, 12);\n      compare_and_swap(keys, 8, 12);\n      compare_and_swap(keys, 7, 11);\n      compare_and_swap(keys, 8, 11);\n      compare_and_swap(keys, 6, 9);\n      compare_and_swap(keys, 7, 10);\n      compare_and_swap(keys, 8, 10);\n      compare_and_swap(keys, 7, 9);\n      compare_and_swap(keys, 8, 9);\n    }\n  };\n\n  template<\n    int RUN_LENGTH,\n    int NUM_RUN_ITEMS,  // Number of items to sort in this run (starting at keys)\n    bool IS_LAST_RUN  // If this run is the last run to be sorted\n  >\n  struct SortRunAgent\n  {\n    static __device__ __forceinline__ void sort_runs(KeyT *keys)\n    {\n      SortingNetwork<KeyT>::sort<RUN_LENGTH>(keys);\n      SortRunAgent<RUN_LENGTH, NUM_RUN_ITEMS-RUN_LENGTH, (NUM_RUN_ITEMS-RUN_LENGTH<=RUN_LENGTH)>::sort_runs(&keys[RUN_LENGTH]);\n    }\n  };\n\n  template<\n    int RUN_LENGTH,\n    int NUM_RUN_ITEMS\n  >\n  struct SortRunAgent<RUN_LENGTH, NUM_RUN_ITEMS, true>\n  {\n    static __device__ __forceinline__ void sort_runs(KeyT *keys)\n    {\n      SortingNetwork<KeyT>::sort<NUM_RUN_ITEMS>(keys);\n    }\n  };\n\npublic:\n\n  template<int NUM_ITEMS>\n  static __device__ __forceinline__ void sort(KeyT (&keys)[NUM_ITEMS])\n  {\n    SortingNetworkAgent<NUM_ITEMS, 0>::sort(keys);\n  }\n\n  template<int NUM_ITEMS>\n  static __device__ __forceinline__ void sort(KeyT *keys)\n  {\n    SortingNetworkAgent<NUM_ITEMS, 0>::sort(keys);\n  }\n\n  template<\n    int RUN_LENGTH,\n    int NUM_ITEMS\n  >\n  static __device__ __forceinline__ void sort_runs(KeyT (&keys)[NUM_ITEMS])\n  {\n    SortRunAgent<RUN_LENGTH, NUM_ITEMS, (NUM_ITEMS>RUN_LENGTH)>::sort_runs(keys);\n  }\n\n  template<\n    int RUN_LENGTH,\n    int NUM_ITEMS\n  >\n  static __device__ __forceinline__ void sort_runs(KeyT *keys)\n  {\n    SortRunAgent<RUN_LENGTH, NUM_ITEMS, (NUM_ITEMS>RUN_LENGTH)>::sort_runs(keys);\n  }\n}\n"
  },
  {
    "path": "test/compareTopKAlgorithms.cu",
    "content": "#include <cuda.h>\n#include <curand.h>\n#include <cuda_runtime_api.h>\n#include <cub/util_allocator.cuh>\n\n#include <time.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <iostream>\n#include <fstream>\n#include <sys/time.h>\n#include <algorithm>\n\n#include \"printFunctions.cuh\"\n#include \"generateProblems.cuh\"\n#include \"sortTopK.cuh\"\n#include \"radixSelectTopK.cuh\"\n#include \"bitonicTopK.cuh\"\n\n#define SETUP_TIMING() cudaEvent_t start, stop; cudaEventCreate(&start); cudaEventCreate(&stop);\n\n#define TIME_FUNC(f,t) { \\\n    cudaEventRecord(start, 0); \\\n    f; \\\n    cudaEventRecord(stop, 0); \\\n    cudaEventSynchronize(stop); \\\n    cudaEventElapsedTime(&t, start,stop); \\\n}\n\nusing namespace std;\n\nCachingDeviceAllocator  g_allocator(true);  // Caching allocator for device memory\n\n#define NUMBEROFALGORITHMS 3\nconst char* namesOfTimingFunctions[NUMBEROFALGORITHMS] = {\"Sort\", \"Radix Select\", \"Bitonic TopK\"};\n\ntemplate<typename KeyT>\nvoid compareAlgorithms(uint size, uint k, uint numTests,uint *algorithmsToTest, uint generateType){\n  KeyT *d_vec;\n  KeyT *d_vec_copy;\n  KeyT *d_res;\n  float timeArray[NUMBEROFALGORITHMS][numTests];\n  float totalTimesPerAlgorithm[NUMBEROFALGORITHMS];\n  float minTimesPerAlgorithm[NUMBEROFALGORITHMS];\n  KeyT* resultsArray[NUMBEROFALGORITHMS][numTests];\n  std::fill_n(minTimesPerAlgorithm, NUMBEROFALGORITHMS, 2000);\n\n  uint winnerArray[numTests];\n  uint timesWon[NUMBEROFALGORITHMS];\n  uint i,j,m,x;\n  int runOrder[NUMBEROFALGORITHMS];\n\n  unsigned long long seed;\n  timeval t1;\n  float runtime;\n\n  SETUP_TIMING()\n\n  typedef cudaError_t (*ptrToTimingFunction)(KeyT*, uint, uint, KeyT*, CachingDeviceAllocator&);\n  typedef void (*ptrToGeneratingFunction)(KeyT*, uint, curandGenerator_t, CachingDeviceAllocator&);\n  //these are the functions that can be called\n  ptrToTimingFunction arrayOfTimingFunctions[NUMBEROFALGORITHMS] = {&sortTopK<KeyT> , &radixSelectTopK<KeyT>, &bitonicTopK<KeyT>};\n  /*ptrToTimingFunction arrayOfTimingFunctions[NUMBEROFALGORITHMS] = {NULL, NULL, NULL};*/\n\n  ptrToGeneratingFunction *arrayOfGenerators;\n  const char** namesOfGeneratingFunctions;\n  //this is the array of names of functions that generate problems of this type, ie float, double, or uint\n  namesOfGeneratingFunctions = returnNamesOfGenerators<KeyT>();\n  arrayOfGenerators = (ptrToGeneratingFunction *) returnGenFunctions<KeyT>();\n\n  //zero out the totals and times won\n  bzero(totalTimesPerAlgorithm, NUMBEROFALGORITHMS * sizeof(uint));\n  bzero(timesWon, NUMBEROFALGORITHMS * sizeof(uint));\n  //allocate space for d_vec, and d_vec_copy\n  cudaMalloc(&d_vec, size * sizeof(KeyT));\n  cudaMalloc(&d_vec_copy, size * sizeof(KeyT));\n  cudaMalloc(&d_res, k * sizeof(KeyT));\n\n  //create the random generator.\n  curandGenerator_t generator;\n  srand(unsigned(time(NULL)));\n\n  printf(\"The distribution is: %s\\n\", namesOfGeneratingFunctions[generateType]);\n  for(i = 0; i < numTests; i++){\n    // cudaDeviceReset();\n    gettimeofday(&t1, NULL);\n    seed = t1.tv_usec * t1.tv_sec;\n\n    for(m = 0; m < NUMBEROFALGORITHMS;m++){\n      runOrder[m] = m;\n    }\n    std::random_shuffle(runOrder, runOrder + NUMBEROFALGORITHMS);\n    curandCreateGenerator(&generator, CURAND_RNG_PSEUDO_DEFAULT);\n    curandSetPseudoRandomGeneratorSeed(generator,seed);\n    curandSetPseudoRandomGeneratorSeed(generator,0);\n    printf(\"Running test %u of %u for size: %u and k: %u\\n\", i + 1, numTests,size,k);\n    //generate the random vector using the specified distribution\n    arrayOfGenerators[generateType](d_vec, size, generator, g_allocator);\n\n    //copy the vector to d_vec_copy, which will be used to restore it later\n    cudaMemcpy(d_vec_copy, d_vec, size * sizeof(KeyT), cudaMemcpyDeviceToDevice);\n\n    uint* h_vec = new uint[size];\n    cudaMemcpy(h_vec, d_vec, size * sizeof(KeyT), cudaMemcpyDeviceToHost);\n\n/*    uint *b = new uint[size];*/\n    /*uint *c = new uint[size];*/\n    /*uint *d = new uint[size];*/\n\n    /*int x=0,y=0,z=0;*/\n    /*for (int r=0; r<size; r++) {*/\n      /*if ((h_vec[r] & 0xff000000) == 0xff000000) {*/\n        /*b[x] = h_vec[r];*/\n        /*x += 1;*/\n      /*}*/\n    /*}*/\n\n/*    for (int i=0; i<x; i++) {*/\n      /*if (b[i] & 0x0f00 == 0x0f00) {*/\n        /*c[y] = b[i];*/\n        /*y += 1;*/\n      /*}*/\n    /*}*/\n\n    /*for (int i=0; i<x; i++) {*/\n      /*if (b[i] & 0x0f00 == 0x0f00) {*/\n        /*c[y] = b[i];*/\n        /*y += 1;*/\n      /*}*/\n    /*}*/\n/*    std::sort(b, b+x, std::greater<uint>());*/\n    /*cout << \"Count \" << x << endl;*/\n    /*for (int r=0; r<k; r++) cout << b[r] << endl;*/\n\n/*    std::sort(h_vec, h_vec+size, std::greater<uint>());*/\n    /*for (int r=0; r<k; r++) cout << h_vec[r] << endl;*/\n\n\n\n    winnerArray[i] = 0;\n    float currentWinningTime = INFINITY;\n    //run the various timing functions\n    for(x = 0; x < NUMBEROFALGORITHMS; x++){\n      j = runOrder[x];\n      if(algorithmsToTest[j]){\n\n        //run timing function j\n        printf(\"TESTING: %u %s\\n\", j, namesOfTimingFunctions[j]);\n        TIME_FUNC(arrayOfTimingFunctions[j](d_vec_copy, size, k, d_res, g_allocator), runtime);\n\n          // check for error\n          cudaError_t error = cudaGetLastError();\n            if(error != cudaSuccess)\n            {\n                  // print the CUDA error message and exit\n                  printf(\"CUDA error: %s\\n\", cudaGetErrorString(error));\n                      exit(-1);\n            }\n\n        //record the time result\n        timeArray[j][i] = runtime;\n\n        KeyT* h_res = new KeyT[k];\n        cudaMemcpy(h_res, d_res, k * sizeof(KeyT), cudaMemcpyDeviceToHost);\n        std::sort(h_res, h_res+k, std::greater<KeyT>());\n\n        //record the value returned\n        resultsArray[j][i] = h_res;\n        //update the current \"winner\" if necessary\n        if(timeArray[j][i] < currentWinningTime){\n          currentWinningTime = runtime;\n          winnerArray[i] = j;\n        }\n\n        //perform clean up\n        cudaMemcpy(d_vec_copy, d_vec, size * sizeof(KeyT), cudaMemcpyDeviceToDevice);\n      }\n    }\n    curandDestroyGenerator(generator);\n/*    //for(x = 0; x < NUMBEROFALGORITHMS; x++){*/\n      //if(algorithmsToTest[x]){\n        //fileCsv << namesOfTimingFunctions[x] << \",\"<< resultsArray[x][i] <<\",\"<< timeArray[x][i] <<\",\";\n      //}\n    /*}*/\n //   uint flag = 0;\n/*    T tempResult = resultsArray[0][i];*/\n    //for(m = 1; m < NUMBEROFALGORITHMS;m++){\n      //if(algorithmsToTest[m]){\n        //if(resultsArray[m][i] != tempResult){\n          //flag++;\n        //}\n      //}\n    /*}*/\n    //fileCsv << flag << \"\\n\";\n  }\n\n  //calculate the total time each algorithm took\n  for(i = 0; i < numTests; i++){\n    for(j = 0; j < NUMBEROFALGORITHMS;j++){\n      if(algorithmsToTest[j]){\n        totalTimesPerAlgorithm[j] += timeArray[j][i];\n        minTimesPerAlgorithm[j] = min(minTimesPerAlgorithm[j], timeArray[j][i]);\n      }\n    }\n  }\n\n  //count the number of times each algorithm won.\n  for(i = 0; i < numTests;i++){\n    timesWon[winnerArray[i]]++;\n  }\n\n  printf(\"\\n\\n\");\n\n  //print out the average times\n  for(i = 0; i < NUMBEROFALGORITHMS; i++){\n    if(algorithmsToTest[i]){\n      printf(\"%-20s averaged: %f ms\\n\", namesOfTimingFunctions[i], totalTimesPerAlgorithm[i] / numTests);\n    }\n  }\n  for(i = 0; i < NUMBEROFALGORITHMS; i++){\n    if(algorithmsToTest[i]){\n      printf(\"%-20s minimum: %f ms\\n\", namesOfTimingFunctions[i], minTimesPerAlgorithm[i]);\n    }\n  }\n  for(i = 0; i < NUMBEROFALGORITHMS; i++){\n    if(algorithmsToTest[i]){\n      printf(\"%s won %u times\\n\", namesOfTimingFunctions[i], timesWon[i]);\n    }\n  }\n  if (algorithmsToTest[0]) {\n    for(i = 0; i < numTests; i++){\n      for(j =1 ; j< NUMBEROFALGORITHMS; j++){\n        if(algorithmsToTest[j]){\n          for (int m=0; m<k; m++)\n            if(resultsArray[j][i][m] != resultsArray[0][i][m]){\n              std::cout <<namesOfTimingFunctions[j] <<\" did not return the correct answer on test\" << i + 1 << std::endl;\n              std::cout << \"Method:\\t\";\n              PrintFunctions::printArray<KeyT>(resultsArray[j][i], k);\n              std::cout << \"Sort:\\t\";\n              PrintFunctions::printArray<KeyT>(resultsArray[0][i], k);\n              break;\n            }\n        }\n      }\n    }\n  }\n\n  //free d_vec and d_vec_copy\n  cudaFree(d_vec);\n  cudaFree(d_vec_copy);\n}\n\ntemplate<typename KeyT>\nvoid runTests(uint generateType, int K, uint startPower, uint stopPower, uint timesToTestEachK = 3) {\n  // Algorithms To Run\n  // timeSort, timeRadixSelect, timeBitonicTopK\n  uint algorithmsToRun[NUMBEROFALGORITHMS]= {1,1,1};\n  uint size;\n  for (size = (1 << startPower); size <= (1 <<stopPower);size *= 2){\n    //  cudaDeviceReset();\n    /*cudaThreadExit();*/\n    printf(\"NOW STARTING A NEW K\\n\\n\");\n    compareAlgorithms<KeyT>(size, K, timesToTestEachK,algorithmsToRun,generateType);\n  }\n}\n\nint main(int argc, char** argv)\n{\n  uint testCount;\n  int K;\n  uint type,distributionType,startPower,stopPower;\n  if (argc == 7) {\n    type = atoi(argv[1]);\n    distributionType = atoi(argv[2]);\n    K = atoi(argv[3]);\n    testCount = atoi(argv[4]);\n    startPower = atoi(argv[5]);\n    stopPower = atoi(argv[6]);\n  } else {\n    printf(\"Please enter the type of value you want to test:\\n1-float\\n2-double\\n3-uint\\n\");\n    cin >> type;\n    printf(\"Please enter distribution type: \");\n    cin >> distributionType;\n    printf(\"Please enter K: \");\n    cin >> K;\n    printf(\"Please enter number of tests to run per K: \");\n    cin >> testCount;\n    printf(\"Please enter start power (dataset size starts at 2^start)(max val: 29): \");\n    cin >> startPower;\n    printf(\"Please enter stop power (dataset size stops at 2^stop)(max val: 29): \");\n    cin >> stopPower;\n  }\n\n  switch(type){\n  case 1:\n    runTests<float>(distributionType,K,startPower,stopPower,testCount);\n    break;\n  case 2:\n    // runTests<double>(distributionType,K,startPower,stopPower,testCount);\n    break;\n  case 3:\n     runTests<unsigned int>(distributionType,K,startPower,stopPower,testCount);\n    break;\n  default:\n    printf(\"You entered and invalid option, now exiting\\n\");\n    break;\n  }\n\n  return 0;\n}\n\n"
  },
  {
    "path": "test/generateProblems.cuh",
    "content": "#pragma once\n\n#include <cstdlib>\n#include <typeinfo>\n#include <cuda.h>\n#include <curand.h>\n#include <cub/device/device_radix_sort.cuh>\n#include <cub/util_allocator.cuh>\n/*#include <algorithm>*/\nusing namespace cub;\nusing namespace std;\n\ntemplate<typename KeyT>\nvoid sort_keys(KeyT* d_vec, const unsigned int num_keys, CachingDeviceAllocator& g_allocator) {\n // Allocate device memory for input/output\n  DoubleBuffer<KeyT> d_keys;\n  d_keys.d_buffers[0] = d_vec;\n  CubDebugExit(g_allocator.DeviceAllocate((void**)&d_keys.d_buffers[1], sizeof(KeyT) * num_keys));\n\n  // Allocate temporary storage\n  size_t  temp_storage_bytes  = 0;\n  void    *d_temp_storage     = NULL;\n  CubDebugExit(DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys, num_keys));\n  CubDebugExit(g_allocator.DeviceAllocate(&d_temp_storage, temp_storage_bytes));\n\n  // Sort\n  CubDebugExit(DeviceRadixSort::SortKeys(d_temp_storage, temp_storage_bytes, d_keys, num_keys));\n\n  // Copy results for verification. GPU-side part is done.\n  if (d_keys.Current() != d_vec) {\n    CubDebugExit(cudaMemcpy(d_vec, d_keys.Current(), sizeof(KeyT) * num_keys, cudaMemcpyDeviceToDevice));\n  }\n\n  if (d_temp_storage)\n    CubDebugExit(g_allocator.DeviceFree(d_temp_storage));\n\n  if (d_keys.d_buffers[1])\n    CubDebugExit( g_allocator.DeviceFree(d_keys.d_buffers[1]) );\n}\n\n///////////////////////////////////////////////////////////////////\n////           FUNCTIONS TO GENERATE UINTS\n///////////////////////////////////////////////////////////////////\ntypedef void (*ptrToUintGeneratingFunction)(uint*, uint, curandGenerator_t, CachingDeviceAllocator&);\n\nvoid generateUniformUints(uint *d_vec, uint num_keys, curandGenerator_t generator, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerate(generator, d_vec, num_keys);\n}\n\nvoid generateSortedIncreasingUints(uint* d_vec, uint num_keys, curandGenerator_t gen, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerate(gen, d_vec,num_keys);\n  sort_keys<uint>(d_vec, num_keys, g_allocator);\n}\n\nvoid generateSortedDecreasingUints(uint* d_vec, uint num_keys, curandGenerator_t gen, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerate(gen, d_vec,num_keys);\n  sort_keys<uint>(d_vec, num_keys, g_allocator);\n}\n\n#define NUMBEROFUINTDISTRIBUTIONS 3\nptrToUintGeneratingFunction arrayOfUintGenerators[NUMBEROFUINTDISTRIBUTIONS] = {&generateUniformUints, &generateSortedIncreasingUints, &generateSortedDecreasingUints};\nconst char* namesOfUintGeneratingFunctions[NUMBEROFUINTDISTRIBUTIONS]={\"UNIFORM UINTS\",\"SORTED INC UINTS\", \"SORTED DEC UINTS\"};\n\n///////////////////////////////////////////////////////////////////\n////           FUNCTIONS TO GENERATE FLOATS\n///////////////////////////////////////////////////////////////////\ntypedef void (*ptrToFloatGeneratingFunction)(float*, uint, curandGenerator_t, CachingDeviceAllocator&);\n\nvoid generateUniformFloats(float *d_vec, uint num_keys, curandGenerator_t generator, \n    CachingDeviceAllocator& g_allocator){\n  curandGenerateUniform(generator, d_vec,num_keys);\n}\n\nvoid generateSortedIncreasingFloats(float *d_vec, uint num_keys, curandGenerator_t generator, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerateUniform(generator, d_vec,num_keys);\n  sort_keys<float>(d_vec, num_keys, g_allocator);\n}\n\nvoid generateSortedDecreasingFloats(float *d_vec, uint num_keys, curandGenerator_t generator, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerateUniform(generator, d_vec,num_keys);\n  sort_keys<float>(d_vec, num_keys, g_allocator);\n}\n\n/*void generateBucketKillerFloats(float *d_vec, uint num_keys, curandGenerator_t generator){*/\n  /*int i;*/\n  /*float * d_generated = d_vec;*/\n  /*curandGenerateUniform(generator, d_generated,num_keys);*/\n  /*thrust::device_ptr<unsigned int> dev_ptr((uint *)d_generated);*/\n  /*thrust::for_each( dev_ptr, dev_ptr + num_keys, makeSmallFloat());*/\n  /*thrust::sort(dev_ptr,dev_ptr + num_keys);*/\n\n  /*float* h_vec = (float*) malloc(num_keys * sizeof(float));*/\n  /*cudaMemcpy(h_vec, d_generated, num_keys * sizeof(float), cudaMemcpyDeviceToHost);*/\n\n  /*for(i = -126; i < 127; i++){*/\n    /*h_vec[i + 126] = pow(2.0f,(float)i);*/\n  /*}*/\n  /*cudaMemcpy(d_generated, h_vec, num_keys * sizeof(float), cudaMemcpyHostToDevice);*/\n  /*free(h_vec);*/\n/*}*/\n\n#define NUMBEROFFLOATDISTRIBUTIONS 3\nptrToFloatGeneratingFunction arrayOfFloatGenerators[NUMBEROFFLOATDISTRIBUTIONS] = {&generateUniformFloats, &generateSortedIncreasingFloats, &generateSortedDecreasingFloats};\n\nconst char* namesOfFloatGeneratingFunctions[NUMBEROFFLOATDISTRIBUTIONS] = {\"UNIFORM FLOATS\", \"SORTED INC FLOATS\", \"SORTED DEC FLOATS\"};\n\n///////////////////////////////////////////////////////////////////\n////           FUNCTIONS TO GENERATE DOUBLES\n///////////////////////////////////////////////////////////////////\n\ntypedef void (*ptrToDoubleGeneratingFunction)(double*, uint, curandGenerator_t, CachingDeviceAllocator&);\n\nvoid generateUniformDoubles(double *d_generated, uint num_keys, curandGenerator_t generator, \n    CachingDeviceAllocator& g_allocator) {\n  curandGenerateUniformDouble(generator, d_generated,num_keys);\n}\n\n#define NUMBEROFDOUBLEDISTRIBUTIONS 1\nptrToDoubleGeneratingFunction arrayOfDoubleGenerators[NUMBEROFDOUBLEDISTRIBUTIONS] = {&generateUniformDoubles};\nconst char* namesOfDoubleGeneratingFunctions[NUMBEROFDOUBLEDISTRIBUTIONS]={\"UNIFORM DOUBLES\"};\n\ntemplate<typename T> void* returnGenFunctions(){\n  if(typeid(T) == typeid(uint)){\n    return arrayOfUintGenerators;\n  }\n  else if(typeid(T) == typeid(float)){\n    return arrayOfFloatGenerators;\n  }\n  else{\n    return arrayOfDoubleGenerators;\n  }\n}\n\n\ntemplate<typename T> const char** returnNamesOfGenerators(){\n  if(typeid(T) == typeid(uint)){\n    return &namesOfUintGeneratingFunctions[0];\n  }\n  else if(typeid(T) == typeid(float)){\n    return &namesOfFloatGeneratingFunctions[0];\n  }\n  else {\n    return &namesOfDoubleGeneratingFunctions[0];\n  }\n}\n\n/*template void* returnGenFunctions<uint>();*/\n/*template void* returnGenFunctions<float>();*/\n/*template void* returnGenFunctions<double>();*/\n\n/*template const char** returnNamesOfGenerators<uint>();*/\n/*template const char** returnNamesOfGenerators<float>();*/\n/*template const char** returnNamesOfGenerators<double>();*/\n\n"
  },
  {
    "path": "test/printFunctions.cuh",
    "content": "/* Copyright 2011 Russel Steinbach, Jeffrey Blanchard, Bradley Gordon,\n *   and Toluwaloju Alabi\n *   Licensed under the Apache License, Version 2.0 (the \"License\");\n *  you may not use this file except in compliance with the License.\n *  You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n#pragma once\n#include <iostream>\n#include <cstdio>\n#include <cuda.h>\nusing namespace std;\n\nnamespace PrintFunctions{\n  template<typename T>\n  void printArray(T *h_vec,uint size){\n    printf(\"\\n\");\n    for(int i = 0; i < size; i++){\n      std::cout <<h_vec[i] << \"\\n\";\n    }\n    printf(\"\\n\");\n  }\n  \n  void printArray(char **h_vec,uint size){\n    printf(\"\\n\");\n    for(int i = 0; i < size; i++){\n      printf(\"%d-%s\\n\",i, h_vec[i]);\n    }\n    printf(\"\\n\");\n  }\n\n  template<typename T>\n  void printCudaArray(T *d_vec,uint size){\n    T* h_vec = (T *) std::malloc(size * sizeof(T));\n    cudaMemcpy(h_vec, d_vec, size*sizeof(T), cudaMemcpyDeviceToHost);\n    printArray(h_vec, size);\n    free(h_vec);\n  }\n}//end namespace \n\n"
  }
]