Rev 97 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (c) 2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package uk.me.parabola.splitter;
/**
* Conversion utility methods
*
* @author Chris Miller
*/
public class Convert
{
/**
* Converts an int into a char[]. The supplied char[] must be at least 11 characters long.
* @param i the int to convert to a char[].
* @param buf the char[] to write the integer into.
* @return the number of characters that were written into the character array.
*/
public static int intToString
(int i,
char[] buf
) {
return intToString
(i, buf,
0);
}
public static int intToString
(int i,
char[] buf,
int startIndex
) {
if (i ==
Integer.
MIN_VALUE) {
System.
arraycopy(MIN_VALUE,
0, buf, startIndex, MIN_VALUE.
length);
return MIN_VALUE.
length;
}
int size =
(i
< 0) ? stringSize
(-i
) +
1 : stringSize
(i
);
getChars
(i, startIndex + size, buf
);
return size
;
}
private final static char[] MIN_VALUE =
new char[] {'-',
'2',
'1',
'4',
'7',
'4',
'8',
'3',
'6',
'4',
'8'};
final static int[] sizeTable =
{9,
99,
999,
9999,
99999,
999999,
9999999,
99999999,
999999999,
Integer.
MAX_VALUE};
final static char[] DigitTens =
{
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'0',
'1',
'1',
'1',
'1',
'1',
'1',
'1',
'1',
'1',
'1',
'2',
'2',
'2',
'2',
'2',
'2',
'2',
'2',
'2',
'2',
'3',
'3',
'3',
'3',
'3',
'3',
'3',
'3',
'3',
'3',
'4',
'4',
'4',
'4',
'4',
'4',
'4',
'4',
'4',
'4',
'5',
'5',
'5',
'5',
'5',
'5',
'5',
'5',
'5',
'5',
'6',
'6',
'6',
'6',
'6',
'6',
'6',
'6',
'6',
'6',
'7',
'7',
'7',
'7',
'7',
'7',
'7',
'7',
'7',
'7',
'8',
'8',
'8',
'8',
'8',
'8',
'8',
'8',
'8',
'8',
'9',
'9',
'9',
'9',
'9',
'9',
'9',
'9',
'9',
'9',
};
final static char[] DigitOnes =
{
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
};
// Requires positive x
static int stringSize
(int x
) {
for (int i =
0; ; i++
)
if (x
<= sizeTable
[i
])
return i +
1;
}
/**
* Places characters representing the integer i into the
* character array buf. The characters are placed into
* the buffer backwards starting with the least significant
* digit at the specified index (exclusive), and working
* backwards from there.
*
* Will fail if i == Integer.MIN_VALUE
*/
static void getChars
(int i,
int charPos,
char[] buf
) {
int q, r
;
char sign =
0;
if (i
< 0) {
sign =
'-';
i = -i
;
}
// Generate two digits per iteration
while (i
>=
65536) {
q = i /
100;
// really: r = i - (q * 100);
r = i -
((q
<< 6) +
(q
<< 5) +
(q
<< 2));
i = q
;
buf
[--charPos
] = DigitOnes
[r
];
buf
[--charPos
] = DigitTens
[r
];
}
// Fall through to fast mode for smaller numbers
for (; ;) {
q =
(i
* 52429) >>> (16 +
3);
r = i -
((q
<< 3) +
(q
<< 1));
// r = i-(q*10) ...
buf
[--charPos
] =
(char) ('0' + r
);
i = q
;
if (i ==
0) break;
}
if (sign
!=
0) {
buf
[--charPos
] = sign
;
}
}
private static final double[] PowersOfTen =
new double[] {
10d,
100d,
1000d,
10000d,
100000d,
1000000d,
10000000d,
100000000d,
1000000000d,
10000000000d,
100000000000d,
1000000000000d,
10000000000000d,
100000000000000d,
1000000000000000d,
10000000000000000d,
100000000000000000d,
1000000000000000000d,
10000000000000000000d,
};
/**
* Parses a string into a double. This code is optimised for performance
* when parsing typical doubles encountered in .osm files.
*
* @param cs the characters to parse into a double
* @return the double value represented by the string.
* @throws NumberFormatException if the value failed to parse.
*/
public static double parseDouble
(String cs
) throws NumberFormatException
{
int end =
Math.
min(cs.
length(),
19); // No point trying to handle more digits than a double precision number can deal with
int i =
0;
char c = cs.
charAt(i
);
boolean isNegative =
(c ==
'-');
if ((isNegative ||
(c ==
'+')) && (++i
< end
))
c = cs.
charAt(i
);
long decimal =
0;
int decimalPoint = -
1;
while (true) {
int digit = c -
'0';
if ((digit
>=
0) && (digit
< 10)) {
long tmp = decimal
* 10 + digit
;
if (tmp
< decimal
)
throw new NumberFormatException("Overflow! Too many digits in " + cs
);
decimal = tmp
;
} else if ((c ==
'.') && (decimalPoint
< 0))
decimalPoint = i
;
else {
// We're out of our depth, let the JDK have a go. This is *much* slower
return Double.
parseDouble(cs
);
}
if (++i
>= end
)
break;
c = cs.
charAt(i
);
}
if (isNegative
)
decimal = -decimal
;
if (decimalPoint
> 0)
return decimal / PowersOfTen
[i - decimalPoint -
2];
else
return decimal
;
}
}