Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd24d1c3

Browse files
committed
Introduce code paths for Longs that are *signed* safe doubles.
Since conversions of signed longs to doubles is in fact no moreexpensive than the unsigned longs, we can take shorter paths forvalues that fit in the *signed* safe range.This applies to the conversions to string (including in thejavalib) and to float.It could also apply to signed division and remainder. However,benchmarks suggest that doing so makes it slower. The trouble isthat we then need a signed double-to-long conversion for theresult, and that appears to be slower than performing the 3 signadjustments.
1 parent944be5a commitd24d1c3

File tree

4 files changed

+196
-180
lines changed

4 files changed

+196
-180
lines changed

‎javalib/src/main/scala/java/lang/Long.scala

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -145,36 +145,44 @@ object Long {
145145

146146
// Must be called only with valid radix
147147
privatedeftoStringImpl(i: scala.Long,radix:Int):String= {
148+
importjs.JSNumberOps.enableJSNumberOps
149+
148150
vallo= i.toInt
149151
valhi= (i>>>32).toInt
150152

151153
if (lo>>31== hi) {
152154
// It's a signed int32
153-
importjs.JSNumberOps.enableJSNumberOps
154155
lo.toString(radix)
155-
}elseif (hi<0) {
156-
valneg=-i
157-
"-"+ toUnsignedStringInternalLarge(neg.toInt, (neg>>>32).toInt,radix)
156+
}elseif (((hi^ (hi>>10))&0xffe00000)==0) {// see RuntimeLong.isSignedSafeDouble
157+
// (lo, hi) is small enough to be a Double, so toDouble is exact
158+
i.toDouble.toString(radix)
158159
}else {
159-
toUnsignedStringInternalLarge(lo, hi, radix)
160+
valabs=Math.abs(i)
161+
vals= toUnsignedStringInternalLarge(abs.toInt, (abs>>>32).toInt, radix)
162+
if (hi<0)"-"+ selse s
160163
}
161164
}
162165

163166
// Must be called only with valid radix
164167
privatedeftoUnsignedStringImpl(i: scala.Long,radix:Int):String= {
168+
importjs.JSNumberOps.enableJSNumberOps
169+
165170
vallo= i.toInt
166171
valhi= (i>>>32).toInt
167172

168173
if (hi==0) {
169174
// It's an unsigned int32
170-
importjs.JSNumberOps.enableJSNumberOps
171175
Integer.toUnsignedDouble(lo).toString(radix)
176+
}elseif ((hi&0xffe00000)==0) {// see RuntimeLong.isUnsignedSafeDouble
177+
// (lo, hi) is small enough to be a Double, so toDouble is exact
178+
i.toDouble.toString(radix)
172179
}else {
173180
toUnsignedStringInternalLarge(lo, hi, radix)
174181
}
175182
}
176183

177-
// Must be called only with valid radix and with (lo, hi) >= 2^30
184+
// Must be called only with valid radix and with (lo, hi) >= 2^53
185+
@inline// inlined twice: once in toStringImpl and once in toUnsignedStringImpl
178186
privatedeftoUnsignedStringInternalLarge(lo:Int,hi:Int,radix:Int):String= {
179187
importjs.JSNumberOps.enableJSNumberOps
180188
importjs.JSStringOps.enableJSStringOps
@@ -185,41 +193,36 @@ object Long {
185193
}
186194

187195
valTwoPow32= (1L<<32).toDouble
188-
valapproxNum=
189-
Integer.toUnsignedDouble(hi)*TwoPow32+Integer.toUnsignedDouble(lo)
190196

191-
if ((hi&0xffe00000)==0) {// see RuntimeLong.isUnsignedSafeDouble
192-
// (lo, hi) is small enough to be a Double, so approxNum is exact
193-
approxNum.toString(radix)
194-
}else {
195-
/* See RuntimeLong.toUnsignedString for a proof. Although that proof is
196-
* done in terms of a fixed divisor of 10^9, it generalizes to any
197-
* divisor that statisfies 2^12 < divisor <= 2^30 and
198-
* ULong.MaxValue / divisor < 2^53, which is true for `radixPowLength`.
199-
*/
197+
/* See RuntimeLong.toUnsignedString for a proof. Although that proof is
198+
* done in terms of a fixed divisor of 10^9, it generalizes to any
199+
* divisor that statisfies 2^12 < divisor <= 2^30 and
200+
* ULong.MaxValue / divisor < 2^53, which is true for `radixPowLength`.
201+
*/
200202

201-
valradixInfo=StringRadixInfos(radix)
202-
valdivisor= radixInfo.radixPowLength
203-
valdivisorInv= radixInfo.radixPowLengthInverse
204-
valpaddingZeros= radixInfo.paddingZeros
205-
206-
// initial approximation of the quotient and remainder
207-
varapproxQuot=Math.floor(approxNum* divisorInv)
208-
varapproxRem= lo- divisor* unsignedSafeDoubleLo(approxQuot)
209-
210-
// correct the approximations
211-
if (approxRem<0) {
212-
approxQuot-=1.0
213-
approxRem+= divisor
214-
}elseif (approxRem>= divisor) {
215-
approxQuot+=1.0
216-
approxRem-= divisor
217-
}
203+
valradixInfo=StringRadixInfos(radix)
204+
valdivisor= radixInfo.radixPowLength
205+
valdivisorInv= radixInfo.radixPowLengthInverse
206+
valpaddingZeros= radixInfo.paddingZeros
218207

219-
// build the result string
220-
valremStr= approxRem.toString(radix)
221-
approxQuot.toString(radix)+ paddingZeros.jsSubstring(remStr.length)+ remStr
208+
// initial approximation of the quotient and remainder
209+
valapproxNum=
210+
Integer.toUnsignedDouble(hi)*TwoPow32+Integer.toUnsignedDouble(lo)
211+
varapproxQuot=Math.floor(approxNum* divisorInv)
212+
varapproxRem= lo- divisor* unsignedSafeDoubleLo(approxQuot)
213+
214+
// correct the approximations
215+
if (approxRem<0) {
216+
approxQuot-=1.0
217+
approxRem+= divisor
218+
}elseif (approxRem>= divisor) {
219+
approxQuot+=1.0
220+
approxRem-= divisor
222221
}
222+
223+
// build the result string
224+
valremStr= approxRem.toString(radix)
225+
approxQuot.toString(radix)+ paddingZeros.jsSubstring(remStr.length)+ remStr
223226
}
224227

225228
defparseLong(s:String,radix:Int): scala.Long= {

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp