import java.io.*;
import java.util.*;
import java.net.*;

class cpuInfo {

   static final int VENDOR = 0;
   static final int MODEL =  1;
   static final int FAMILY = 2;
   static final int TYPE = 3;
   static final int UNKNOWN = 0;
   static final int INTEL =  1;
   static final int AMD   =  2;
   static final int SSE   =  0;
   static final int SSE2  =  1;
   static final int SSE3  =  2;
   static final int SUPPORTED = 1;
   static final int UNSUPPORTED = 0;
   static final int L1 = 0;
   static final int L2 = 1;
   static final int THIRTY_TWO_BIT = 0;
   static final int SIXTY_FOUR_BIT = 1;

   // native method which fills in the values in 3 integer arrays:
   // model  : info on cpu vendor, cpu model, cpu family 
   // ise    : info on what instruction set extensions are supported  
   // caches : caches sizes in KB 
   private native void get_cpu_info( int  model[], int ise[], int caches[]);


      public static void main ( String [] args ) {

         int address_system =  THIRTY_TWO_BIT;
         String file, install_dir,install_file;
         String cmd,info;
         int[] model = new int[10];
         int[] ise = new int[10];
         int[] caches = new int[10];

         try {
            // load the native library which calls the assembly code for the
            // cpuid instruction 
            System.loadLibrary ( "getCpuInfo" ) ; 
            
            // call native method to get cpu info
            new cpuInfo().get_cpu_info(model, ise, caches);

            // determine the cpu vendor 
            if( model[VENDOR] == INTEL ) {
               System.out.println("Intel ");
            
            }else if( model[VENDOR] == AMD ) {
               System.out.println("AMD ");
            } else {
               System.out.println(" *** Unknown CPU manufacturer  *** \n");
            }
            System.out.println("model= "+model[MODEL]);
            System.out.println("family= "+model[FAMILY]);

            // determine which instruction set extensions are supported 
           if( ise[SSE] == SUPPORTED ){ 
               System.out.println("SSE supported ");
           }
           if( ise[SSE2] == SUPPORTED ) { 
               System.out.println("SSE2 supported ");
           }
           if( ise[SSE3] == SUPPORTED ) { 
               System.out.println("SSE supported3 ");
           }

            System.out.println("caches= "+caches[L1]+" "+caches[L2]+"\n");
               
           // on a linux system, we can parse the output of  a uname -i 
           // to determine if it is a 64 or 32 bit system:
           // > uname -i
           // > x86_64
           Process p = Runtime.getRuntime().exec("uname -i");
           BufferedReader in = new BufferedReader(
           new InputStreamReader(p.getInputStream()));
           String line = null;
            
               // determine if 32/64bit system
               line = null;
               while ((line = in.readLine()) != null) {
                  if( line.endsWith("64") ) {
                     address_system = SIXTY_FOUR_BIT; 
                     System.out.println("64bit ");
                  } else {
                     address_system =  THIRTY_TWO_BIT; 
                     System.out.println("32bit ");
                  }
               }

               file = "/intel64_lapack";
               if ( model[VENDOR] == INTEL ) {
                  if( address_system == SIXTY_FOUR_BIT ) {
                         file = "/intel64_lapack";
                  } else {
                         file = "/intel32_lapack";
                  }
               } else if (model[VENDOR] == AMD){
                  if( address_system ==  THIRTY_TWO_BIT ) {
                         file = "/amd64_lapack";
                  } else {
                         file = "/amd32_lapack";
                  }

               }
        
          // default install directory for now
               install_dir = "/usr/local/simtk/lapack/lib";
               System.out.println("install_file ="+install_dir+file);

               download( "http://dev.simtk.org/jacklm/lapack"+file, 
                           install_dir + file);


             } catch (IOException e) {
               e.printStackTrace();
             }
      }

   // method to download a file
   public static void download (String source, String destination) {

      URL u;
      InputStream is = null;
      DataInputStream dis;
      FileOutputStream fos = null;
      String s;

      try {

         //  Create the URL.                                   //

         u = new URL(source);

         //   Open an input stream from the url.  //        

         is = u.openStream();         // throws an IOException

         // Convert the InputStream to a buffered DataInputStream.      //
         // Buffering the stream makes the reading faster; the          //
         // readLine() method of the DataInputStream makes the reading  //
         // easier.                                                     //

         dis = new DataInputStream(new BufferedInputStream(is));

         // Read each record of the input stream, and print   //
         // it out.  
        fos = new FileOutputStream( destination );
        final int BUFSIZ = 4096;
        byte inbuf[] = new byte[BUFSIZ];
        int n;

        while ((n = dis.read(inbuf, 0, BUFSIZ)) != -1)
          fos.write(inbuf, 0, n);



      } catch (MalformedURLException mue) {

         System.out.println(" a MalformedURLException happened.");
         mue.printStackTrace();
         System.exit(1);

      } catch (IOException ioe) {

         System.out.println(" IOException happened.");
         ioe.printStackTrace();
         System.exit(1);

      } finally {

         //  Close the InputStream  //

         try {
            is.close();
            fos.close();
            fos = null;
         } catch (IOException ioe) {
            // just going to ignore this one
         }

      } // end of 'finally' clause
   }  // end of put
} // end of cpuInfo class
