public SerFunkSVDModel(
      ImmutableMatrix umat,
      ImmutableMatrix imat,
      IdIndexMapping uidx,
      IdIndexMapping iidx,
      List<FeatureInfo> features) {
    super(umat, imat, uidx, iidx);

    featureInfo = ImmutableList.copyOf(features);

    double[] means = new double[featureCount];
    for (int f = featureCount - 1; f >= 0; f--) {
      means[f] = featureInfo.get(f).getUserAverage();
    }
    averageUser = ImmutableVector.wrap(means);
  }
 static ImmutableVector makeValues(PreferenceDomain domain) {
   if (!domain.hasPrecision()) {
     throw new IllegalArgumentException("domain is not discrete");
   }
   final double min = domain.getMinimum();
   final double max = domain.getMaximum();
   final double prec = domain.getPrecision();
   final double nv = (max - min) / prec;
   int n = (int) nv;
   if (Math.abs(nv - n) > 1.0e-6) {
     n += 1; // one more to cover everything...
   }
   if (n == 0) {
     throw new IllegalArgumentException("range has no elements");
   }
   double[] values = new double[n + 1];
   for (int i = 0; i <= n; i++) {
     values[i] = min + (prec * i);
   }
   return ImmutableVector.wrap(values);
 }