spiceJ/real-time/src/main/java/at/borkowski/spicej/rt/RateCalculator.java
public static Result calculate(float rateBytesPerSecond, int minInterval) {
      BigDecimal B_MIN = BigDecimal.ONE;
      BigDecimal B_MAX = BigDecimal.valueOf(MAX_BYTES_PER_TICK);
      BigDecimal I_MIN = BigDecimal.valueOf(minInterval);
      BigDecimal I_MAX = BigDecimal.valueOf(MAX_INTERVAL_NS);
      BigDecimal Id_MAX = BigDecimal.valueOf(Integer.MAX_VALUE);

      BigDecimal ONEG = BigDecimal.valueOf(NS_PER_S);
      BigDecimal TWO = BigDecimal.valueOf(2);
      BigDecimal E = BigDecimal.valueOf(Math.E);

      BigDecimal R = BigDecimal.valueOf(rateBytesPerSecond).divide(ONEG, SCALE, ROUND);
      BigDecimal I = I_MAX;

      BigDecimal B = R.multiply(I);

      BigDecimal ERROR;
      BigDecimal ERROR_MAX = BigDecimal.valueOf(MAX_ERROR);

      BigDecimal R_set = BigDecimal.valueOf(rateBytesPerSecond).divide(ONEG, SCALE, ROUND);
      BigDecimal R_eff;

      // bytes per I_MAX <= 1
      if (B.compareTo(B_MIN) <= 0) {
         B = BigDecimal.ONE;
         I = B.divide(R, SCALE, ROUND);

         BigDecimal Id = BigDecimal.ONE;
         while (true) {
            while (I.compareTo(I_MAX) > 0) {
               I = I.divide(E, SCALE, ROUND);
               Id = Id.multiply(E);
            }

            if (Id.compareTo(Id_MAX) > 0)
               throw new IllegalArgumentException("rate too low (" + rateBytesPerSecond + "): prescaler too high");

            BigDecimal B_int = BigDecimal.valueOf(B.setScale(0, ROUND).intValueExact());
            BigDecimal I_int = BigDecimal.valueOf(I.setScale(0, ROUND).intValueExact());
            BigDecimal Id_int = BigDecimal.valueOf(Id.setScale(0, ROUND).intValueExact());

            R_eff = B_int.divide(I_int, SCALE, ROUND).divide(Id_int, SCALE, ROUND);
            ERROR = R_eff.divide(R_set, SCALE, ROUND).subtract(BigDecimal.ONE).abs();
            if (ERROR.compareTo(ERROR_MAX) < 0)
               break;

            I = I.multiply(E);
            B = B.multiply(E);
         }

         return new Result(B.setScale(0, ROUND).intValueExact(), Id.setScale(0, ROUND).intValueExact(), I.setScale(0, ROUND).intValueExact());
      } else {
         BigDecimal Id = BigDecimal.ONE;

         while (true) {
            while (I.compareTo(I_MAX) > 0) {
               I = I.divide(E, SCALE, ROUND);
               Id = Id.multiply(E);
            }

            while (B.compareTo(B_MAX) > 0) {
               B = B.divide(TWO, SCALE, ROUND);
               I = I.divide(TWO, SCALE, ROUND);
            }

            if (I.compareTo(BigDecimal.ONE) < 0)
               throw new IllegalArgumentException("rate too high (" + rateBytesPerSecond + "): interval too low");

            BigDecimal B_int = BigDecimal.valueOf(B.setScale(0, ROUND).intValueExact());
            BigDecimal I_int = BigDecimal.valueOf(I.setScale(0, ROUND).intValueExact());
            BigDecimal Id_int = BigDecimal.valueOf(Id.setScale(0, ROUND).intValueExact());

            R_eff = B_int.divide(I_int, SCALE, ROUND).divide(Id_int, SCALE, ROUND);
            ERROR = R_eff.divide(R_set, SCALE, ROUND).subtract(BigDecimal.ONE).abs();
            if (ERROR.compareTo(ERROR_MAX) < 0)
               break;

            I = I.multiply(E);
            B = B.multiply(E);
         }

         if (I.compareTo(I_MIN) < 0)
            throw new IllegalArgumentException("rate too high (" + rateBytesPerSecond + "): interval too low");

         return new Result(B.setScale(0, ROUND).intValueExact(), Id.setScale(0, ROUND).intValueExact(), I.setScale(0, ROUND).intValueExact());
      }
   }
public static Result calculate(float rateBytesPerSecond, int minInterval) {
      BigDecimal B_MIN = BigDecimal.ONE;
      BigDecimal B_MAX = BigDecimal.valueOf(MAX_BYTES_PER_TICK);
      BigDecimal I_MIN = BigDecimal.valueOf(minInterval);
      BigDecimal I_MAX = BigDecimal.valueOf(MAX_INTERVAL_NS);
      BigDecimal Id_MAX = BigDecimal.valueOf(Integer.MAX_VALUE);

      BigDecimal ONEG = BigDecimal.valueOf(NS_PER_S);
      BigDecimal TWO = BigDecimal.valueOf(2);
      BigDecimal E = BigDecimal.valueOf(Math.E);

      BigDecimal R = BigDecimal.valueOf(rateBytesPerSecond).divide(ONEG, SCALE, ROUND);
      BigDecimal I = I_MAX;

      BigDecimal B = R.multiply(I);

      BigDecimal ERROR;
      BigDecimal ERROR_MAX = BigDecimal.valueOf(MAX_ERROR);

      BigDecimal R_set = BigDecimal.valueOf(rateBytesPerSecond).divide(ONEG, SCALE, ROUND);
      BigDecimal R_eff;

      // bytes per I_MAX <= 1
      if (B.compareTo(B_MIN) <= 0) {
         B = BigDecimal.ONE;
         I = B.divide(R, SCALE, ROUND);

         BigDecimal Id = BigDecimal.ONE;
         while (true) {
            while (I.compareTo(I_MAX) > 0) {
               I = I.divide(E, SCALE, ROUND);
               Id = Id.multiply(E);
            }

            if (Id.compareTo(Id_MAX) > 0)
               throw new IllegalArgumentException("rate too low (" + rateBytesPerSecond + "): prescaler too high");

            BigDecimal B_int = BigDecimal.valueOf(B.setScale(0, ROUND).intValueExact());
            BigDecimal I_int = BigDecimal.valueOf(I.setScale(0, ROUND).intValueExact());
            BigDecimal Id_int = BigDecimal.valueOf(Id.setScale(0, ROUND).intValueExact());

            R_eff = B_int.divide(I_int, SCALE, ROUND).divide(Id_int, SCALE, ROUND);
            ERROR = R_eff.divide(R_set, SCALE, ROUND).subtract(BigDecimal.ONE).abs();
            if (ERROR.compareTo(ERROR_MAX) < 0)
               break;

            I = I.multiply(E);
            B = B.multiply(E);
         }

         return new Result(B.setScale(0, ROUND).intValueExact(), Id.setScale(0, ROUND).intValueExact(), I.setScale(0, ROUND).intValueExact());
      } else {
         BigDecimal Id = BigDecimal.ONE;

         while (true) {
            while (I.compareTo(I_MAX) > 0) {
               I = I.divide(E, SCALE, ROUND);
               Id = Id.multiply(E);
            }

            while (B.compareTo(B_MAX) > 0) {
               B = B.divide(TWO, SCALE, ROUND);
               I = I.divide(TWO, SCALE, ROUND);
            }

            if (I.compareTo(BigDecimal.ONE) < 0)
               throw new IllegalArgumentException("rate too high (" + rateBytesPerSecond + "): interval too low");

            BigDecimal B_int = BigDecimal.valueOf(B.setScale(0, ROUND).intValueExact());
            BigDecimal I_int = BigDecimal.valueOf(I.setScale(0, ROUND).intValueExact());
            BigDecimal Id_int = BigDecimal.valueOf(Id.setScale(0, ROUND).intValueExact());

            R_eff = B_int.divide(I_int, SCALE, ROUND).divide(Id_int, SCALE, ROUND);
            ERROR = R_eff.divide(R_set, SCALE, ROUND).subtract(BigDecimal.ONE).abs();
            if (ERROR.compareTo(ERROR_MAX) < 0)
               break;

            I = I.multiply(E);
            B = B.multiply(E);
         }

         if (I.compareTo(I_MIN) < 0)
            throw new IllegalArgumentException("rate too high (" + rateBytesPerSecond + "): interval too low");

         return new Result(B.setScale(0, ROUND).intValueExact(), Id.setScale(0, ROUND).intValueExact(), I.setScale(0, ROUND).intValueExact());
      }
   }
Performs a calculation with the given minimal interval. See
{@link RateCalculator} for details.

@param rateBytesPerSecond
The rate in bytes per second to target
@param minInterval
The minimal interval in nanoseconds.
@return the calculation result