docs: @Override
      protected int scale(BigInteger satoshis, int fractionPlaces) {
          /* The algorithm is as follows.  TODO: is there a way to optimize step 4?
             1. Can we use coin denomination w/ no rounding?  If yes, do it.
             2. Else, can we use millicoin denomination w/ no rounding? If yes, do it.
             3. Else, can we use micro denomination w/ no rounding?  If yes, do it.
             4. Otherwise we must round:
               (a) round to nearest coin + decimals
               (b) round to nearest millicoin + decimals
               (c) round to nearest microcoin + decimals
               Subtract each of (a), (b) and (c) from the true value, and choose the
               denomination that gives smallest absolute difference.  It case of tie, use the
               smaller denomination.
          */
          int places;
          int coinOffset = Math.max(SMALLEST_UNIT_EXPONENT - fractionPlaces, 0);
          BigDecimal inCoins = new BigDecimal(satoshis).movePointLeft(coinOffset);
          if (inCoins.remainder(ONE).compareTo(ZERO) == 0) {
              places = COIN_SCALE;
          } else {
              BigDecimal inMillis = inCoins.movePointRight(MILLICOIN_SCALE);
              if (inMillis.remainder(ONE).compareTo(ZERO) == 0) {
                  places = MILLICOIN_SCALE;
              } else {
                  BigDecimal inMicros = inCoins.movePointRight(MICROCOIN_SCALE);
                  if (inMicros.remainder(ONE).compareTo(ZERO) == 0) {
                      places = MICROCOIN_SCALE;
                  } else {
                      // no way to avoid rounding: so what denomination gives smallest error?
                      BigDecimal a = inCoins.subtract(inCoins.setScale(0, HALF_UP)).
                                     movePointRight(coinOffset).abs();
                      BigDecimal b = inMillis.subtract(inMillis.setScale(0, HALF_UP)).
                                     movePointRight(coinOffset - MILLICOIN_SCALE).abs();
                      BigDecimal c = inMicros.subtract(inMicros.setScale(0, HALF_UP)).
                                     movePointRight(coinOffset - MICROCOIN_SCALE).abs();
                      if (a.compareTo(b) < 0)
                          if (a.compareTo(c) < 0) places = COIN_SCALE;
                          else places = MICROCOIN_SCALE;
                      else if (b.compareTo(c) < 0) places = MILLICOIN_SCALE;
                      else places = MICROCOIN_SCALE;
                  }
              }
          }
          prefixUnitsIndicator(numberFormat, places);
          return places;
      }