This is an automated email from the ASF dual-hosted git repository.
twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 5c73de213 chore(log): remove the DCHECK macro (#2896)
5c73de213 is described below
commit 5c73de21374c5e4875111e9c203c646710045af7
Author: Twice <[email protected]>
AuthorDate: Fri Apr 25 12:42:22 2025 +0800
chore(log): remove the DCHECK macro (#2896)
Signed-off-by: PragmaTwice <[email protected]>
Co-authored-by: hulk <[email protected]>
---
src/commands/cmd_hll.cc | 6 +++---
src/commands/command_parser.h | 2 +-
src/common/bitfield_util.cc | 8 ++++----
src/common/logging.h | 6 +-----
src/common/rdb_stream.cc | 2 +-
src/server/server.cc | 2 +-
src/storage/batch_indexer.h | 6 +++---
src/storage/storage.cc | 18 +++++++++---------
src/storage/storage.h | 2 +-
src/types/hyperloglog.cc | 4 ++--
src/types/redis_bitmap.cc | 6 +++---
src/types/redis_bitmap_string.cc | 2 +-
src/types/redis_hash.cc | 2 +-
src/types/redis_hyperloglog.cc | 16 ++++++++--------
src/types/redis_set.cc | 2 +-
src/types/sample_helper.h | 2 +-
src/types/tdigest.cc | 8 ++++----
src/types/tdigest.h | 4 ++--
18 files changed, 47 insertions(+), 51 deletions(-)
diff --git a/src/commands/cmd_hll.cc b/src/commands/cmd_hll.cc
index 35d63103e..818d563c0 100644
--- a/src/commands/cmd_hll.cc
+++ b/src/commands/cmd_hll.cc
@@ -35,7 +35,7 @@ class CommandPfAdd final : public Commander {
public:
Status Execute(engine::Context &ctx, Server *srv, Connection *conn,
std::string *output) override {
redis::HyperLogLog hll(srv->storage, conn->GetNamespace());
- DCHECK(args_.size() >= 2u);
+ CHECK(args_.size() >= 2u);
std::vector<uint64_t> hashes(args_.size() - 2);
for (size_t i = 2; i < args_.size(); i++) {
hashes[i - 2] = redis::HyperLogLog::HllHash(args_[i]);
@@ -61,7 +61,7 @@ class CommandPfCount final : public Commander {
uint64_t ret{};
rocksdb::Status s;
// The first argument is the command name, so we need to skip it.
- DCHECK(args_.size() >= 2u);
+ CHECK(args_.size() >= 2u);
if (args_.size() > 2) {
std::vector<Slice> keys(args_.begin() + 1, args_.end());
@@ -86,7 +86,7 @@ class CommandPfCount final : public Commander {
class CommandPfMerge final : public Commander {
Status Execute(engine::Context &ctx, Server *srv, Connection *conn,
std::string *output) override {
redis::HyperLogLog hll(srv->storage, conn->GetNamespace());
- DCHECK(args_.size() > 1u);
+ CHECK(args_.size() > 1u);
std::vector<Slice> src_user_keys(args_.begin() + 2, args_.end());
auto s = hll.Merge(ctx, /*dest_user_key=*/args_[1], src_user_keys);
diff --git a/src/commands/command_parser.h b/src/commands/command_parser.h
index a4e06e1c5..89ec57519 100644
--- a/src/commands/command_parser.h
+++ b/src/commands/command_parser.h
@@ -88,7 +88,7 @@ struct CommandParser {
std::enable_if_t<IsRandomAccessIter, size_t> Remains() const {
// O(1) iff Iter is random access iterator.
auto d = std::distance(begin_, end_);
- DCHECK(d >= 0);
+ CHECK(d >= 0);
return d;
}
diff --git a/src/common/bitfield_util.cc b/src/common/bitfield_util.cc
index bd8a549fd..8a3b9da87 100644
--- a/src/common/bitfield_util.cc
+++ b/src/common/bitfield_util.cc
@@ -59,7 +59,7 @@ StatusOr<bool> SignedBitfieldPlus(uint64_t value, int64_t
incr, uint8_t bits, Bi
} else if (overflow == BitfieldOverflowBehavior::kSat) {
*dst = max;
} else {
- DCHECK(overflow == BitfieldOverflowBehavior::kFail);
+ CHECK(overflow == BitfieldOverflowBehavior::kFail);
}
return true;
} else if (signed_value < min || (bits != 64 && incr < min_incr) ||
@@ -69,7 +69,7 @@ StatusOr<bool> SignedBitfieldPlus(uint64_t value, int64_t
incr, uint8_t bits, Bi
} else if (overflow == BitfieldOverflowBehavior::kSat) {
*dst = min;
} else {
- DCHECK(overflow == BitfieldOverflowBehavior::kFail);
+ CHECK(overflow == BitfieldOverflowBehavior::kFail);
}
return true;
}
@@ -103,7 +103,7 @@ StatusOr<bool> UnsignedBitfieldPlus(uint64_t value, int64_t
incr, uint8_t bits,
} else if (overflow == BitfieldOverflowBehavior::kSat) {
*dst = max;
} else {
- DCHECK(overflow == BitfieldOverflowBehavior::kFail);
+ CHECK(overflow == BitfieldOverflowBehavior::kFail);
}
return true;
} else if (incr < 0 && incr < min_incr) {
@@ -112,7 +112,7 @@ StatusOr<bool> UnsignedBitfieldPlus(uint64_t value, int64_t
incr, uint8_t bits,
} else if (overflow == BitfieldOverflowBehavior::kSat) {
*dst = 0;
} else {
- DCHECK(overflow == BitfieldOverflowBehavior::kFail);
+ CHECK(overflow == BitfieldOverflowBehavior::kFail);
}
return true;
}
diff --git a/src/common/logging.h b/src/common/logging.h
index ff54f890a..c2ddc2f56 100644
--- a/src/common/logging.h
+++ b/src/common/logging.h
@@ -120,8 +120,4 @@ inline constexpr bool GLOG_IN_DEBUG =
// NOLINTNEXTLINE
#define CHECK(cond) \
- if (!(cond)) LOG(FATAL) << "Check `" << #cond << "` failed. "
-
-// NOLINTNEXTLINE
-#define DCHECK(cond) \
- if constexpr (GLOG_IN_DEBUG) CHECK(cond)
+ if (!(cond)) fatal("Check `{}` failed.", #cond);
diff --git a/src/common/rdb_stream.cc b/src/common/rdb_stream.cc
index 7be1088be..5a4fb9be3 100644
--- a/src/common/rdb_stream.cc
+++ b/src/common/rdb_stream.cc
@@ -70,7 +70,7 @@ Status RdbFileStream::Read(char *buf, size_t len) {
}
check_sum_ = crc64(check_sum_, reinterpret_cast<const unsigned char
*>(buf), read_bytes);
buf = buf + read_bytes;
- DCHECK(len >= read_bytes);
+ CHECK(len >= read_bytes);
len -= read_bytes;
total_read_bytes_ += read_bytes;
}
diff --git a/src/server/server.cc b/src/server/server.cc
index 2d69c5d88..fed86c734 100644
--- a/src/server/server.cc
+++ b/src/server/server.cc
@@ -1894,7 +1894,7 @@ void Server::increaseWorkerThreads(size_t delta) {
void Server::decreaseWorkerThreads(size_t delta) {
auto current_worker_threads = worker_threads_.size();
- DCHECK(current_worker_threads > delta);
+ CHECK(current_worker_threads > delta);
auto remain_worker_threads = current_worker_threads - delta;
for (size_t i = remain_worker_threads; i < current_worker_threads; i++) {
// Unix socket will be listening on the first worker,
diff --git a/src/storage/batch_indexer.h b/src/storage/batch_indexer.h
index b0aaafff7..4b310b468 100644
--- a/src/storage/batch_indexer.h
+++ b/src/storage/batch_indexer.h
@@ -36,9 +36,9 @@ class WriteBatchIndexer : public rocksdb::WriteBatch::Handler
{
explicit WriteBatchIndexer(engine::Storage* storage,
rocksdb::WriteBatchWithIndex* dest_batch,
const rocksdb::Snapshot* snapshot)
: storage_(storage), dest_batch_(dest_batch), snapshot_(snapshot) {
- DCHECK(storage != nullptr);
- DCHECK(dest_batch != nullptr);
- DCHECK(snapshot != nullptr);
+ CHECK(storage != nullptr);
+ CHECK(dest_batch != nullptr);
+ CHECK(snapshot != nullptr);
}
explicit WriteBatchIndexer(engine::Context& ctx)
: WriteBatchIndexer(ctx.storage, ctx.batch.get(), ctx.GetSnapshot()) {}
diff --git a/src/storage/storage.cc b/src/storage/storage.cc
index 4c16e186e..e59a0e602 100644
--- a/src/storage/storage.cc
+++ b/src/storage/storage.cc
@@ -606,8 +606,8 @@ rocksdb::Status Storage::Get(engine::Context &ctx, const
rocksdb::ReadOptions &o
rocksdb::ColumnFamilyHandle *column_family, const
rocksdb::Slice &key,
std::string *value) {
if (ctx.txn_context_enabled) {
- DCHECK(options.snapshot != nullptr);
- DCHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
+ CHECK(options.snapshot != nullptr);
+ CHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
}
rocksdb::Status s;
if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) {
@@ -631,8 +631,8 @@ rocksdb::Status Storage::Get(engine::Context &ctx, const
rocksdb::ReadOptions &o
rocksdb::ColumnFamilyHandle *column_family, const
rocksdb::Slice &key,
rocksdb::PinnableSlice *value) {
if (ctx.txn_context_enabled) {
- DCHECK(options.snapshot != nullptr);
- DCHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
+ CHECK(options.snapshot != nullptr);
+ CHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
}
rocksdb::Status s;
if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) {
@@ -664,8 +664,8 @@ void Storage::recordKeyspaceStat(const
rocksdb::ColumnFamilyHandle *column_famil
rocksdb::Iterator *Storage::NewIterator(engine::Context &ctx, const
rocksdb::ReadOptions &options,
rocksdb::ColumnFamilyHandle
*column_family) {
if (ctx.txn_context_enabled) {
- DCHECK(options.snapshot != nullptr);
- DCHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
+ CHECK(options.snapshot != nullptr);
+ CHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
}
auto iter = db_->NewIterator(options, column_family);
if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) {
@@ -680,8 +680,8 @@ void Storage::MultiGet(engine::Context &ctx, const
rocksdb::ReadOptions &options
rocksdb::ColumnFamilyHandle *column_family, const
size_t num_keys, const rocksdb::Slice *keys,
rocksdb::PinnableSlice *values, rocksdb::Status
*statuses) {
if (ctx.txn_context_enabled) {
- DCHECK(options.snapshot != nullptr);
- DCHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
+ CHECK(options.snapshot != nullptr);
+ CHECK(ctx.GetSnapshot()->GetSequenceNumber() ==
options.snapshot->GetSequenceNumber());
}
if (is_txn_mode_ && txn_write_batch_->GetWriteBatch()->Count() > 0) {
txn_write_batch_->MultiGetFromBatchAndDB(db_.get(), options,
column_family, num_keys, keys, values, statuses,
@@ -722,7 +722,7 @@ rocksdb::Status Storage::writeToDB(engine::Context &ctx,
const rocksdb::WriteOpt
auto s = updates->Iterate(&handle);
if (!s.ok()) return s;
} else {
- DCHECK(ctx.batch == nullptr);
+ CHECK(ctx.batch == nullptr);
}
return db_->Write(options, updates);
diff --git a/src/storage/storage.h b/src/storage/storage.h
index 71d8b9537..9f2352d5e 100644
--- a/src/storage/storage.h
+++ b/src/storage/storage.h
@@ -469,7 +469,7 @@ struct Context {
const rocksdb::Snapshot *GetSnapshot() {
if (snapshot_ == nullptr) {
// Should not acquire a snapshot_ on a moved-from object.
- DCHECK(storage != nullptr);
+ CHECK(storage != nullptr);
snapshot_ = storage->GetDB()->GetSnapshot(); // NOLINT
}
return snapshot_;
diff --git a/src/types/hyperloglog.cc b/src/types/hyperloglog.cc
index 509c867bf..dcca3d3a3 100644
--- a/src/types/hyperloglog.cc
+++ b/src/types/hyperloglog.cc
@@ -100,7 +100,7 @@ DenseHllResult ExtractDenseHllResult(uint64_t hash) {
* This may sound like inefficient, but actually in the average case
* there are high probabilities to find a 1 after a few iterations. */
uint32_t index = hash & kHyperLogLogRegisterCountMask; /* Register index. */
- DCHECK(index < kHyperLogLogRegisterCount);
+ CHECK(index < kHyperLogLogRegisterCount);
hash >>= kHyperLogLogRegisterCountPow; /* Remove bits used to address the
register. */
hash |= (static_cast<uint64_t>(1U) << kHyperLogLogHashBitCount);
uint8_t ctz = __builtin_ctzll(hash) + 1;
@@ -165,7 +165,7 @@ void HllMerge(std::vector<std::string> *dest_registers,
const std::vector<nonstd
continue;
}
if (dest_segment->empty()) {
- DCHECK(kHyperLogLogSegmentBytes == src_segment.size());
+ CHECK(kHyperLogLogSegmentBytes == src_segment.size());
*dest_segment = std::string(src_segment.begin(), src_segment.end());
continue;
}
diff --git a/src/types/redis_bitmap.cc b/src/types/redis_bitmap.cc
index fb9d9d102..00c8d1b3f 100644
--- a/src/types/redis_bitmap.cc
+++ b/src/types/redis_bitmap.cc
@@ -308,7 +308,7 @@ rocksdb::Status Bitmap::BitCount(engine::Context &ctx,
const Slice &user_key, in
rocksdb::Status Bitmap::BitPos(engine::Context &ctx, const Slice &user_key,
bool bit, int64_t start, int64_t stop,
bool stop_given, int64_t *pos, bool
is_bit_index) {
- if (is_bit_index) DCHECK(stop_given);
+ if (is_bit_index) CHECK(stop_given);
std::string raw_value;
std::string ns_key = AppendNamespacePrefix(user_key);
@@ -404,7 +404,7 @@ rocksdb::Status Bitmap::BitPos(engine::Context &ctx, const
Slice &user_key, bool
}
size_t stop_byte_in_segment = pin_value.size();
if (i == stop_segment_index) {
- DCHECK((u_stop / to_bit_factor) % kBitmapSegmentBytes + 1 <=
pin_value.size());
+ CHECK((u_stop / to_bit_factor) % kBitmapSegmentBytes + 1 <=
pin_value.size());
stop_byte_in_segment = (u_stop / to_bit_factor) % kBitmapSegmentBytes +
1;
byte_with_bit_stop = stop_byte_in_segment;
}
@@ -558,7 +558,7 @@ rocksdb::Status Bitmap::BitOp(engine::Context &ctx,
BitOpFlags op_flag, const st
auto apply_fast_path_op = [&](auto op) {
// Note: kBitOpNot cannot use this op, it only applying
// to kBitOpAnd, kBitOpOr, kBitOpXor.
- DCHECK(op_flag != kBitOpNot);
+ CHECK(op_flag != kBitOpNot);
while (frag_minlen >= sizeof(uint64_t) * 4) {
for (uint64_t i = 1; i < frag_numkeys; i++) {
op(lres[0], lp[i][0]);
diff --git a/src/types/redis_bitmap_string.cc b/src/types/redis_bitmap_string.cc
index 71a898f37..33202b6f5 100644
--- a/src/types/redis_bitmap_string.cc
+++ b/src/types/redis_bitmap_string.cc
@@ -195,7 +195,7 @@ std::pair<int64_t, int64_t>
BitmapString::NormalizeToByteRangeWithPaddingMask(bo
int64_t origin_end,
uint8_t *first_byte_neg_mask,
uint8_t *last_byte_neg_mask) {
- DCHECK(origin_start <= origin_end);
+ CHECK(origin_start <= origin_end);
if (is_bit) {
*first_byte_neg_mask = ~((1 << (8 - (origin_start & 7))) - 1) & 0xFF;
*last_byte_neg_mask = (1 << (7 - (origin_end & 7))) - 1;
diff --git a/src/types/redis_hash.cc b/src/types/redis_hash.cc
index 448a6b240..1f31b3279 100644
--- a/src/types/redis_hash.cc
+++ b/src/types/redis_hash.cc
@@ -418,7 +418,7 @@ rocksdb::Status Hash::RandField(engine::Context &ctx, const
Slice &user_key, int
case HashFetchType::kOnlyKey: {
// GetAll should only fetching the key, checking all the values is empty
for (const FieldValue &value : *field_values) {
- DCHECK(value.value.empty());
+ CHECK(value.value.empty());
}
break;
}
diff --git a/src/types/redis_hyperloglog.cc b/src/types/redis_hyperloglog.cc
index f7d2b12ee..63ee0b2b9 100644
--- a/src/types/redis_hyperloglog.cc
+++ b/src/types/redis_hyperloglog.cc
@@ -102,7 +102,7 @@ rocksdb::Status HyperLogLog::GetMetadata(engine::Context
&ctx, const Slice &ns_k
}
uint64_t HyperLogLog::HllHash(std::string_view element) {
- DCHECK(element.size() <= std::numeric_limits<int32_t>::max());
+ CHECK(element.size() <= std::numeric_limits<int32_t>::max());
return HllMurMurHash64A(element.data(),
static_cast<int32_t>(element.size()), kHyperLogLogHashSeed);
}
@@ -139,8 +139,8 @@ rocksdb::Status HyperLogLog::Add(engine::Context &ctx,
const Slice &user_key,
},
&entry);
if (!s.ok()) return s;
- DCHECK(entry != nullptr);
- DCHECK(kHyperLogLogSegmentBytes == entry->data.size());
+ CHECK(entry != nullptr);
+ CHECK(kHyperLogLogSegmentBytes == entry->data.size());
auto *segment_data = reinterpret_cast<uint8_t *>(entry->data.data());
uint8_t old_count = HllDenseGetRegister(segment_data,
register_index_in_segment);
if (dense_hll_result.hll_trailing_zero > old_count) {
@@ -185,7 +185,7 @@ rocksdb::Status HyperLogLog::Count(engine::Context &ctx,
const Slice &user_key,
if (!s.ok()) {
return s;
}
- DCHECK(kHyperLogLogSegmentCount == registers.size());
+ CHECK(kHyperLogLogSegmentCount == registers.size());
std::vector<nonstd::span<const uint8_t>> register_segments =
TransformToSpan(registers);
*ret = HllDenseEstimate(register_segments);
return rocksdb::Status::OK();
@@ -193,7 +193,7 @@ rocksdb::Status HyperLogLog::Count(engine::Context &ctx,
const Slice &user_key,
rocksdb::Status HyperLogLog::mergeUserKeys(engine::Context &ctx, const
std::vector<Slice> &user_keys,
std::vector<std::string>
*register_segments) {
- DCHECK(user_keys.size() >= static_cast<size_t>(1));
+ CHECK(user_keys.size() >= static_cast<size_t>(1));
std::string first_ns_key = AppendNamespacePrefix(user_keys[0]);
rocksdb::Status s = getRegisters(ctx, first_ns_key, register_segments);
@@ -212,8 +212,8 @@ rocksdb::Status HyperLogLog::mergeUserKeys(engine::Context
&ctx, const std::vect
std::vector<rocksdb::PinnableSlice> source_registers;
s = getRegisters(ctx, source_key, &source_registers);
if (!s.ok()) return s;
- DCHECK(kHyperLogLogSegmentCount == source_registers.size());
- DCHECK(kHyperLogLogSegmentCount == register_segments->size());
+ CHECK(kHyperLogLogSegmentCount == source_registers.size());
+ CHECK(kHyperLogLogSegmentCount == register_segments->size());
std::vector<nonstd::span<const uint8_t>> source_register_span =
TransformToSpan(source_registers);
HllMerge(register_segments, source_register_span);
}
@@ -221,7 +221,7 @@ rocksdb::Status HyperLogLog::mergeUserKeys(engine::Context
&ctx, const std::vect
}
rocksdb::Status HyperLogLog::CountMultiple(engine::Context &ctx, const
std::vector<Slice> &user_key, uint64_t *ret) {
- DCHECK(user_key.size() > static_cast<size_t>(1));
+ CHECK(user_key.size() > static_cast<size_t>(1));
std::vector<std::string> register_segments;
auto s = mergeUserKeys(ctx, user_key, ®ister_segments);
if (!s.ok()) return s;
diff --git a/src/types/redis_set.cc b/src/types/redis_set.cc
index 01849328c..07d5c7829 100644
--- a/src/types/redis_set.cc
+++ b/src/types/redis_set.cc
@@ -208,7 +208,7 @@ rocksdb::Status Set::Take(engine::Context &ctx, const Slice
&user_key, std::vect
bool unique = true;
if (count == 0) return rocksdb::Status::OK();
if (count < 0) {
- DCHECK(!pop);
+ CHECK(!pop);
count = -count;
unique = false;
}
diff --git a/src/types/sample_helper.h b/src/types/sample_helper.h
index 07ef234ad..f7d6db15d 100644
--- a/src/types/sample_helper.h
+++ b/src/types/sample_helper.h
@@ -37,7 +37,7 @@ rocksdb::Status ExtractRandMemberFromSet(bool unique, size_t
count, const GetAll
if (!s.ok() || samples.empty()) return s;
size_t all_element_size = samples.size();
- DCHECK(all_element_size >= 1U);
+ CHECK(all_element_size >= 1U);
elements->reserve(std::min(all_element_size, count));
if (!unique || count == 1) {
diff --git a/src/types/tdigest.cc b/src/types/tdigest.cc
index af3a71bbb..3c6080975 100644
--- a/src/types/tdigest.cc
+++ b/src/types/tdigest.cc
@@ -281,7 +281,7 @@ class TDigestImpl {
break;
}
}
- DCHECK(ci < td.size());
+ CHECK(ci < td.size());
// deviation of index from the centroid center
double diff = index + td[ci].weight / 2 - weight_sum;
@@ -297,9 +297,9 @@ class TDigestImpl {
if (diff > 0) {
if (ci_right == td.size() - 1) {
// index larger than center of last bin
- DCHECK(weight_sum == total_weight_);
+ CHECK(weight_sum == total_weight_);
const Centroid* c = &td[ci_right];
- DCHECK(c->weight >= 2);
+ CHECK(c->weight >= 2);
return Lerp(c->mean, max_, diff / (c->weight / 2));
}
++ci_right;
@@ -307,7 +307,7 @@ class TDigestImpl {
if (ci_left == 0) {
// index smaller than center of first bin
const Centroid* c = &td[0];
- DCHECK(c->weight >= 2);
+ CHECK(c->weight >= 2);
return Lerp(min_, c->mean, index / (c->weight / 2));
}
--ci_left;
diff --git a/src/types/tdigest.h b/src/types/tdigest.h
index dd6d39e5b..0f088cb0f 100644
--- a/src/types/tdigest.h
+++ b/src/types/tdigest.h
@@ -124,7 +124,7 @@ inline StatusOr<double> TDigestQuantile(TD&& td, double q) {
if (ci_right == td.End()) {
// index larger than center of last bin
auto c = GET_OR_RET(ci_left->GetCentroid());
- DCHECK(c.weight >= 2);
+ CHECK(c.weight >= 2);
return Lerp(c.mean, td.Max(), diff / (c.weight / 2));
}
ci_right->Next();
@@ -132,7 +132,7 @@ inline StatusOr<double> TDigestQuantile(TD&& td, double q) {
if (ci_left == td.Begin()) {
// index smaller than center of first bin
auto c = GET_OR_RET(ci_left->GetCentroid());
- DCHECK(c.weight >= 2);
+ CHECK(c.weight >= 2);
return Lerp(td.Min(), c.mean, index / (c.weight / 2));
}
ci_left->Prev();