Skip to content

Commit 0988c69

Browse files
committed
seeking java 1.7 compatibility
1 parent 96ff304 commit 0988c69

File tree

2 files changed

+210
-1
lines changed

2 files changed

+210
-1
lines changed

src/main/kotlin/unsigned/Long.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fun Long.toUint() = Uint(this)
1515
fun Long.toUlong() = Ulong(this)
1616

1717
fun Long.toBigInt(): BigInteger = BigInteger.valueOf(this)
18-
fun Long.toUBigInt(): BigInteger = BigInteger(java.lang.Long.toUnsignedString(this))
18+
fun Long.toUBigInt(): BigInteger = BigInteger(toUnsignedString())
1919

2020
val Long.ub
2121
get() = toUbyte()
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package unsigned
2+
3+
import java.math.BigInteger
4+
5+
6+
fun Long.toUnsignedString(radix: Int = 10): String =
7+
if (this >= 0)
8+
toString(radix)
9+
else
10+
when (radix) {
11+
2 -> toBinaryString()
12+
13+
4 -> toUnsignedString0(2)
14+
15+
8 -> toOctalString()
16+
17+
10 -> {
18+
/*
19+
* We can get the effect of an unsigned division by 10
20+
* on a long value by first shifting right, yielding a
21+
* positive value, and then dividing by 5. This
22+
* allows the last digit and preceding digits to be
23+
* isolated more quickly than by an initial conversion
24+
* to BigInteger.
25+
*/
26+
val quot = this.ushr(1) / 5
27+
val rem = this - quot * 10
28+
quot.toString_() + rem
29+
}
30+
31+
16 -> toHexString()
32+
33+
32 -> toUnsignedString0(5)
34+
35+
else -> toUnsignedBigInteger().toString(radix)
36+
}
37+
38+
fun Long.toString(radix: Int): String {
39+
var i = this
40+
var _radix = radix
41+
if (_radix < Character.MIN_RADIX || _radix > Character.MAX_RADIX)
42+
_radix = 10
43+
if (_radix == 10)
44+
return toString_()
45+
val buf = CharArray(65)
46+
var charPos = 64
47+
val negative = i < 0
48+
49+
if (!negative) {
50+
i = -i
51+
}
52+
53+
while (i <= -_radix) {
54+
buf[charPos--] = digits[(-(i % _radix)).toInt()]
55+
i = i / _radix
56+
}
57+
buf[charPos] = digits[(-i).toInt()]
58+
59+
if (negative) {
60+
buf[--charPos] = '-'
61+
}
62+
63+
return String(buf, charPos, 65 - charPos)
64+
}
65+
66+
fun Long.toString_(): String {
67+
if (this == java.lang.Long.MIN_VALUE)
68+
return "-9223372036854775808"
69+
val size = if (this < 0) stringSize(-this) + 1 else stringSize(this)
70+
val buf = CharArray(size)
71+
getChars(this, size, buf)
72+
return String(buf)
73+
}
74+
75+
internal fun stringSize(x: Long): Int {
76+
var p = 10L
77+
for (i in 1..18) {
78+
if (x < p)
79+
return i
80+
p *= 10
81+
}
82+
return 19
83+
}
84+
85+
internal fun getChars(i: Long, index: Int, buf: CharArray) {
86+
var _i = i
87+
var q: Long
88+
var r: Int
89+
var charPos = index
90+
var sign: Char = 0.toChar()
91+
92+
if (_i < 0) {
93+
sign = '-'
94+
_i = -_i
95+
}
96+
97+
// Get 2 digits/iteration using longs until quotient fits into an int
98+
while (_i > Integer.MAX_VALUE) {
99+
q = _i / 100
100+
// really: r = i - (q * 100);
101+
r = (_i - ((q shl 6) + (q shl 5) + (q shl 2))).toInt()
102+
_i = q
103+
buf[--charPos] = DigitOnes[r]
104+
buf[--charPos] = DigitTens[r]
105+
}
106+
107+
// Get 2 digits/iteration using ints
108+
var q2: Int
109+
var i2 = _i.toInt()
110+
while (i2 >= 65536) {
111+
q2 = i2 / 100
112+
// really: r = i2 - (q * 100);
113+
r = i2 - ((q2 shl 6) + (q2 shl 5) + (q2 shl 2))
114+
i2 = q2
115+
buf[--charPos] = DigitOnes[r]
116+
buf[--charPos] = DigitTens[r]
117+
}
118+
119+
// Fall thru to fast mode for smaller numbers
120+
// assert(i2 <= 65536, i2);
121+
while (true) {
122+
q2 = (i2 * 52429).ushr(16 + 3)
123+
r = i2 - ((q2 shl 3) + (q2 shl 1)) // r = i2-(q2*10) ...
124+
buf[--charPos] = digits[r]
125+
i2 = q2
126+
if (i2 == 0) break
127+
}
128+
if (sign.toInt() != 0)
129+
buf[--charPos] = sign
130+
}
131+
132+
internal val DigitTens by lazy {
133+
charArrayOf(
134+
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
135+
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
136+
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
137+
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
138+
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
139+
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
140+
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
141+
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
142+
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
143+
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9')
144+
}
145+
146+
internal val DigitOnes by lazy {
147+
charArrayOf(
148+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
149+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
150+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
151+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
152+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
153+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
154+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
155+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
156+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
157+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
158+
}
159+
160+
internal val digits by lazy {
161+
charArrayOf(
162+
'0', '1', '2', '3', '4', '5',
163+
'6', '7', '8', '9', 'a', 'b',
164+
'c', 'd', 'e', 'f', 'g', 'h',
165+
'i', 'j', 'k', 'l', 'm', 'n',
166+
'o', 'p', 'q', 'r', 's', 't',
167+
'u', 'v', 'w', 'x', 'y', 'z')
168+
}
169+
170+
fun Long.toBinaryString() = toUnsignedString0(1)
171+
172+
internal fun Long.toUnsignedString0(shift: Int): String {
173+
// assert shift > 0 && shift <=5 : "Illegal shift value";
174+
val mag = java.lang.Long.SIZE - java.lang.Long.numberOfLeadingZeros(this)
175+
val chars = Math.max((mag + (shift - 1)) / shift, 1)
176+
val buf = CharArray(chars)
177+
178+
formatUnsignedLong(shift, buf, 0, chars)
179+
return String(buf)
180+
}
181+
182+
internal fun Long.formatUnsignedLong(shift: Int, buf: CharArray, offset: Int, len: Int): Int {
183+
var _this = this
184+
var charPos = len
185+
val radix = 1 shl shift
186+
val mask = radix - 1
187+
do {
188+
buf[offset + --charPos] = digits[toInt() and mask]
189+
_this = _this ushr shift
190+
} while (_this != 0L && charPos > 0)
191+
192+
return charPos
193+
}
194+
195+
fun Long.toOctalString() = toUnsignedString0(3)
196+
197+
fun Long.toHexString() = toUnsignedString0(4)
198+
199+
private fun Long.toUnsignedBigInteger(): BigInteger {
200+
if (this >= 0L)
201+
return BigInteger.valueOf(this)
202+
else {
203+
val upper = this.ushr(32).toInt()
204+
val lower = this.toInt()
205+
206+
// return (upper << 32) + lower
207+
return BigInteger.valueOf(Integer.toUnsignedLong(upper)).shiftLeft(32).add(BigInteger.valueOf(Integer.toUnsignedLong(lower)))
208+
}
209+
}

0 commit comments

Comments
 (0)