Index: compare.py
===================================================================
--- compare.py	(revision b89f519c356bd2e11f1aff0bcd59de0fb7a62d1c)
+++ compare.py	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -14,4 +14,5 @@
 from sasmodels import kerneldll
 from sasmodels.convert import revert_model
+kerneldll.ALLOW_SINGLE_PRECISION_DLLS = True
 
 # List of available models
Index: sasmodels/bumps_model.py
===================================================================
--- sasmodels/bumps_model.py	(revision 3c56da87f0995bdde77f4183b68e77b81584dde0)
+++ sasmodels/bumps_model.py	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -365,6 +365,6 @@
         if 'theory' not in self._cache:
             if self._fn is None:
-                input_value = self.model.make_input(self._fn_inputs)
-                self._fn = self.model(input_value)
+                q_input= self.model.make_input(self._fn_inputs)
+                self._fn = self.model(q_input)
 
             fixed_pars = [getattr(self, p).value for p in self._fn.fixed_pars]
Index: sasmodels/kernel_template.c
===================================================================
--- sasmodels/kernel_template.c	(revision 95e861b1d71101b777752f37a0712fccf7f2ce45)
+++ sasmodels/kernel_template.c	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -12,28 +12,24 @@
      #include <cstdio>
      #include <cmath>
+     using namespace std;
      #if defined(_MSC_VER)
-     #define kernel extern "C" __declspec( dllexport )
+     #   define kernel extern "C" __declspec( dllexport )
+         inline double trunc(double x) { return x>=0?floor(x):-floor(-x); }
      #else
-     #define kernel extern "C"
+     #   define kernel extern "C"
      #endif
-     using namespace std;
-     inline void SINCOS(double angle, double &svar, double &cvar)
-       { svar=sin(angle); cvar=cos(angle); }
+     inline void SINCOS(double angle, double &svar, double &cvar) { svar=sin(angle); cvar=cos(angle); }
 #  else
      #include <stdio.h>
-     #include <math.h>
-     #if defined(_MSC_VER)
-     #define kernel __declspec( dllexport )
-     #else
+     #include <tgmath.h> // C99 type-generic math, so sin(float) => sinf
+     // MSVC doesn't support C99, so no need for dllexport on C99 branch
      #define kernel
-     #endif
-     #define SINCOS(angle,svar,cvar) do {svar=sin(angle);cvar=cos(angle);} while (0)
+     #define SINCOS(angle,svar,cvar) do {const double _t_=angle; svar=sin(_t_);cvar=cos(_t_);} while (0)
 #  endif
-     #if defined(_MSC_VER)
-     inline double trunc(double x) { return x>=0?floor(x):-floor(-x); }
-     #endif
 #  define global
 #  define local
 #  define constant const
+// OpenCL powr(a,b) = C99 pow(a,b), b >= 0
+// OpenCL pown(a,b) = C99 pow(a,b), b integer
 #  define powr(a,b) pow(a,b)
 #  define pown(a,b) pow(a,b)
@@ -42,5 +38,5 @@
 #    define SINCOS(angle,svar,cvar) svar=sincos(angle,&cvar)
 #  else
-#    define SINCOS(angle,svar,cvar) do {svar=sin(angle);cvar=cos(angle);} while (0)
+#    define SINCOS(angle,svar,cvar) do {const double _t_=angle; svar=sin(_t_);cvar=cos(_t_);} while (0)
 #  endif
 #endif
@@ -126,7 +122,7 @@
     const double weight = IQ_WEIGHT_PRODUCT;
     if (weight > cutoff) {
-      const double I = Iq(qi, IQ_PARAMETERS);
-      if (I>=0.0) { // scattering cannot be negative
-        ret += weight*I;
+      const double scattering = Iq(qi, IQ_PARAMETERS);
+      if (scattering >= 0.0) { // scattering cannot be negative
+        ret += weight*scattering;
         norm += weight;
       #ifdef VOLUME_PARAMETERS
@@ -136,5 +132,5 @@
       #endif
       }
-    //else { printf("exclude qx,qy,I:%%g,%%g,%%g\n",qi,I); }
+    //else { printf("exclude qx,qy,I:%%g,%%g,%%g\n",qi,scattering); }
     }
     IQ_CLOSE_LOOPS
@@ -199,6 +195,6 @@
     if (weight > cutoff) {
 
-      const double I = Iqxy(qxi, qyi, IQXY_PARAMETERS);
-      if (I>=0.0) { // scattering cannot be negative
+      const double scattering = Iqxy(qxi, qyi, IQXY_PARAMETERS);
+      if (scattering >= 0.0) { // scattering cannot be negative
         // TODO: use correct angle for spherical correction
         // Definition of theta and phi are probably reversed relative to the
@@ -211,7 +207,7 @@
         const double spherical_correction
           = (Ntheta>1 ? fabs(cos(M_PI_180*theta))*M_PI_2:1.0);
-        ret += spherical_correction * weight * I;
+        ret += spherical_correction * weight * scattering;
       #else
-        ret += weight * I;
+        ret += weight * scattering;
       #endif
         norm += weight;
@@ -222,5 +218,5 @@
         norm_vol += vol_weight;
       }
-      //else { printf("exclude qx,qy,I:%%g,%%g,%%g\n",qi,I); }
+      //else { printf("exclude qx,qy,I:%%g,%%g,%%g\n",qi,scattering); }
     }
     IQXY_CLOSE_LOOPS
Index: sasmodels/kernelcl.py
===================================================================
--- sasmodels/kernelcl.py	(revision 3c56da87f0995bdde77f4183b68e77b81584dde0)
+++ sasmodels/kernelcl.py	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -68,5 +68,5 @@
     #open(info['name']+'.cl','w').write(source)
     #source = open(info['name']+'.cl','r').read()
-    return GpuModel(source, info, dtype)
+    return GpuModel(source, info, np.dtype(dtype))
 
 ENV = None
@@ -92,6 +92,7 @@
     Return the size of an execution batch for *kernel* running on *queue*.
     """
-    return kernel.get_work_group_info(cl.kernel_work_group_info.PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
-                                      queue.device)
+    return kernel.get_work_group_info(
+            cl.kernel_work_group_info.PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
+            queue.device)
 
 def _stretch_input(vector, dtype, extra=1e-3, boundary=32):
@@ -219,5 +220,5 @@
         self.info = info
         self.source = source
-        self.dtype = dtype
+        self.dtype = np.dtype(dtype)
         self.program = None # delay program creation
 
@@ -230,13 +231,13 @@
         self.__dict__ = state.copy()
 
-    def __call__(self, input_value):
-        if self.dtype != input_value.dtype:
-            raise TypeError("data and kernel have different types")
+    def __call__(self, q_input):
+        if self.dtype != q_input.dtype:
+            raise TypeError("data is %s kernel is %s" % (q_input.dtype, self.dtype))
         if self.program is None:
             compiler = environment().compile_program
             self.program = compiler(self.info['name'], self.source, self.dtype)
-        kernel_name = generate.kernel_name(self.info, input_value.is_2D)
+        kernel_name = generate.kernel_name(self.info, q_input.is_2D)
         kernel = getattr(self.program, kernel_name)
-        return GpuKernel(kernel, self.info, input_value)
+        return GpuKernel(kernel, self.info, q_input)
 
     def release(self):
Index: sasmodels/kerneldll.py
===================================================================
--- sasmodels/kerneldll.py	(revision 3c56da87f0995bdde77f4183b68e77b81584dde0)
+++ sasmodels/kerneldll.py	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -1,10 +1,15 @@
 """
 C types wrapper for sasview models.
+
+The global attribute *ALLOW_SINGLE_PRECISION_DLLS* should be set to *True* if
+you wish to allow single precision floating point evaluation for the compiled
+models, otherwise it defaults to *False*.
 """
+
 import sys
 import os
 import tempfile
 import ctypes as ct
-from ctypes import c_void_p, c_int, c_double
+from ctypes import c_void_p, c_int, c_double, c_float
 
 import numpy as np
@@ -36,6 +41,8 @@
 DLL_PATH = tempfile.gettempdir()
 
-
-def dll_path(info):
+ALLOW_SINGLE_PRECISION_DLLS = False
+
+
+def dll_path(info, dtype="double"):
     """
     Path to the compiled model defined by *info*.
@@ -43,8 +50,10 @@
     from os.path import join as joinpath, split as splitpath, splitext
     basename = splitext(splitpath(info['filename'])[1])[0]
+    if np.dtype(dtype) == generate.F32:
+        basename += "32"
     return joinpath(DLL_PATH, basename+'.so')
 
 
-def load_model(kernel_module, dtype=None):
+def load_model(kernel_module, dtype="double"):
     """
     Load the compiled model defined by *kernel_module*.
@@ -57,13 +66,23 @@
     be defined without using too many resources.
     """
+    if not ALLOW_SINGLE_PRECISION_DLLS: dtype = "double"   # Force 64-bit dll
+    dtype = np.dtype(dtype)
+
     source, info = generate.make(kernel_module)
     if callable(info.get('Iq',None)):
         return PyModel(info)
+
+    if dtype == generate.F32: # 32-bit dll
+        source = generate.use_single(source)
+        tempfile_prefix = 'sas_'+info['name']+'32_'
+    else:
+        tempfile_prefix = 'sas_'+info['name']+'_'
+
     source_files = generate.sources(info) + [info['filename']]
+    dllpath = dll_path(info, dtype)
     newest = max(os.path.getmtime(f) for f in source_files)
-    dllpath = dll_path(info)
     if not os.path.exists(dllpath) or os.path.getmtime(dllpath)<newest:
         # Replace with a proper temp file
-        fid, filename = tempfile.mkstemp(suffix=".c",prefix="sas_"+info['name'])
+        fid, filename = tempfile.mkstemp(suffix=".c",prefix=tempfile_prefix)
         os.fdopen(fid,"w").write(source)
         command = COMPILE%{"source":filename, "output":dllpath}
@@ -76,5 +95,5 @@
             #os.unlink(filename); print "saving compiled file in %r"%filename
             pass
-    return DllModel(dllpath, info)
+    return DllModel(dllpath, info, dtype=dtype)
 
 
@@ -96,8 +115,9 @@
     Call :meth:`release` when done with the kernel.
     """
-    def __init__(self, dllpath, info):
+    def __init__(self, dllpath, info, dtype=generate.F32):
         self.info = info
         self.dllpath = dllpath
         self.dll = None
+        self.dtype = np.dtype(dtype)
 
     def _load_dll(self):
@@ -110,11 +130,12 @@
         self.dll = ct.CDLL(self.dllpath)
 
-        pd_args_1d = [c_void_p, c_double] + [c_int]*Npd1d if Npd1d else []
-        pd_args_2d= [c_void_p, c_double] + [c_int]*Npd2d if Npd2d else []
+        fp = c_float if self.dtype == generate.F32 else c_double
+        pd_args_1d = [c_void_p, fp] + [c_int]*Npd1d if Npd1d else []
+        pd_args_2d= [c_void_p, fp] + [c_int]*Npd2d if Npd2d else []
         self.Iq = self.dll[generate.kernel_name(self.info, False)]
-        self.Iq.argtypes = IQ_ARGS + pd_args_1d + [c_double]*Nfixed1d
+        self.Iq.argtypes = IQ_ARGS + pd_args_1d + [fp]*Nfixed1d
 
         self.Iqxy = self.dll[generate.kernel_name(self.info, True)]
-        self.Iqxy.argtypes = IQXY_ARGS + pd_args_2d + [c_double]*Nfixed2d
+        self.Iqxy.argtypes = IQXY_ARGS + pd_args_2d + [fp]*Nfixed2d
 
     def __getstate__(self):
@@ -125,4 +146,6 @@
 
     def __call__(self, q_input):
+        if self.dtype != q_input.dtype:
+            raise TypeError("data is %s kernel is %s" % (q_input.dtype, self.dtype))
         if self.dll is None: self._load_dll()
         kernel = self.Iqxy if q_input.is_2D else self.Iq
@@ -138,5 +161,5 @@
         ctypes and some may be pure python.
         """
-        return PyInput(q_vectors, dtype=F64)
+        return PyInput(q_vectors, dtype=self.dtype)
 
     def release(self):
Index: sasmodels/kernelpy.py
===================================================================
--- sasmodels/kernelpy.py	(revision 3c56da87f0995bdde77f4183b68e77b81584dde0)
+++ sasmodels/kernelpy.py	(revision 750ffa58d4841615a93ccb846e347c34ab7cb9e9)
@@ -43,5 +43,5 @@
         self.is_2D = (len(q_vectors) == 2)
         self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors]
-        self.q_pointers = [q.ctypes.data for q in q_vectors]
+        self.q_pointers = [q.ctypes.data for q in self.q_vectors]
 
     def release(self):
