|
1 | 1 | package com.tegonal.minimalist |
2 | 2 |
|
3 | 3 | import com.tegonal.minimalist.generators.impl.possibleMaxSizeSafeInIntDomainWithoutDivideTrick |
4 | | -import com.tegonal.minimalist.generators.impl.prefixSumFast |
5 | | -import com.tegonal.minimalist.generators.impl.prefixSumSlower |
6 | 4 | import org.openjdk.jmh.annotations.* |
7 | 5 | import java.util.concurrent.TimeUnit |
8 | 6 |
|
@@ -59,3 +57,87 @@ open class PrefixSumBench { |
59 | 57 | ) |
60 | 58 | } |
61 | 59 | } |
| 60 | + |
| 61 | + |
| 62 | +private fun prefixSumFast(size: Int, numOfRangesWithMinSize: Int, minSize: Int, possibleMaxSize: Int) = |
| 63 | + prefixSumFast( |
| 64 | + size = size, |
| 65 | + numOfRangesWithMinSize = numOfRangesWithMinSize, |
| 66 | + minSize = minSize, |
| 67 | + possibleMaxSize = possibleMaxSize, |
| 68 | + plus = Int::plus, |
| 69 | + minus = Int::minus, |
| 70 | + times = Int::times, |
| 71 | + divide = Int::div, |
| 72 | + one = 1, |
| 73 | + two = 2 |
| 74 | + ) |
| 75 | + |
| 76 | +private fun prefixSumSlower(size: Int, numOfRangesWithMinSize: Int, minSize: Int, possibleMaxSize: Int): Int = |
| 77 | + prefixSumSlower( |
| 78 | + size = size, |
| 79 | + numOfRangesWithMinSize = numOfRangesWithMinSize, |
| 80 | + minSize = minSize, |
| 81 | + possibleMaxSize = possibleMaxSize, |
| 82 | + plus = Int::plus, |
| 83 | + minus = Int::minus, |
| 84 | + times = Int::times, |
| 85 | + divide = Int::div, |
| 86 | + mod = Int::rem, |
| 87 | + zero = 0, |
| 88 | + one = 1, |
| 89 | + two = 2 |
| 90 | + ) |
| 91 | + |
| 92 | +private inline fun <NumberT> prefixSumFast( |
| 93 | + size: NumberT, |
| 94 | + numOfRangesWithMinSize: NumberT, |
| 95 | + minSize: NumberT, |
| 96 | + possibleMaxSize: NumberT, |
| 97 | + crossinline plus: (NumberT, NumberT) -> NumberT, |
| 98 | + crossinline minus: (NumberT, NumberT) -> NumberT, |
| 99 | + crossinline times: (NumberT, NumberT) -> NumberT, |
| 100 | + crossinline divide: (NumberT, NumberT) -> NumberT, |
| 101 | + one: NumberT, |
| 102 | + two: NumberT, |
| 103 | +): NumberT where NumberT : Number, NumberT : Comparable<NumberT> { |
| 104 | + val n = plus(minus(size, minSize), one) |
| 105 | + val numOfRangesWithGivenSize = numOfRangesWithSize(size, possibleMaxSize, plus, minus, one) |
| 106 | + // note, as far as I can see it is not possible that both n and numOfRangesWithMinSize + numOfRangesWithGivenSize |
| 107 | + // are odd, i.e. the result is always even, and therefore / 2 is safe (no truncation because of Int/Long arithmetic |
| 108 | + // happens) |
| 109 | + return divide(times(n, plus(numOfRangesWithMinSize, numOfRangesWithGivenSize)), two) |
| 110 | +} |
| 111 | + |
| 112 | +private inline fun <NumberT> prefixSumSlower( |
| 113 | + size: NumberT, |
| 114 | + numOfRangesWithMinSize: NumberT, |
| 115 | + minSize: NumberT, |
| 116 | + possibleMaxSize: NumberT, |
| 117 | + crossinline plus: (NumberT, NumberT) -> NumberT, |
| 118 | + crossinline minus: (NumberT, NumberT) -> NumberT, |
| 119 | + crossinline times: (NumberT, NumberT) -> NumberT, |
| 120 | + crossinline divide: (NumberT, NumberT) -> NumberT, |
| 121 | + crossinline mod: (NumberT, NumberT) -> NumberT, |
| 122 | + zero: NumberT, |
| 123 | + one: NumberT, |
| 124 | + two: NumberT, |
| 125 | +): NumberT where NumberT : Number, NumberT : Comparable<NumberT> { |
| 126 | + val n = plus(minus(size, minSize), one) |
| 127 | + val numOfRangesWithGivenSize = numOfRangesWithSize(size, possibleMaxSize, plus, minus, one) |
| 128 | + // usual formula: n * (first + last) / 2 would overflow, hence we divide first. In order not to truncate (due to |
| 129 | + // int division) need to check if n is even or not (one of both is always even). |
| 130 | + return if (mod(n, two) == zero) { |
| 131 | + times(divide(n, two), plus(numOfRangesWithMinSize, numOfRangesWithGivenSize)) |
| 132 | + } else { |
| 133 | + times(n, divide(plus(numOfRangesWithMinSize, numOfRangesWithGivenSize), two)) |
| 134 | + } |
| 135 | +} |
| 136 | + |
| 137 | +private inline fun <NumberT> numOfRangesWithSize( |
| 138 | + size: NumberT, |
| 139 | + possibleMaxSize: NumberT, |
| 140 | + plus: (NumberT, NumberT) -> NumberT, |
| 141 | + minus: (NumberT, NumberT) -> NumberT, |
| 142 | + one: NumberT, |
| 143 | +): NumberT where NumberT : Number, NumberT : Comparable<NumberT> = plus(minus(possibleMaxSize, size), one) |
0 commit comments