diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e371192f98f3004c0c3949fe91a5ec48b9296862..2f7b3f008c4677660951f67ca435fbbdf6ed8d14 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -77,3 +77,13 @@ Python 2.7 with legacy PyOpenCL:
 #   - amd-cl-cpu
 #   except:
 #   - tags
+
+CentOS binary:
+  script:
+  - (cd build-helpers; ./make-linux-build-docker.sh --nodate)
+  - (cd ./build-helpers; ./loopy-centos6 ../examples/fortran/sparse.floopy)
+  artifacts:
+    paths:
+    - build-helpers/loopy-centos6
+  tags:
+  - docker
diff --git a/bin/loopy b/bin/loopy
index 8291bdd3bfe5c157fca5bc4ad60ced2839ae529f..b169c6296acd453cf4183ee603813d186119d317 100644
--- a/bin/loopy
+++ b/bin/loopy
@@ -64,7 +64,7 @@ def main():
             help="Defaults to stdout ('-').", nargs='?')
     parser.add_argument("--lang", metavar="LANGUAGE", help="loopy|fortran")
     parser.add_argument("--target", choices=(
-        "opencl", "ispc", "ispc-occa", "c", "cuda"),
+        "opencl", "ispc", "ispc-occa", "c", "c-fortran", "cuda"),
         default="opencl")
     parser.add_argument("--name")
     parser.add_argument("--transform")
@@ -86,6 +86,9 @@ def main():
     elif args.target == "c":
         from loopy.target.c import CTarget
         target = CTarget()
+    elif args.target == "c-fortran":
+        from loopy.target.c import CTarget
+        target = CTarget(fortran_abi=True)
     elif args.target == "cuda":
         from loopy.target.cuda import CudaTarget
         target = CudaTarget()
@@ -102,10 +105,13 @@ def main():
         _, ext = splitext(args.infile)
 
         lang = {
+                ".py": "loopy",
                 ".loopy": "loopy",
                 ".floopy": "fortran",
                 ".f90": "fortran",
                 ".fpp": "fortran",
+                ".f": "fortran",
+                ".f77": "fortran",
                 }.get(ext)
         with open(args.infile, "r") as infile_fd:
             infile_content = infile_fd.read()
@@ -221,16 +227,25 @@ def main():
 
     code = "\n\n".join(codes)
 
+    # {{{ edit code if requested
+
     import os
     edit_kernel_env = os.environ.get("LOOPY_EDIT_KERNEL")
-    if (args.edit_code
-            or (
-                edit_kernel_env is not None
-                and
-                any(edit_kernel_env.lower() in k.name.lower() for k in kernels))):
+    need_edit = args.edit_code
+    if not need_edit and edit_kernel_env is not None:
+        # Do not replace with "any()"--Py2.6/2.7 bug doesn't like
+        # comprehensions in functions with exec().
+
+        for k in kernels:
+            if edit_kernel_env.lower() in k.name.lower():
+                need_edit = True
+
+    if need_edit:
         from pytools import invoke_editor
         code = invoke_editor(code, filename="edit.cl")
 
+    # }}}
+
     if outfile == "-":
         sys.stdout.write(code)
     else:
diff --git a/build-helpers/loopy.spec b/build-helpers/loopy.spec
index 31162a2c6157504cc1363c95ad380780809865bd..14116ec539381137e0423855550773a43ad423d6 100644
--- a/build-helpers/loopy.spec
+++ b/build-helpers/loopy.spec
@@ -10,9 +10,16 @@ debug = False
 
 from os.path import expanduser
 
+import packaging # pip install packaging to add
+
 a = Analysis(['../bin/loopy'],
              pathex=[expanduser('~/src/loopy')],
-             hiddenimports=["appdirs"],
+             hiddenimports=[
+                "appdirs",
+                "packaging.markers",
+                "packaging.specifiers",
+                "packaging.version",
+                ],
              hookspath=None,
              runtime_hooks=None,
              excludes=["hedge", "meshpy", "pyopencl", "PIL"]
diff --git a/build-helpers/make-linux-build-docker-inner-part-2.sh b/build-helpers/make-linux-build-docker-inner-part-2.sh
new file mode 100755
index 0000000000000000000000000000000000000000..d6f3ff3266192aec6b1761b771320966432d9166
--- /dev/null
+++ b/build-helpers/make-linux-build-docker-inner-part-2.sh
@@ -0,0 +1,31 @@
+#! /bin/bash
+
+set -e
+set -x
+
+VENV_VERSION="virtualenv-1.9.1"
+rm -Rf "$VENV_VERSION"
+curl -k https://pypi.python.org/packages/source/v/virtualenv/$VENV_VERSION.tar.gz | tar xfz -
+
+$VENV_VERSION/virtualenv.py --system-site-packages --no-setuptools .env
+
+source .env/bin/activate
+
+curl -k https://ssl.tiker.net/software/ez_setup.py | python -
+curl -k https://gitlab.tiker.net/inducer/pip/raw/7.0.3/contrib/get-pip.py | python -
+
+pip install packaging
+
+PYTHON_VER=$(python -c 'import sys; print(".".join(str(s) for s in sys.version_info[:2]))')
+pip install git+https://github.com/pyinstaller/pyinstaller.git@413c37bec126c0bd26084813593f65128966b4b7
+
+git clone --recursive git://github.com/inducer/loopy
+cd loopy
+
+grep -v pyopencl requirements.txt > myreq.txt
+pip install -r myreq.txt
+python setup.py install
+
+chown -R user /tmp/build
+
+su user -p -c "cd /tmp/build && source .env/bin/activate && cd loopy && ./build-helpers/run-pyinstaller.sh"
diff --git a/build-helpers/make-linux-build-docker-inner.sh b/build-helpers/make-linux-build-docker-inner.sh
index 6b72639e0de24ee7e424a6157de2064e5beee978..119609a3c1767dd1e5ce1781f27c946781d1a79b 100755
--- a/build-helpers/make-linux-build-docker-inner.sh
+++ b/build-helpers/make-linux-build-docker-inner.sh
@@ -8,28 +8,8 @@ cd /tmp/build
 
 useradd -d /home/user -m -s /bin/bash user
 
-yum install -y git python-devel tar gcc gcc-c++ mercurial numpy libffi-devel
+yum install -y centos-release-SCL
+yum install -y git python27 python27-python-devel python27-numpy tar gcc gcc-c++ mercurial libffi-devel
 
-VENV_VERSION="virtualenv-1.9.1"
-rm -Rf "$VENV_VERSION"
-curl -k https://pypi.python.org/packages/source/v/virtualenv/$VENV_VERSION.tar.gz | tar xfz -
+scl enable python27 /mnt/make-linux-build-docker-inner-part-2.sh
 
-VIRTUALENV=virtualenv
-$VENV_VERSION/virtualenv.py --system-site-packages --no-setuptools .env
-
-source .env/bin/activate
-
-curl -k https://ssl.tiker.net/software/ez_setup.py | python -
-curl -k https://gitlab.tiker.net/inducer/pip/raw/7.0.3/contrib/get-pip.py | python -
-
-pip install pyinstaller
-git clone --recursive git://github.com/inducer/loopy
-cd loopy
-
-grep -v pyopencl requirements.txt > myreq.txt
-pip install -r myreq.txt
-python setup.py install
-
-chown -R user /tmp/build
-
-su user -p -c "cd /tmp/build && source .env/bin/activate && cd loopy && ./build-helpers/run-pyinstaller.sh"
diff --git a/build-helpers/make-linux-build-docker.sh b/build-helpers/make-linux-build-docker.sh
index 90684a267e98f1976a31fd3036b824d2c2cdc1d8..fb0cfb587d654698800bfdc827259691bc056fb7 100755
--- a/build-helpers/make-linux-build-docker.sh
+++ b/build-helpers/make-linux-build-docker.sh
@@ -2,9 +2,19 @@
 
 # should be run in this directory (build-helpers)
 
+if test "$1" = "--nodate"; then
+  TGT_NAME=loopy-centos6
+else
+  TGT_NAME=loopy-centos6-$(date +"%Y-%m-%d")
+fi
+
+echo "Generating $TGT_NAME..."
+
 set -e
 set -x
 
+docker pull centos:6
+
 CNT=$(docker create -t -v $(pwd):/mnt centos:6 /mnt/make-linux-build-docker-inner.sh)
 echo "working in container $CNT"
 
@@ -12,7 +22,7 @@ docker start -i $CNT
 
 docker cp $CNT:/tmp/build/loopy/dist/loopy $(pwd) || true
 
-mv loopy loopy-centos6-$(date +"%Y-%m-%d")
+mv loopy $TGT_NAME
 
 docker rm $CNT
 
diff --git a/doc/index.rst b/doc/index.rst
index 73fd85f52fff0068d5a91e54c8ea37d4524185ee..19bbe87727e8d3ffa5aa0cb1c31e4e206bd97b3e 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -18,6 +18,29 @@ When you run this script, the following kernel is generated, compiled, and execu
 
 (See the full example for how to print the generated code.)
 
+Want to try out loopy?
+----------------------
+
+There's no need to go through :ref:`installation` if you'd just like to get a
+feel for what loopy is.  Instead, you may
+`download a self-contained Linux binary <https://gitlab.tiker.net/inducer/loopy/builds/1989/artifacts/browse/build-helpers/>`_.
+This is purposefully built on an ancient Linux distribution, so it should work
+on most versions of Linux that are currently out there.
+
+Once you have the binary, do the following::
+
+    chmod +x ./loopy-centos6
+    ./loopy-centos6 --target=opencl hello-loopy-lp.py
+    ./loopy-centos6 --target=cuda hello-loopy-lp.py
+    ./loopy-centos6 --target=ispc hello-loopy-lp.py
+
+Grab the example here: :download:`examples/python/hello-loopy.py <../examples/python/hello-loopy-lp.py>`.
+
+You may also donwload the most recent version by going to the `list of builds
+<https://gitlab.tiker.net/inducer/loopy/builds>`_, clicking on the newest one
+of type "CentOS binary", clicking on "Browse" under "Build Artifacts", then
+navigating to "build-helpers", and downloading the binary from there.
+
 Places on the web related to Loopy
 ----------------------------------
 
diff --git a/doc/misc.rst b/doc/misc.rst
index a07a772eb5bb97ce98414b80038057476bd27dd1..fc170120f894f2cf5645d86621e56680019d3fae 100644
--- a/doc/misc.rst
+++ b/doc/misc.rst
@@ -5,7 +5,7 @@ Installation
 
 This command should install :mod:`loopy`::
 
-    pip install https://github.com/inducer/loopy/tarball/master
+    pip install loopy
 
 You may need to run this with :command:`sudo`.
 If you don't already have `pip <https://pypi.python.org/pypi/pip>`_,
@@ -27,14 +27,17 @@ You may also clone its git repository::
 User-visible Changes
 ====================
 
-Version 2014.1
+Version 2016.2
 --------------
 .. note::
 
     This version is currently under development. You can get snapshots from
-    PyOpenCL's `git repository <https://github.com/inducer/loopy>`_
+    loopy's `git repository <https://github.com/inducer/loopy>`_
 
-* Initial release. 
+Version 2016.1
+--------------
+
+* Initial release.
 
 .. _license:
 
diff --git a/examples/python/hello-loopy-lp.py b/examples/python/hello-loopy-lp.py
index 382aadc097352ab7328b9ef956e0c0379d06a2cb..0ba44d6eccb18236ac13e17ca747318af3962634 100644
--- a/examples/python/hello-loopy-lp.py
+++ b/examples/python/hello-loopy-lp.py
@@ -8,4 +8,4 @@ knl = lp.make_kernel(
         "out[i] = 2*a[i]")
 
 knl = lp.add_and_infer_dtypes(knl, dict(a=np.float32))
-lp_knl = lp.split_iname(knl, "i", 128, outer_tag="g.0", inner_tag="l.0")
+lp_knl = lp.split_iname(knl, "i", 8, outer_tag="g.0", inner_tag="l.0")
diff --git a/loopy/frontend/fortran/translator.py b/loopy/frontend/fortran/translator.py
index c708fc4a1d2980dbe36cd243678f355d441fbdd7..53ea602f1d9b0a5b4fd9b04bc2486d7daae0ca5f 100644
--- a/loopy/frontend/fortran/translator.py
+++ b/loopy/frontend/fortran/translator.py
@@ -301,6 +301,7 @@ class F2LoopyTranslator(FTreeWalkerBase):
     TYPE_MAP = {
             ("real", "4"): np.float32,
             ("real", "8"): np.float64,
+            ("doubleprecision", ""): np.float64,
 
             ("complex", "8"): np.complex64,
             ("complex", "16"): np.complex128,
@@ -339,6 +340,7 @@ class F2LoopyTranslator(FTreeWalkerBase):
     map_Integer = map_type_decl
     map_Real = map_type_decl
     map_Complex = map_type_decl
+    map_DoublePrecision = map_type_decl
 
     def map_Dimension(self, node):
         scope = self.scope_stack[-1]
diff --git a/loopy/kernel/__init__.py b/loopy/kernel/__init__.py
index 46888e620501785073e2abf58180a5c6c93109d1..d125b0dfa964688e60d02fae242f2f1876b22f87 100644
--- a/loopy/kernel/__init__.py
+++ b/loopy/kernel/__init__.py
@@ -1155,7 +1155,7 @@ class LoopKernel(RecordWithoutPickling):
 
     # {{{ persistent hash key generation / comparison
 
-    hash_fields = [
+    hash_fields = (
             "domains",
             "instructions",
             "args",
@@ -1173,9 +1173,9 @@ class LoopKernel(RecordWithoutPickling):
             "options",
             "state",
             "target",
-            ]
+            )
 
-    comparison_fields = hash_fields + [
+    comparison_fields = hash_fields + (
             # Contains pymbolic expressions, hence a (small) headache to hash.
             # Likely not needed for hash uniqueness => headache avoided.
             "applied_iname_rewrites",
@@ -1189,7 +1189,7 @@ class LoopKernel(RecordWithoutPickling):
             "preamble_generators",
             "function_manglers",
             "symbol_manglers",
-            ]
+            )
 
     def update_persistent_hash(self, key_hash, key_builder):
         """Custom hash computation function for use with
diff --git a/loopy/target/__init__.py b/loopy/target/__init__.py
index b8c903fc12cccde4e764731580cc8cfc04151af3..ee28594a50ce8486702e13f0ee9bf01debb4f859 100644
--- a/loopy/target/__init__.py
+++ b/loopy/target/__init__.py
@@ -30,8 +30,8 @@ class TargetBase(object):
 
     # {{{ persistent hashing
 
-    hash_fields = []
-    comparison_fields = []
+    hash_fields = ()
+    comparison_fields = ()
 
     def update_persistent_hash(self, key_hash, key_builder):
         for field_name in self.hash_fields:
diff --git a/loopy/target/c/__init__.py b/loopy/target/c/__init__.py
index 0cf17992251778ee971298e736bd1080f6f36f13..73310c4db7ad590396377d1d757ebf8eb068a8e6 100644
--- a/loopy/target/c/__init__.py
+++ b/loopy/target/c/__init__.py
@@ -56,6 +56,13 @@ def _preamble_generator(kernel, seen_dtypes, seen_functions):
 
 
 class CTarget(TargetBase):
+    hash_fields = TargetBase.hash_fields + ("fortran_abi",)
+    comparison_fields = TargetBase.comparison_fields + ("fortran_abi",)
+
+    def __init__(self, fortran_abi=False):
+        self.fortran_abi = fortran_abi
+        super(CTarget, self).__init__()
+
     # {{{ types
 
     @memoize_method
@@ -101,12 +108,16 @@ class CTarget(TargetBase):
         body, implemented_domains = kernel.target.generate_body(
                 kernel, codegen_state)
 
+        name = kernel.name
+        if self.fortran_abi:
+            name += "_"
+
         mod = Module([
             FunctionBody(
                 kernel.target.wrap_function_declaration(
                     kernel,
                     FunctionDeclaration(
-                        Value("void", kernel.name),
+                        Value("void", name),
                         [iai.cgen_declarator for iai in impl_arg_info])),
                 body)
             ])
@@ -234,7 +245,7 @@ class CTarget(TargetBase):
 
     def get_expression_to_code_mapper(self, codegen_state):
         from loopy.target.c.codegen.expression import LoopyCCodeMapper
-        return LoopyCCodeMapper(codegen_state)
+        return LoopyCCodeMapper(codegen_state, fortran_abi=self.fortran_abi)
 
     def wrap_temporary_decl(self, decl, is_local):
         return decl
@@ -247,6 +258,11 @@ class CTarget(TargetBase):
         if not is_written:
             from cgen import Const
             result = Const(result)
+
+        if self.fortran_abi:
+            from cgen import Pointer
+            result = Pointer(result)
+
         return result
 
     def get_global_arg_decl(self, name, shape, dtype, is_written):
diff --git a/loopy/target/c/codegen/expression.py b/loopy/target/c/codegen/expression.py
index 2bf5c06bad405fba3a6a01f039cee0f4a133322c..d931ebf3373b7ab455787f5be7db7360cc042e66 100644
--- a/loopy/target/c/codegen/expression.py
+++ b/loopy/target/c/codegen/expression.py
@@ -42,13 +42,15 @@ from loopy.tools import is_integer
 # {{{ C code mapper
 
 class LoopyCCodeMapper(RecursiveMapper):
-    def __init__(self, codegen_state):
+    def __init__(self, codegen_state, fortran_abi=False):
         self.kernel = codegen_state.kernel
         self.codegen_state = codegen_state
 
         self.type_inf_mapper = TypeInferenceMapper(self.kernel)
         self.allow_complex = codegen_state.allow_complex
 
+        self.fortran_abi = fortran_abi
+
     # {{{ helpers
 
     def infer_type(self, expr):
@@ -108,6 +110,8 @@ class LoopyCCodeMapper(RecursiveMapper):
                 "entry to loopy")
 
     def map_variable(self, expr, enclosing_prec, type_context):
+        prefix = ""
+
         if expr.name in self.codegen_state.var_subst_map:
             if self.kernel.options.annotate_inames:
                 return " /* %s */ %s" % (
@@ -131,12 +135,16 @@ class LoopyCCodeMapper(RecursiveMapper):
                     raise RuntimeError("unsubscripted reference to array '%s'"
                             % expr.name)
 
+            from loopy.kernel.data import ValueArg
+            if isinstance(arg, ValueArg) and self.fortran_abi:
+                prefix = "*"
+
         result = self.kernel.mangle_symbol(expr.name)
         if result is not None:
             _, c_name = result
-            return c_name
+            return prefix + c_name
 
-        return expr.name
+        return prefix + expr.name
 
     def map_tagged_variable(self, expr, enclosing_prec, type_context):
         return expr.name
diff --git a/loopy/target/cuda.py b/loopy/target/cuda.py
index 4b3237515152965f1d7c0f7ddd271d25e3afb767..94a144cb972b10cd7a1d797adbd8d259e7eb64dc 100644
--- a/loopy/target/cuda.py
+++ b/loopy/target/cuda.py
@@ -169,6 +169,8 @@ class CudaTarget(CTarget):
         """
         self.extern_c = extern_c
 
+        super(CudaTarget, self).__init__()
+
     # {{{ library
 
     def function_manglers(self):
diff --git a/loopy/target/ispc.py b/loopy/target/ispc.py
index 4fcccf8ab7c938b13a6fa76253010f80a7465520..f28dc4e72e8bc639b7c0483a0b31c96beb29fec4 100644
--- a/loopy/target/ispc.py
+++ b/loopy/target/ispc.py
@@ -62,6 +62,8 @@ class ISPCTarget(CTarget):
         """
         self.occa_mode = occa_mode
 
+        super(ISPCTarget, self).__init__()
+
     # {{{ top-level codegen
 
     def generate_code(self, kernel, codegen_state, impl_arg_info):
diff --git a/loopy/version.py b/loopy/version.py
index 4154c3a59cd2e2db383db3e4670ce55365ede1c1..2b35b55e073359992a483f494d56b8d3a912fd64 100644
--- a/loopy/version.py
+++ b/loopy/version.py
@@ -32,4 +32,4 @@ except ImportError:
 else:
     _islpy_version = islpy.version.VERSION_TEXT
 
-DATA_MODEL_VERSION = "v17-islpy%s" % _islpy_version
+DATA_MODEL_VERSION = "v18-islpy%s" % _islpy_version
diff --git a/requirements.txt b/requirements.txt
index df54704f8091c6c4b8807c7d7b7b1d09d918cc9e..5dbc4b050f4dd688e038b994281e08e73ab3133b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,3 +8,6 @@ hg+https://bitbucket.org/inducer/f2py
 
 # Optional, needed for using the C preprocessor on Fortran
 ply>=3.6
+
+# This is needed for the pyinstaller executable to be usable.
+packaging