Modified and improved the efficiency and readability of hull-detection and its various phases, which also included use of template functions for generic instantiations/allocations and the use of the standard library functions copy/transform to convert between data types and/or create a new image by performing basic element wise binary operations on one or more images.  Also converted the return data type of the x/y/z remaining device functions used by SC/MSC/SM from float to double.

- Replaced the separate hull initialization functions for different data types with a single template function which can initialize a hull of any data type.
- Hull-detection initialization no longer initializes a host array and transfers this to the GPU to initialize a hull on the GPU, a hull is allocated GPU memory and initialized by template kernel function.  Host array is only allocated host memory if needed to be transferred to the host for disk writing or MLP hull selection.  In addition, allocation of arrays for SC/MSC/SM are made only when necessary and deallocated immediately after their existence is no longer needed.  These have also been moved from the SC/MSC/SM and MSC/SM edge-detection functions and into the initialization, finish, and selection functions of hull-detection.
- To reduce the size of a hull and the amount of time it takes to transfer it to/from the GPU, they are declared boolean.  If the MSC/SM hull is to be used by MLP, the integer arrays of 0s/1s needs to be converted to boolean.  Previously this had been done explicitly on the host of GPU by assigning the MSC/SM hull true/false from MSC/SM counts values of 0/1.  This is now performed with the std::transform function using the binary operation std::logical_or<int> evaluated between the counts arrays and themselves, so 1|1 = true and 0|0 = false.
- Similarly, the initial iterate of image reconstruction can be a hull, a float image (e.g. FBP image), or a hybrid composed of a combination of a hull and a float image (e.g. only setting the voxels of the hull to the values in float image).  The initial iterate is a float image, so if hull is used the true/false values must be mappen to 1.0/0.0 and if the hybrid is used the voxels outside the hull can be left 0 and those in the hull can be set to float value by multiplying boolean hull and float image voxels one by one.  The first can be accomplished using std::copy, which automatically casts data if necessary and the second by using std::transform using the hull and image as inputs and the binary operation std::multiplies<float>.  These two approached avoid the need to explicitly assign values without performance degradation.  Note that the copy/transform functions can incur performance costs if improperly used for data type conversion and although these are most likely still less than the costs of explicit assignment, this is why the integer count arrays were converted to hulls using transform instead of copy, as this function gives the user a way to explicitly state why binary operation to use in the conversion.
- Average filter no longer requires a separate kernel to apply new values to image to avoid lack of block synchronization; once the new value is calculated, the original device memory allocated for input image is freed and then its pointer is given the address of the new values, essentially allowing it to now point to its new values instead of explicitily having to assign it the new values.
- To avoid possible trunction/rounding errors, the x/y/z remaining functions were converted from float to double return type, as internal intermediate variables in SC/MSC/SM are of type double.