We have first/0x1p57 - 1 < JAVA{first>>>57} && JAVA{first>>>57} <= first/0x1p57. Here JAVA{.} stands for Java expression with all its truncations and wrappings. Expressions without JAVA{.}are exact mathematical expressions.
JAVA{first>>>57} <= first/0x1p57 < 1p64/1p57 = 1p7, radix <= Character.MAX_RADIX = 36, hence JAVA{(int)(first>>>57)} = JAVA{first>>>57}. guard = JAVA{radix * (int)(first>>>57)} = radix*JAVA{first>>>57}. radix*(first/0x1p57 - 1) < guard && guard <= radix*first/0x1p57 . radix*first/0x1p57 - Character.MAX_RADIX < guard && guard <= radix*first/0x1p57 . This means guard*0xp57 <= first*radix && first*radix < (guard + Character.MAX_RADIX)*0x1p57 guard*0xp57 <= first*radix + second && first*radix + second < (guard + Character.MAX_RADIX)*0x1p57 + Character.MAX_RADIX . Now we shall split by "guard". When guard >= 128 = 1p7, we have first*first + second >= 1p7 * 1p57 = 1p64 hence overflow always occur in this. When guard < 128 - Character,MAX_RADIX, we have guard + Character.MAX_RADIX <= 127 first*radix + second < 127*0x1p57 + 36 < 0x1p64 , hence overflow doesn't occur in this. When 128 - Character.MAX_RADIX <= guard && guard < 128 , (128 - Character.MAX_RADIX)*0xp57 <= first*radix + second && first*radix + second < (127 + Character.MAX_RADIX)*0x1p57 + Character.MAX_RADIX. 0x1p63 < (128 - 36)*0xp57 <= first*radix + second && first*radix + second < (128 + 36)*1p57 + 36 < 0x1p64 + 0x1p63 . Hence JAVA{first*radix + second} = (first*radix + second - 0x1p64) JAVA{result >= 0} = JAVA{first*radix + second >= 0} = (first*radix + second >= 0x1p64). Hence overflow is detected correctly in this case too. On Tue, Dec 24, 2013 at 4:58 AM, Brian Burkhalter < brian.burkhal...@oracle.com> wrote: > It looks like this could be rearranged to > > long result = first * radix + second; > int guard = radix * (int) (first >>> 57); > if (guard >= 128 || (result >= 0 && guard >= 128 - Character.MAX_RADIX)) { > … > > provided reasonable comments were added. I understand the first part of > this conditional, guard >= 128, but the second part eludes me. Would you > please explain this part. > > BTW this works for the test case in question, of course. > > On Dec 21, 2013, at 2:04 AM, Dmitry Nadezhin wrote: > > > I can weaken the question: > > Is there a reason to prefer extra int multiplication to the cache ? > > > > long result = first * radix + second; > > final int GUARD_BIT = 7; > > int guard = radix * (int) (first >>> (Long.SIZE - GUARD_BIT)); > > if (guard >= (1 << GUARD_BIT) - Character.MAX_RADIX > > && (guard >= (1 << GUARD_BIT) || result >= 0)) { > > . . . > >