25package umontreal.ssj.util;
27import java.text.NumberFormat;
28import java.text.DecimalFormat;
29import java.text.DecimalFormatSymbols;
30import java.util.Locale;
31import java.util.Formatter;
46 private static NumberFormat nf = NumberFormat.getInstance(Locale.US);
47 private static DecimalFormatSymbols dfs =
new DecimalFormatSymbols(Locale.US);
48 private static final int NDEC = 50;
49 private static DecimalFormat[] dfe =
new DecimalFormat[NDEC + 1];
50 private static DecimalFormat[] dfg =
new DecimalFormat[NDEC + 1];
51 private StringBuffer sb;
79 public static final String
NEWLINE = System.getProperty(
"line.separator");
84 public static final String
LINE_SEPARATOR = System.getProperty(
"line.separator");
94 sb =
new StringBuffer();
103 sb =
new StringBuffer(length);
112 sb =
new StringBuffer(str);
175 sb.
append(
f(fieldwidth, precision, x));
275 return sb.toString();
285 public static String
s(String str) {
305 public static String
s(
int fieldwidth, String str) {
307 return s(fieldwidth,
"null");
309 int fw = Math.abs(fieldwidth);
310 if (str.length() < fw) {
312 StringBuffer buf =
new StringBuffer();
313 int sl = str.length();
314 for (
int i = 0; i < fw - sl; i++)
317 return fieldwidth >= 0 ? buf.toString() + str : str + buf.toString();
332 public static String
d(
long x) {
343 public static String
d(
int fieldwidth,
long x) {
344 return d(fieldwidth, 1, x);
359 public static String
d(
int fieldwidth,
int precision,
long x) {
361 throw new IllegalArgumentException(
"precision must " +
"not be negative.");
362 if (precision == 0 && x == 0)
363 return s(fieldwidth,
"");
365 nf.setGroupingUsed(
false);
366 nf.setMinimumIntegerDigits(precision);
367 nf.setMaximumFractionDigits(0);
368 return s(fieldwidth, nf.format(x));
390 public static String
format(
int fieldwidth,
long x) {
391 return d(fieldwidth, 1, x);
414 public static String
formatBase(
int fieldwidth,
int b,
long x) {
417 throw new IllegalArgumentException(
"base must be between 2 and 10.");
428 StringBuffer sb =
new StringBuffer();
435 return s(fieldwidth, sb.toString());
452 public static String
E(
double x) {
463 public static String
E(
int fieldwidth,
double x) {
464 return E(fieldwidth, 6, x);
480 public static String
E(
int fieldwidth,
int precision,
double x) {
482 throw new IllegalArgumentException(
"precision must " +
"not be negative.");
484 return s(fieldwidth,
"NaN");
485 if (Double.isInfinite(x))
486 return s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
489 if (precision >= dfe.length || dfe[precision] ==
null) {
491 StringBuffer pattern =
new StringBuffer(
"0.");
492 for (
int i = 0; i < precision; i++)
494 pattern.append(
"E00");
495 df =
new DecimalFormat(pattern.toString(), dfs);
496 df.setGroupingUsed(
false);
497 if (precision < dfe.length)
501 String res = df.format(x);
504 int exppos = res.indexOf(
'E');
505 if (exppos != -1 && res.charAt(exppos + 1) !=
'-')
506 res = res.substring(0, exppos + 1) +
"+" + res.substring(exppos + 1);
507 return s(fieldwidth, res);
516 public static String
e(
double x) {
527 public static String
e(
int fieldwidth,
double x) {
528 return e(fieldwidth, 6, x);
540 public static String
e(
int fieldwidth,
int precision,
double x) {
541 String res =
E(fieldwidth, precision, x);
542 int exppos = res.indexOf(
'E');
543 return exppos == -1 ? res : res.substring(0, exppos) +
'e' + res.substring(exppos + 1);
552 public static String
f(
double x) {
563 public static String
f(
int fieldwidth,
double x) {
564 return f(fieldwidth, 6, x);
580 public static String
f(
int fieldwidth,
int precision,
double x) {
582 throw new IllegalArgumentException(
"precision must " +
"not be negative.");
584 return s(fieldwidth,
"NaN");
585 if (Double.isInfinite(x))
586 return s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
588 nf.setGroupingUsed(
false);
589 nf.setMinimumIntegerDigits(1);
590 nf.setMinimumFractionDigits(precision);
591 nf.setMaximumFractionDigits(precision);
592 return s(fieldwidth, nf.format(x));
601 public static String
G(
double x) {
612 public static String
G(
int fieldwidth,
double x) {
613 return G(fieldwidth, 6, x);
630 public static String
G(
int fieldwidth,
int precision,
double x) {
632 throw new IllegalArgumentException(
"precision must " +
"not be negative.");
637 return s(fieldwidth,
"NaN");
638 if (Double.isInfinite(x))
639 return s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
645 if (precision >= dfg.length || dfg[precision] ==
null) {
646 StringBuffer pattern =
new StringBuffer(
"0.");
647 for (
int i = 0; i < (precision - 1); i++)
649 pattern.append(
"E00");
650 df =
new DecimalFormat(pattern.toString(), dfs);
651 df.setGroupingUsed(
false);
652 if (precision < dfg.length)
656 String res = df.format(x);
658 int exppos = res.indexOf(
'E');
661 int expval = Integer.parseInt(res.substring(exppos + 1));
662 if (expval < -4 || expval >= precision) {
664 if (res.charAt(exppos + 1) !=
'-')
665 return s(fieldwidth, res.substring(0, exppos + 1) +
"+" + res.substring(exppos + 1));
667 return s(fieldwidth, res);
671 nf.setGroupingUsed(
false);
672 nf.setMinimumIntegerDigits(1);
673 nf.setMinimumFractionDigits(0);
683 nf.setMaximumFractionDigits(precision - expval - 1);
685 return s(fieldwidth, res);
694 public static String
g(
double x) {
705 public static String
g(
int fieldwidth,
double x) {
706 return g(fieldwidth, 6, x);
717 public static String
g(
int fieldwidth,
int precision,
double x) {
718 String res =
G(fieldwidth, precision, x);
719 int exppos = res.indexOf(
'E');
720 return exppos == -1 ? res : res.substring(0, exppos) +
'e' + res.substring(exppos + 1);
740 public static String
format(
int fieldwidth,
int accuracy,
int precision,
double x) {
742 return s(fieldwidth,
"NaN");
743 if (Double.isInfinite(x))
744 return s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
746 if (canUseDecimalNotation(fieldwidth, accuracy, precision, x))
747 return f(fieldwidth, accuracy, x);
750 String S =
E(fieldwidth, precision - 1, x);
751 return processExp(S);
755 private static boolean canUseDecimalNotation(
int fieldwidth,
int accuracy,
int precision,
double x) {
766 EntierSign = PosEntier = (int) Math.floor(Math.log10(Math.abs(x)) + 1);
772 return x == 0.0 || (((EntierSign + accuracy) >= precision) && (fieldwidth >= (PosEntier + accuracy + Neg + 1)));
775 private static int getMinAccuracy(
double x) {
776 if (Math.abs(x) >= 1 || x == 0)
779 return -(int) Math.floor(Math.log10(Math.abs(x)));
782 private static String processExp(String
s) {
783 int p =
s.indexOf(
"E+0");
785 p =
s.indexOf(
"E-0");
789 s =
" " +
s.substring(0, p + 2) +
s.substring(p + 3);
793 s =
" " +
s.substring(0, p) +
s.substring(p + 1);
808 public static String
format(Locale locale,
int fieldwidth,
int accuracy,
int precision,
double x) {
809 Formatter fmt =
new Formatter(locale);
811 return fmt.format(
"%" + fieldwidth +
"s",
"NaN").toString();
812 if (Double.isInfinite(x))
813 return fmt.format(
"%" + fieldwidth +
"s", (x < 0 ?
"-" :
"") +
"Infinite").toString();
815 if (canUseDecimalNotation(fieldwidth, accuracy, precision, x))
816 return fmt.format(
"%" + fieldwidth +
"." + accuracy +
"f", x).toString();
819 String S = fmt.format(
"%" + fieldwidth +
"." + (precision - 1) +
"E", x).toString();
820 return processExp(S);
838 public static String
formatBase(
int fieldwidth,
int accuracy,
int b,
double x) {
840 return s(fieldwidth,
"NaN");
841 if (Double.isInfinite(x))
842 return s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
843 if (0. == x || -0. == x)
844 return s(fieldwidth,
"0");
846 throw new UnsupportedOperationException(
" |x| >= 2^63");
851 return s(fieldwidth, mant);
860 x += 0.5 * Math.pow(b, -accuracy - 1);
862 x -= 0.5 * Math.pow(b, -accuracy - 1);
867 StringBuffer frac =
new StringBuffer(
".");
870 for (j = 0; j < accuracy; ++j) {
879 StringBuffer number =
new StringBuffer(mant);
883 j = number.length() - 1;
884 while (j > 0 && (number.charAt(j) ==
'0' || number.charAt(j) ==
' ')) {
885 number.deleteCharAt(j);
889 return s(fieldwidth, number.toString());
893 public char charAt(
int index) {
894 return sb.charAt(index);
897 public int length() {
901 public CharSequence subSequence(
int start,
int end) {
902 return sb.subSequence(start, end);
906 public Appendable
append(CharSequence csq) {
910 public Appendable
append(CharSequence csq,
int start,
int end) {
911 return sb.
append(csq, start, end);
946 public static void formatWithError(
int fieldwidth,
int fieldwidtherr,
int accuracy,
int precision,
double x,
947 double error, String[] res) {
949 throw new IllegalArgumentException(
"The given res array must contain two elements");
950 if (Double.isNaN(x)) {
951 res[0] =
s(fieldwidth,
"NaN");
952 res[1] =
s(fieldwidtherr,
"");
955 if (Double.isInfinite(x)) {
956 res[0] =
s(fieldwidth, (x < 0 ?
"-" :
"") +
"Infinite");
957 res[1] =
s(fieldwidtherr,
"");
963 if (canUseDecimalNotation(fieldwidth, accuracy, precision, x)) {
964 res[0] =
f(fieldwidth, accuracy, x);
965 res[1] =
f(fieldwidtherr, accuracy, error);
969 res[0] = processExp(
E(fieldwidth, precision - 1, x));
970 int xExp = x == 0 ? 0 : (int) Math.floor(Math.log10(Math.abs(x)));
971 int errorExp = error == 0 ? 0 : (int) Math.floor(Math.log10(Math.abs(error)));
972 int errorPrecision = precision - 1 - (xExp - errorExp);
973 if (errorPrecision < 0)
975 res[1] = processExp(
E(fieldwidtherr, errorPrecision, error));
996 public static void formatWithError(
int fieldwidth,
int fieldwidtherr,
int precision,
double x,
double error,
998 int accuracy = getMinAccuracy(error);
999 if (!canUseDecimalNotation(fieldwidth, accuracy, precision, x)) {
1000 int posEntier = (int) Math.floor(Math.log(Math.abs(x)) / Math.log(10) + 1);
1003 int newAccuracy = precision - posEntier;
1004 if (canUseDecimalNotation(fieldwidth, newAccuracy, precision, x))
1005 accuracy = newAccuracy;
1007 formatWithError(fieldwidth, fieldwidtherr, accuracy, precision, x, error, res);
1026 public static void formatWithError(Locale locale,
int fieldwidth,
int fieldwidtherr,
int accuracy,
int precision,
1027 double x,
double error, String[] res) {
1028 if (res.length != 2)
1029 throw new IllegalArgumentException(
"The given res array must contain two elements");
1030 Formatter fmt =
new Formatter(locale);
1031 Formatter fmtErr =
new Formatter(locale);
1032 if (Double.isNaN(x)) {
1033 res[0] = fmt.format(
"%" + fieldwidth +
"s",
"NaN").toString();
1034 res[1] = fmtErr.format(
"%" + fieldwidtherr +
"s",
"").toString();
1037 if (Double.isInfinite(x)) {
1038 res[0] = fmt.format(
"%" + fieldwidth +
"s", (x < 0 ?
"-" :
"") +
"Infinite").toString();
1039 res[1] = fmtErr.format(
"%" + fieldwidtherr +
"s",
"").toString();
1045 if (canUseDecimalNotation(fieldwidth, accuracy, precision, x)) {
1046 res[0] = fmt.format(
"%" + fieldwidth +
"." + accuracy +
"f", x).toString();
1047 res[1] = fmtErr.format(
"%" + fieldwidtherr +
"." + accuracy +
"f", error).toString();
1051 res[0] = processExp(fmt.format(
"%" + fieldwidth +
"." + (precision - 1) +
"E", x).toString());
1052 int xExp = x == 0 ? 0 : (int) Math.floor(Math.log10(Math.abs(x)));
1053 int errorExp = error == 0 ? 0 : (int) Math.floor(Math.log10(Math.abs(error)));
1054 int errorPrecision = precision - 1 - (xExp - errorExp);
1055 if (errorPrecision < 0)
1057 res[1] = processExp(fmtErr.format(
"%" + fieldwidtherr +
"." + errorPrecision +
"E", error).toString());
1075 public static void formatWithError(Locale locale,
int fieldwidth,
int fieldwidtherr,
int precision,
double x,
1076 double error, String[] res) {
1077 int accuracy = getMinAccuracy(error);
1078 if (!canUseDecimalNotation(fieldwidth, accuracy, precision, x)) {
1079 int posEntier = (int) Math.floor(Math.log(Math.abs(x)) / Math.log(10) + 1);
1082 int newAccuracy = precision - posEntier;
1083 if (canUseDecimalNotation(fieldwidth, newAccuracy, precision, x))
1084 accuracy = newAccuracy;
1086 formatWithError(locale, fieldwidth, fieldwidtherr, accuracy, precision, x, error, res);
This class provides various constants and methods to compute numerical quantities such as factorials,...
static final double TWOEXP[]
Contains the precomputed positive powers of 2.