@@ -205,6 +205,73 @@ private fun Long.toUnsignedBigInteger(): BigInteger {
205205 val lower = this .toInt()
206206
207207 // return (upper << 32) + lower
208- return BigInteger .valueOf(Integer .toUnsignedLong(upper )).shiftLeft(32 ).add(BigInteger .valueOf(Integer .toUnsignedLong(lower )))
208+ return BigInteger .valueOf(upper .toUnsignedLong()).shiftLeft(32 ).add(BigInteger .valueOf(lower .toUnsignedLong()))
209209 }
210+ }
211+
212+ @Throws(NumberFormatException ::class )
213+ fun String.parseUnsignedLong (radix : Int = 10): Long {
214+
215+ if (length > 0 ) {
216+ val firstChar = this [0 ]
217+ if (firstChar == ' -' )
218+ throw NumberFormatException (String .format(" Illegal leading minus sign on unsigned string $this ." ))
219+ else {
220+ if (length <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits
221+ radix == 10 && length <= 18 ) // Long.MAX_VALUE in base 10 is 19 digits
222+ return this .toLong(radix)
223+
224+ // No need for range checks on len due to testing above.
225+ val first = substring(0 , length - 1 ).toLong(radix)
226+ val second = Character .digit(this [length - 1 ], radix)
227+ if (second < 0 )
228+ throw NumberFormatException (" Bad digit at end of $this " )
229+ val result = first * radix + second
230+ if (result compareUnsigned first < 0 ) {
231+ /* The maximum unsigned value, (2^64)-1, takes at most one more digit to represent than the maximum
232+ signed value, (2^63)-1. Therefore, parsing (len - 1) digits will be appropriately in-range of the
233+ signed parsing. In other words, if parsing (len -1) digits overflows signed parsing, parsing len
234+ digits will certainly overflow unsigned parsing.
235+
236+ The compareUnsigned check above catches situations where an unsigned overflow occurs incorporating
237+ the contribution of the final digit. */
238+ throw NumberFormatException (String .format(" String value $this exceeds range of unsigned long." ))
239+ }
240+ return result
241+ }
242+ } else throw NumberFormatException (" For input string: $this " )
243+ }
244+
245+ infix fun Long.compareUnsigned (b : Long ) = compare(this + Long .MIN_VALUE , b + Long .MIN_VALUE )
246+
247+ fun compare (a : Long , b : Long ) = if (a < b) - 1 else if (a == b) 0 else 1
248+
249+ infix fun Long.divideUnsigned (divisor : Long ): Long {
250+ if (divisor < 0L ) // signed comparison
251+ // Answer must be 0 or 1 depending on relative magnitude
252+ // of dividend and divisor.
253+ return if (compareUnsigned(divisor) < 0 ) 0L else 1L
254+
255+ if (this > 0 )
256+ // Both inputs non-negative
257+ return this / divisor
258+ else
259+ /*
260+ * For simple code, leveraging BigInteger. Longer and faster
261+ * code written directly in terms of operations on longs is
262+ * possible; see "Hacker's Delight" for divide and remainder
263+ * algorithms.
264+ */
265+ return toUnsignedBigInteger().divide(divisor.toUnsignedBigInteger()).toLong()
266+ }
267+
268+ infix fun Long.remainderUnsigned (divisor : Long ): Long {
269+ if (this > 0 && divisor > 0 ) // signed comparisons
270+ return this % divisor
271+ else
272+ if (compareUnsigned(divisor) < 0 )
273+ // Avoid explicit check for 0 divisor
274+ return this
275+ else
276+ return toUnsignedBigInteger().remainder(divisor.toUnsignedBigInteger()).toLong()
210277}
0 commit comments