Computes the result from a range value. @param value sequence @param avg calculate average @return result, or null if sequence is empty @throws QueryException query exception
(final Value value, final boolean avg)
| 113 | * @throws QueryException query exception |
| 114 | */ |
| 115 | private Item range(final Value value, final boolean avg) throws QueryException { |
| 116 | if(value.isEmpty()) return null; |
| 117 | |
| 118 | long min = value.itemAt(0).itr(info), max = value.itemAt(value.size() - 1).itr(info); |
| 119 | if(avg) { |
| 120 | final BigDecimal bs = BigDecimal.valueOf(min), be = BigDecimal.valueOf(max); |
| 121 | return Dec.get(bs.add(be).divide(Dec.BD_2, MathContext.DECIMAL64)); |
| 122 | } |
| 123 | |
| 124 | // Little Gauss computation |
| 125 | // swap values if order is descending |
| 126 | if(min > max) { |
| 127 | final long t = max; |
| 128 | max = min; |
| 129 | min = t; |
| 130 | } |
| 131 | |
| 132 | // range is small enough to be computed with long values |
| 133 | if(max < 3037000500L) return Itr.get((min + max) * (max - min + 1) / 2); |
| 134 | // compute larger ranges |
| 135 | final BigInteger bs = BigInteger.valueOf(min), be = BigInteger.valueOf(max); |
| 136 | final BigInteger bi = bs.add(be).multiply(be.subtract(bs).add(BigInteger.ONE)). |
| 137 | divide(BigInteger.valueOf(2)); |
| 138 | final long l = bi.longValue(); |
| 139 | // check if result is small enough to be represented as long value |
| 140 | if(bi.equals(BigInteger.valueOf(l))) return Itr.get(l); |
| 141 | throw RANGE_X.get(info, bi); |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Sums up the specified item(s). |