docs: @SuppressWarnings("unchecked")
      protected static DataSet<?> load(InputStream inRaw, boolean forceAsStandard, DataStore store) throws IOException
      {
          DataInputStream in = new DataInputStream(inRaw);
          
          byte[] magic_number = new byte[MAGIC_NUMBER.length];
          in.readFully(magic_number);
          String magic = new String(magic_number, "US-ASCII");
          
          if(!magic.startsWith("JSAT_"))
              throw new RuntimeException("data does not contain magic number");
          
          DatasetTypeMarker marker = DatasetTypeMarker.values()[in.readByte()];
          FloatStorageMethod fpStore = FloatStorageMethod.values()[in.readByte()];
          
          int numNumeric = in.readInt();
          int numCat = in.readInt();
          int N = in.readInt();
          
          if(forceAsStandard)
              marker = DatasetTypeMarker.STANDARD;
          
          if(marker == DatasetTypeMarker.CLASSIFICATION)
              numCat--;
          else if(marker == DatasetTypeMarker.REGRESSION)
              numNumeric--;
          
          CategoricalData[] categories = new CategoricalData[numCat];
          CategoricalData predicting = null;//may not be used
          
          for(int i = 0; i < categories.length; i++)
          {
              //first, whats the name of the i'th category
              String name = readString(in);
              int k = in.readInt();//output the number of categories 
              
              categories[i] = new CategoricalData(k);
              categories[i].setCategoryName(name);
              
              for(int j = 0; j < k; j++)//the option names
                  categories[i].setOptionName(readString(in), j);
          }
          
          if(marker == DatasetTypeMarker.CLASSIFICATION)
          {
              //first, whats the name of the i'th category
              String name = readString(in);
              int k = in.readInt();//output the number of categories 
              
              predicting = new CategoricalData(k);
              predicting.setCategoryName(name);
              
              for(int j = 0; j < k; j++)//the option names
                  predicting.setOptionName(readString(in), j);
          }
          
          //used for both numeric and categorical target storage
          DoubleList targets = new DoubleList();
          DoubleList weights = new DoubleList();
          store.setCategoricalDataInfo(categories);
          store.setNumNumeric(numNumeric);
          
          //read in all the data points
          if(N < 0)
              N = Integer.MAX_VALUE;
          try
          {
              for(int i = 0; i < N; i++)
              {
              
                  double weight = fpStore.readFP(in);//in.readDouble();
                  int[] catVals = new int[numCat];
                  double target = 0;
  
                  for(int j = 0; j < catVals.length; j++)
                      catVals[j] = in.readInt();
  
                  if(marker ==  DatasetTypeMarker.CLASSIFICATION)
                  {
                      //int can be stored losselessly in a double, so this is safe
                      target = in.readInt();
                  }
  
                  boolean sparse = in.readBoolean();
                  Vec numericVals;
  
  
                  if(sparse)
                  {
                      int nnz = in.readInt();
                      if(marker == DatasetTypeMarker.REGRESSION)
                          nnz--;//don't count the target value
                      int[] indicies = new int[nnz];
                      double[] values = new double[nnz];
                      for(int j = 0; j < nnz; j++)
                      {
                          indicies[j] = in.readInt();
                          values[j] = fpStore.readFP(in);
                      }
                      numericVals = new SparseVector(indicies, values, numNumeric, nnz);
                  }
                  else
                  {
                      numericVals = new DenseVector(numNumeric);
                      for(int j = 0; j < numNumeric; j++)
                          numericVals.set(j, fpStore.readFP(in));
                  }
  
                  //get the target value 
                  if(marker == DatasetTypeMarker.REGRESSION)
                  {
                      /* 
                       * if dense, we only need to just add the extra double. If 
                       * sparse, we do the index and then the double. 
                       */
                      if (numericVals.isSparse())
                          in.readInt();//don't care, its the last index value - so its the target
  
                      target = fpStore.readFP(in);
                  }
  
                  DataPoint dp = new DataPoint(numericVals, catVals, categories);
  		weights.add(weight);
                  store.addDataPoint(dp);
  
                  switch(marker)
                  {
                      case CLASSIFICATION:
                      case REGRESSION:
                          targets.add(target);
                      default:
                          break;
                  }
              
              }
          }
          catch (EOFException eo)
          {
              //No problem
          }
          
          in.close();
          
  	DataSet toRet;
          switch(marker)
          {
              case CLASSIFICATION:
                  IntList targets_i = IntList.view(targets.stream().mapToInt(Double::intValue).toArray());
                  toRet =  new ClassificationDataSet(store, targets_i, predicting);
  		break;
              case REGRESSION:
                  toRet =  new RegressionDataSet(store, targets);
  		break;
              default:
                  toRet =  new SimpleDataSet(store);
          }
  	for(int i = 0; i < weights.size(); i++)
  	    toRet.setWeight(i, weights.getD(i));
  	return toRet;
      }