content: package edu.stanford.rsl.conrad.cuda;
  
  /*
   * JCuda - Java bindings for NVIDIA CUDA driver and runtime API
   * http://www.jcuda.org
   *
   * DISCLAIMER: THIS SOFTWARE IS PROVIDED WITHOUT WARRANTY OF ANY KIND
   * If you find any bugs or errors, contact me at http://www.jcuda.org
   *
   * LICENSE: THIS SOFTWARE IS FREE FOR NON-COMMERCIAL USE ONLY
   * For non-commercial applications, you may use this software without
   * any restrictions. If you wish to use it for commercial purposes,
   * contact me at http://www.jcuda.org
   */
  
  import java.util.*;
  
  import jcuda.*;
  import jcuda.jcublas.*;
  import jcuda.jcudpp.*;
  import jcuda.jcufft.*;
  import jcuda.runtime.*;
  
  /**
   * This is a class that demonstrates the interoperability among
   * JCuda, JCufft, JCublas and JCudpp. It performs several 
   * computations using each library, using always the same
   * "shared" device memory.
   */
  public class JCudaRuntimeSample
  {
      public static void main(String args[])
      {
          System.out.println("Creating input data");
          
       // the classpath
          System.out.println( System.getProperty( "java.class.path" ) );
  
          // extension directories whose jars are included on the classpath
          System.out.println( System.getProperty( "java.ext.dirs" ) );
  
          // low level classpath, includes system jars
          System.out.println( System.getProperty( "java.library.path" ) );
  
          // character to separate (not terminate!) entries on the classpath, ; for Windows : for unix.
          System.out.println( System.getProperty( "path.separator" ) );
  
  
          // Create some input data
          int complexElements = 100;
          int floatElements = complexElements * 2;
          int memorySize = floatElements * Sizeof.FLOAT;
          float hostX[] = createRandomFloatData(floatElements);
          float hostY[] = createRandomFloatData(floatElements);
  
          
          System.out.println("Initializing device data using JCuda");
          
          // Allocate memory on the device using JCuda
          Pointer deviceX = new Pointer();
          Pointer deviceY = new Pointer();
          JCuda.cudaMalloc(deviceX, memorySize);
          JCuda.cudaMalloc(deviceY, memorySize);
          
          // Copy memory from host to device using JCuda
          JCuda.cudaMemcpy(deviceX, Pointer.to(hostX), memorySize, 
              cudaMemcpyKind.cudaMemcpyHostToDevice);
          JCuda.cudaMemcpy(deviceY, Pointer.to(hostY), memorySize, 
              cudaMemcpyKind.cudaMemcpyHostToDevice);
          
  
          System.out.println("Performing FFT using JCufft");
          
          // Perform in-place complex-to-complex 1D transforms using JCufft
          cufftHandle plan = new cufftHandle();
          JCufft.cufftPlan1d(plan, complexElements, cufftType.CUFFT_C2C, 1);
          JCufft.cufftExecC2C(plan, deviceX, deviceX, JCufft.CUFFT_FORWARD);
          JCufft.cufftExecC2C(plan, deviceY, deviceY, JCufft.CUFFT_FORWARD);
  
  
          System.out.println("Performing caxpy using JCublas");
          
          // Perform a complex y=a*x+y operation (caxpy) using JCublas
          cuComplex alpha = cuComplex.cuCmplx(0.3f, 0.7f);
          JCublas.cublasInit();
          JCublas.cublasCaxpy(complexElements, alpha, deviceX, 1, deviceY, 1);
          
  
          // This is a sample application, so perform a scan of one 
          // of the complex vectors using JCudpp, although this does 
          // not make any sense...
          
          System.out.println("Performing scan using JCudpp");
          
          // Create a configuration that describes a scan
          CUDPPConfiguration config = new CUDPPConfiguration();
          config.op = CUDPPOperator.CUDPP_ADD;
          config.datatype = CUDPPDatatype.CUDPP_FLOAT;
          config.algorithm = CUDPPAlgorithm.CUDPP_SCAN;
          config.options = CUDPPOption.CUDPP_OPTION_FORWARD;
          
          // Create a CUDPPHandle for the scan operation
          CUDPPHandle handle = new CUDPPHandle();
          JCudpp.cudppPlan(handle, config, complexElements, 1, 0);  
  
          // Run the scan
          JCudpp.cudppScan(handle, deviceX, deviceY, floatElements);
      
          
          // Copy the result from the device to the host
          JCuda.cudaMemcpy(Pointer.to(hostX), deviceX, memorySize, 
              cudaMemcpyKind.cudaMemcpyDeviceToHost);
          
          System.out.println("Result: "+hostX[hostX.length-1]);
          
          // Clean up
          JCuda.cudaFree(deviceX);
          JCuda.cudaFree(deviceY);
          JCublas.cublasShutdown();
          JCufft.cufftDestroy(plan);
          JCudpp.cudppDestroyPlan(handle);
      }
  
      /**
       * Creates an array of the specified size, containing some random data
       */
      private static float[] createRandomFloatData(int x)
      {
          Random random = new Random(0);
          float a[] = new float[x];
          for (int i=0; i<x; i++)
          {
              a[i] = random.nextFloat();
          }
          return a;
      }
  }
  
  