@@ -10,6 +10,7 @@ import java.math.BigInteger
10
10
11
11
class FactorialAdvanced {
12
12
13
+ // precomputed factorials
13
14
private val factorials = longArrayOf(
14
15
1L ,
15
16
1L ,
@@ -43,37 +44,37 @@ class FactorialAdvanced {
43
44
return BigInteger .valueOf(factorials[n])
44
45
}
45
46
46
- // Pre -allocate space for our list of intermediate BigIntegers.
47
+ // pre -allocate space for our list of intermediate BigIntegers.
47
48
val approxSize = divide(n * log2Celling(n), Long .SIZE_BITS )
48
49
val bigNumbers = ArrayList <BigInteger >(approxSize)
49
50
50
- // Start from the pre-computed maximum long factorial.
51
+ // start from the pre-computed maximum long factorial.
51
52
val startingNumber = factorials.size
52
53
var number = factorials[startingNumber - 1 ]
53
- // Strip off 2s from this value.
54
+ // strip off 2s from this value.
54
55
var shift = number.countTrailingZeroBits()
55
56
number = number shr shift
56
57
57
- // Use floor(log2(num)) + 1 to prevent overflow of multiplication.
58
+ // use floor(log2(num)) + 1 to prevent overflow of multiplication.
58
59
var numberBits = log2Floor(number) + 1
59
60
var bits = log2Floor(startingNumber.toLong()) + 1
60
- // Check for the next power of two boundary, to save us a CLZ operation.
61
+ // check for the next power of two boundary, to save us a CLZ operation.
61
62
var nextPowerOfTwo = 1 shl bits - 1
62
63
63
- // Iteratively multiply the longs as big as they can go.
64
+ // iteratively multiply the longs as big as they can go.
64
65
for (num in startingNumber.. n) {
65
- // Check to see if the floor(log2(num)) + 1 has changed.
66
+ // check to see if the floor(log2(num)) + 1 has changed.
66
67
if ((num and nextPowerOfTwo) != 0 ) {
67
68
nextPowerOfTwo = nextPowerOfTwo shl 1
68
69
bits++
69
70
}
70
- // Get rid of the 2s in num.
71
+ // get rid of the 2s in num.
71
72
val tz = num.toLong().countTrailingZeroBits()
72
73
val normalizedNum = (num shr tz).toLong()
73
74
shift + = tz
74
- // Adjust floor(log2(num)) + 1.
75
+ // adjust floor(log2(num)) + 1.
75
76
val normalizedBits = bits - tz
76
- // If it won't fit in a long, then we store off the intermediate product.
77
+ // if it won't fit in a long, then we store off the intermediate product.
77
78
if (normalizedBits + numberBits >= Long .SIZE_BITS ) {
78
79
bigNumbers.add(BigInteger .valueOf(number))
79
80
number = 1
@@ -82,11 +83,11 @@ class FactorialAdvanced {
82
83
number * = normalizedNum
83
84
numberBits = log2Floor(number) + 1
84
85
}
85
- // Check for leftovers.
86
+ // check for leftovers.
86
87
if (number > 1 ) {
87
88
bigNumbers.add(BigInteger .valueOf(number))
88
89
}
89
- // Efficiently multiply all the intermediate products together.
90
+ // efficiently multiply all the intermediate products together.
90
91
return listNumbers(bigNumbers).shiftLeft(shift)
91
92
}
92
93
@@ -116,24 +117,21 @@ class FactorialAdvanced {
116
117
2 -> numbers[start].multiply(numbers[start + 1 ])
117
118
3 -> numbers[start].multiply(numbers[start + 1 ]).multiply(numbers[start + 2 ])
118
119
else -> {
119
- // Otherwise , split the list in half and recursively do this.
120
+ // otherwise , split the list in half and recursively do this.
120
121
val m = end + start ushr 1
121
122
listNumbers(numbers, start, m).multiply(listNumbers(numbers, m, end))
122
123
}
123
124
}
124
125
}
125
126
126
- /* *
127
- * returns the base-2 logarithm of number, rounded according to the celling.
128
- */
127
+ // returns the base-2 logarithm of number, rounded according to the celling.
129
128
private fun log2Celling (number : Int ): Int {
130
129
return Int .SIZE_BITS - (number - 1 ).countLeadingZeroBits()
131
130
}
132
131
133
- /* *
134
- * returns the base-2 logarithm of number rounded according to the floor.
135
- */
132
+ // returns the base-2 logarithm of number rounded according to the floor.
136
133
private fun log2Floor (number : Long ): Int {
137
134
return Long .SIZE_BITS - 1 - number.countLeadingZeroBits()
138
135
}
136
+
139
137
}
0 commit comments