diff --git a/pyopencl/array.py b/pyopencl/array.py
index b43756f9a30d7612a3719a59d9c7937f1208a752..d00253a4a0f7ad16b836ef23064c7f7236dae9fd 100644
--- a/pyopencl/array.py
+++ b/pyopencl/array.py
@@ -57,6 +57,7 @@ except:
     def _dtype_is_object(t):
         return False
 
+
 # {{{ vector types
 
 class vec:
@@ -2018,6 +2019,34 @@ def diff(array, queue=None, allocator=None):
     _diff(result, array, queue=queue)
     return result
 
+
+def hstack(arrays, queue=None):
+    from pyopencl.array import empty
+
+    if len(arrays) == 0:
+        return empty(queue, (), dtype=np.float64)
+
+    if queue is None:
+        for ary in arrays:
+            if ary.queue is not None:
+                queue = ary.queue
+                break
+
+    from pytools import all_equal, single_valued
+    if not all_equal(len(ary.shape) for ary in arrays):
+        raise ValueError("arguments must all have the same number of axes")
+
+    lead_shape = single_valued(ary.shape[:-1] for ary in arrays)
+
+    w = _builtin_sum([ary.shape[-1] for ary in arrays])
+    result = empty(queue, lead_shape+(w,), arrays[0].dtype)
+    index = 0
+    for ary in arrays:
+        result[..., index:index+ary.shape[-1]] = ary
+        index += ary.shape[-1]
+
+    return result
+
 # }}}
 
 
diff --git a/pyopencl/cache.py b/pyopencl/cache.py
index 9971b1e3da62852f2a43d2bdef83098dcfc4e7fe..113f296299aa5795d68f939d7323dd5b06f31a85 100644
--- a/pyopencl/cache.py
+++ b/pyopencl/cache.py
@@ -338,16 +338,15 @@ def _create_built_program_from_source_cached(ctx, src, options, devices, cache_d
             option_idx += 1
 
     if cache_dir is None:
-        from tempfile import gettempdir
-        import getpass
-        cache_dir = join(gettempdir(),
-                "pyopencl-compiler-cache-v2-uid%s-py%s" % (
-                    getpass.getuser(), ".".join(str(i) for i in sys.version_info)))
+        import appdirs
+        cache_dir = join(appdirs.user_cache_dir("pyopencl", "pyopencl"),
+                "pyopencl-compiler-cache-v2-py%s" % (
+                    ".".join(str(i) for i in sys.version_info),))
 
     # {{{ ensure cache directory exists
 
     try:
-        os.mkdir(cache_dir)
+        os.makedirs(cache_dir)
     except OSError, e:
         from errno import EEXIST
         if e.errno != EEXIST:
diff --git a/pyopencl/scan.py b/pyopencl/scan.py
index 3b09b7d0d097972714bed7cc8537ab286c472dc8..43e0d18b1c6e142036e7c30b095d93618b69c689 100644
--- a/pyopencl/scan.py
+++ b/pyopencl/scan.py
@@ -1102,9 +1102,9 @@ class GenericScanKernel(_GenericScanKernelBase):
 
                 if have_sol_above_floor:
                     # delete all solutions not meeting the wg size floor
-                    solutions = [(total, k_group_size, wg_size)
-                            for total, k_group_size, wg_size in solutions
-                            if wg_size >= wg_size_floor]
+                    solutions = [(total, try_k_group_size, try_wg_size)
+                            for total, try_k_group_size, try_wg_size in solutions
+                            if try_wg_size >= wg_size_floor]
                     break
 
         _, k_group_size, max_scan_wg_size = max(solutions)
diff --git a/pyopencl/tools.py b/pyopencl/tools.py
index 2f1c6ce340222f1f6bdf00d4027d288aace2cedc..f9603992a81efa80c18429b1c08240d662342077 100644
--- a/pyopencl/tools.py
+++ b/pyopencl/tools.py
@@ -918,6 +918,10 @@ class _CLFakeArrayModule:
         from pyopencl.array import empty
         return empty(self.queue, shape, dtype, order=order)
 
+    def hstack(self, arrays):
+        from pyopencl.array import hstack
+        return hstack(arrays, self.queue)
+
 
 def array_module(a):
     if isinstance(a, np.ndarray):
diff --git a/setup.cfg b/setup.cfg
index eca7b43fd4a3ea8f7a21eb2a4fbdb1aab0cd4fa1..6faef2e65abe138f9ab22c94452c43be0e52c075 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,3 @@
 [flake8]
-ignore = E126,E127,E128,E123,E226,E241,E242
+ignore = E126,E127,E128,E123,E226,E241,E242,E265
 max-line-length=85
diff --git a/setup.py b/setup.py
index d489196f574a7f171ed091c1ef0b9c391d5aa6cb..86a6bdad7e6f570048796aa19d885ab8609e4ff3 100644
--- a/setup.py
+++ b/setup.py
@@ -180,6 +180,7 @@ def main():
         import os.path
         current_directory = os.path.dirname(__file__)
 
+        import shutil
         shutil.rmtree(os.path.join(current_directory,
             'pyopencl', '__pycache__/'), ignore_errors=True)
 
@@ -225,6 +226,7 @@ def main():
                 "pytest>=2",
                 "decorator>=3.2.0",
                 "cffi>=0.7.2",
+                "appdirs>=1.4.0",
                 # "Mako>=0.3.6",
                 ],