Merge multiple sets of expr's optypes in diff dirs (#17192)

Signed-off-by: xige-16 <xi.ge@zilliz.com>
pull/17198/head
xige-16 2022-05-24 21:56:00 +08:00 committed by GitHub
parent ec1103ca27
commit a8829554eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 186 additions and 211 deletions

View File

@ -31,6 +31,7 @@
#include "knowhere/common/MetricType.h" #include "knowhere/common/MetricType.h"
#include "pb/schema.pb.h" #include "pb/schema.pb.h"
#include "pb/segcore.pb.h" #include "pb/segcore.pb.h"
#include "pb/plan.pb.h"
namespace milvus { namespace milvus {
@ -61,6 +62,8 @@ using Timestamp = uint64_t; // TODO: use TiKV-like timestamp
constexpr auto MAX_TIMESTAMP = std::numeric_limits<Timestamp>::max(); constexpr auto MAX_TIMESTAMP = std::numeric_limits<Timestamp>::max();
constexpr auto MAX_ROW_COUNT = std::numeric_limits<idx_t>::max(); constexpr auto MAX_ROW_COUNT = std::numeric_limits<idx_t>::max();
using OpType = proto::plan::OpType;
using ArithOpType = proto::plan::ArithOpType;
using ScalarArray = proto::schema::ScalarField; using ScalarArray = proto::schema::ScalarField;
using DataArray = proto::schema::FieldData; using DataArray = proto::schema::FieldData;
using VectorArray = proto::schema::VectorField; using VectorArray = proto::schema::VectorField;

View File

@ -14,7 +14,6 @@
#include <memory> #include <memory>
#include <knowhere/index/Index.h> #include <knowhere/index/Index.h>
#include <knowhere/common/Dataset.h> #include <knowhere/common/Dataset.h>
#include "index/OperatorType.h"
#include <boost/dynamic_bitset.hpp> #include <boost/dynamic_bitset.hpp>
namespace milvus::scalar { namespace milvus::scalar {

View File

@ -1,26 +0,0 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#pragma once
namespace milvus::scalar {
enum OperatorType {
LT = 0,
LE = 1,
GT = 3,
GE = 4,
RangeOp = 5,
InOp = 6,
NotInOp = 7,
PrefixMatchOp = 8,
PostfixMatchOp = 9,
};
} // namespace milvus::scalar

View File

@ -17,17 +17,17 @@ namespace milvus::scalar {
template <typename T> template <typename T>
const TargetBitmapPtr const TargetBitmapPtr
ScalarIndex<T>::Query(const DatasetPtr& dataset) { ScalarIndex<T>::Query(const DatasetPtr& dataset) {
auto op = dataset->Get<OperatorType>(OPERATOR_TYPE); auto op = dataset->Get<OpType>(OPERATOR_TYPE);
switch (op) { switch (op) {
case LT: case OpType::LessThan:
case LE: case OpType::LessEqual:
case GT: case OpType::GreaterThan:
case GE: { case OpType::GreaterEqual: {
auto value = dataset->Get<T>(RANGE_VALUE); auto value = dataset->Get<T>(RANGE_VALUE);
return Range(value, op); return Range(value, op);
} }
case RangeOp: { case OpType::Range: {
auto lower_bound_value = dataset->Get<T>(LOWER_BOUND_VALUE); auto lower_bound_value = dataset->Get<T>(LOWER_BOUND_VALUE);
auto upper_bound_value = dataset->Get<T>(UPPER_BOUND_VALUE); auto upper_bound_value = dataset->Get<T>(UPPER_BOUND_VALUE);
auto lower_bound_inclusive = dataset->Get<bool>(LOWER_BOUND_INCLUSIVE); auto lower_bound_inclusive = dataset->Get<bool>(LOWER_BOUND_INCLUSIVE);
@ -35,20 +35,20 @@ ScalarIndex<T>::Query(const DatasetPtr& dataset) {
return Range(lower_bound_value, lower_bound_inclusive, upper_bound_value, upper_bound_inclusive); return Range(lower_bound_value, lower_bound_inclusive, upper_bound_value, upper_bound_inclusive);
} }
case InOp: { case OpType::In: {
auto n = dataset->Get<int64_t>(knowhere::meta::ROWS); auto n = dataset->Get<int64_t>(knowhere::meta::ROWS);
auto values = dataset->Get<const void*>(knowhere::meta::TENSOR); auto values = dataset->Get<const void*>(knowhere::meta::TENSOR);
return In(n, reinterpret_cast<const T*>(values)); return In(n, reinterpret_cast<const T*>(values));
} }
case NotInOp: { case OpType::NotIn: {
auto n = dataset->Get<int64_t>(knowhere::meta::ROWS); auto n = dataset->Get<int64_t>(knowhere::meta::ROWS);
auto values = dataset->Get<const void*>(knowhere::meta::TENSOR); auto values = dataset->Get<const void*>(knowhere::meta::TENSOR);
return NotIn(n, reinterpret_cast<const T*>(values)); return NotIn(n, reinterpret_cast<const T*>(values));
} }
case PrefixMatchOp: case OpType::PrefixMatch:
case PostfixMatchOp: case OpType::PostfixMatch:
default: default:
throw std::invalid_argument(std::string("unsupported operator type: " + std::to_string(op))); throw std::invalid_argument(std::string("unsupported operator type: " + std::to_string(op)));
} }

View File

@ -16,6 +16,7 @@
#include <string> #include <string>
#include <boost/dynamic_bitset.hpp> #include <boost/dynamic_bitset.hpp>
#include "index/Index.h" #include "index/Index.h"
#include "common/Types.h"
namespace milvus::scalar { namespace milvus::scalar {
@ -32,7 +33,7 @@ class ScalarIndex : public IndexBase {
NotIn(size_t n, const T* values) = 0; NotIn(size_t n, const T* values) = 0;
virtual const TargetBitmapPtr virtual const TargetBitmapPtr
Range(T value, OperatorType op) = 0; Range(T value, OpType op) = 0;
virtual const TargetBitmapPtr virtual const TargetBitmapPtr
Range(T lower_bound_value, bool lb_inclusive, T upper_bound_value, bool ub_inclusive) = 0; Range(T lower_bound_value, bool lb_inclusive, T upper_bound_value, bool ub_inclusive) = 0;

View File

@ -17,6 +17,7 @@
#include <string> #include <string>
#include "knowhere/common/Log.h" #include "knowhere/common/Log.h"
#include "Meta.h" #include "Meta.h"
#include "common/Utils.h"
namespace milvus::scalar { namespace milvus::scalar {
@ -140,7 +141,7 @@ ScalarIndexSort<T>::NotIn(const size_t n, const T* values) {
template <typename T> template <typename T>
inline const TargetBitmapPtr inline const TargetBitmapPtr
ScalarIndexSort<T>::Range(const T value, const OperatorType op) { ScalarIndexSort<T>::Range(const T value, const OpType op) {
if (!is_built_) { if (!is_built_) {
build(); build();
} }
@ -148,16 +149,16 @@ ScalarIndexSort<T>::Range(const T value, const OperatorType op) {
auto lb = data_.begin(); auto lb = data_.begin();
auto ub = data_.end(); auto ub = data_.end();
switch (op) { switch (op) {
case OperatorType::LT: case OpType::LessThan:
ub = std::lower_bound(data_.begin(), data_.end(), IndexStructure<T>(value)); ub = std::lower_bound(data_.begin(), data_.end(), IndexStructure<T>(value));
break; break;
case OperatorType::LE: case OpType::LessEqual:
ub = std::upper_bound(data_.begin(), data_.end(), IndexStructure<T>(value)); ub = std::upper_bound(data_.begin(), data_.end(), IndexStructure<T>(value));
break; break;
case OperatorType::GT: case OpType::GreaterThan:
lb = std::upper_bound(data_.begin(), data_.end(), IndexStructure<T>(value)); lb = std::upper_bound(data_.begin(), data_.end(), IndexStructure<T>(value));
break; break;
case OperatorType::GE: case OpType::GreaterEqual:
lb = std::lower_bound(data_.begin(), data_.end(), IndexStructure<T>(value)); lb = std::lower_bound(data_.begin(), data_.end(), IndexStructure<T>(value));
break; break;
default: default:

View File

@ -55,7 +55,7 @@ class ScalarIndexSort : public ScalarIndex<T> {
NotIn(size_t n, const T* values) override; NotIn(size_t n, const T* values) override;
const TargetBitmapPtr const TargetBitmapPtr
Range(T value, OperatorType op) override; Range(T value, OpType op) override;
const TargetBitmapPtr const TargetBitmapPtr
Range(T lower_bound_value, bool lb_inclusive, T upper_bound_value, bool ub_inclusive) override; Range(T lower_bound_value, bool lb_inclusive, T upper_bound_value, bool ub_inclusive) override;

View File

@ -44,8 +44,8 @@ class StringIndex : public ScalarIndex<std::string> {
const TargetBitmapPtr const TargetBitmapPtr
Query(const DatasetPtr& dataset) override { Query(const DatasetPtr& dataset) override {
auto op = dataset->Get<OperatorType>(OPERATOR_TYPE); auto op = dataset->Get<OpType>(OPERATOR_TYPE);
if (op == PrefixMatchOp) { if (op == OpType::PrefixMatch) {
auto prefix = dataset->Get<std::string>(PREFIX_VALUE); auto prefix = dataset->Get<std::string>(PREFIX_VALUE);
return PrefixMatch(prefix); return PrefixMatch(prefix);
} }

View File

@ -20,7 +20,7 @@
#include <stdio.h> #include <stdio.h>
#include <fcntl.h> #include <fcntl.h>
#include <knowhere/common/Utils.h> #include <knowhere/common/Utils.h>
#include <pb/schema.pb.h> #include "exceptions/EasyAssert.h"
namespace milvus::scalar { namespace milvus::scalar {
@ -149,7 +149,7 @@ StringIndexMarisa::NotIn(size_t n, const std::string* values) {
} }
const TargetBitmapPtr const TargetBitmapPtr
StringIndexMarisa::Range(std::string value, OperatorType op) { StringIndexMarisa::Range(std::string value, OpType op) {
throw std::runtime_error("todo: unsupported now"); throw std::runtime_error("todo: unsupported now");
} }

View File

@ -50,7 +50,7 @@ class StringIndexMarisa : public StringIndex {
NotIn(size_t n, const std::string* values) override; NotIn(size_t n, const std::string* values) override;
const TargetBitmapPtr const TargetBitmapPtr
Range(std::string value, OperatorType op) override; Range(std::string value, OpType op) override;
const TargetBitmapPtr const TargetBitmapPtr
Range(std::string lower_bound_value, bool lb_inclusive, std::string upper_bound_value, bool ub_inclusive) override; Range(std::string lower_bound_value, bool lb_inclusive, std::string upper_bound_value, bool ub_inclusive) override;

View File

@ -43,8 +43,8 @@ class StringIndexSort : public ScalarIndexSort<std::string> {
const TargetBitmapPtr const TargetBitmapPtr
Query(const DatasetPtr& dataset) override { Query(const DatasetPtr& dataset) override {
auto op = dataset->Get<OperatorType>(OPERATOR_TYPE); auto op = dataset->Get<OpType>(OPERATOR_TYPE);
if (op == PrefixMatchOp) { if (op == OpType::PrefixMatch) {
auto prefix = dataset->Get<std::string>(PREFIX_VALUE); auto prefix = dataset->Get<std::string>(PREFIX_VALUE);
return PrefixMatch(prefix); return PrefixMatch(prefix);
} }

View File

@ -626,15 +626,15 @@ const char descriptor_table_protodef_plan_2eproto[] PROTOBUF_SECTION_VARIABLE(pr
"\030\005 \001(\t\"\221\001\n\010PlanNode\0224\n\013vector_anns\030\001 \001(\013" "\030\005 \001(\t\"\221\001\n\010PlanNode\0224\n\013vector_anns\030\001 \001(\013"
"2\035.milvus.proto.plan.VectorANNSH\000\022-\n\npre" "2\035.milvus.proto.plan.VectorANNSH\000\022-\n\npre"
"dicates\030\002 \001(\0132\027.milvus.proto.plan.ExprH\000" "dicates\030\002 \001(\0132\027.milvus.proto.plan.ExprH\000"
"\022\030\n\020output_field_ids\030\003 \003(\003B\006\n\004node*\234\001\n\006O" "\022\030\n\020output_field_ids\030\003 \003(\003B\006\n\004node*\272\001\n\006O"
"pType\022\013\n\007Invalid\020\000\022\017\n\013GreaterThan\020\001\022\020\n\014G" "pType\022\013\n\007Invalid\020\000\022\017\n\013GreaterThan\020\001\022\020\n\014G"
"reaterEqual\020\002\022\014\n\010LessThan\020\003\022\r\n\tLessEqual" "reaterEqual\020\002\022\014\n\010LessThan\020\003\022\r\n\tLessEqual"
"\020\004\022\t\n\005Equal\020\005\022\014\n\010NotEqual\020\006\022\017\n\013PrefixMat" "\020\004\022\t\n\005Equal\020\005\022\014\n\010NotEqual\020\006\022\017\n\013PrefixMat"
"ch\020\007\022\020\n\014PostfixMatch\020\010\022\t\n\005Match\020\t*G\n\013Ari" "ch\020\007\022\020\n\014PostfixMatch\020\010\022\t\n\005Match\020\t\022\t\n\005Ran"
"thOpType\022\013\n\007Unknown\020\000\022\007\n\003Add\020\001\022\007\n\003Sub\020\002\022" "ge\020\n\022\006\n\002In\020\013\022\t\n\005NotIn\020\014*G\n\013ArithOpType\022\013"
"\007\n\003Mul\020\003\022\007\n\003Div\020\004\022\007\n\003Mod\020\005B3Z1github.com" "\n\007Unknown\020\000\022\007\n\003Add\020\001\022\007\n\003Sub\020\002\022\007\n\003Mul\020\003\022\007"
"/milvus-io/milvus/internal/proto/planpbb" "\n\003Div\020\004\022\007\n\003Mod\020\005B3Z1github.com/milvus-io"
"\006proto3" "/milvus/internal/proto/planpbb\006proto3"
; ;
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_plan_2eproto_deps[1] = { static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_plan_2eproto_deps[1] = {
&::descriptor_table_schema_2eproto, &::descriptor_table_schema_2eproto,
@ -658,7 +658,7 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_pla
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_plan_2eproto_once; static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_plan_2eproto_once;
static bool descriptor_table_plan_2eproto_initialized = false; static bool descriptor_table_plan_2eproto_initialized = false;
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_plan_2eproto = { const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_plan_2eproto = {
&descriptor_table_plan_2eproto_initialized, descriptor_table_protodef_plan_2eproto, "plan.proto", 3327, &descriptor_table_plan_2eproto_initialized, descriptor_table_protodef_plan_2eproto, "plan.proto", 3357,
&descriptor_table_plan_2eproto_once, descriptor_table_plan_2eproto_sccs, descriptor_table_plan_2eproto_deps, 14, 1, &descriptor_table_plan_2eproto_once, descriptor_table_plan_2eproto_sccs, descriptor_table_plan_2eproto_deps, 14, 1,
schemas, file_default_instances, TableStruct_plan_2eproto::offsets, schemas, file_default_instances, TableStruct_plan_2eproto::offsets,
file_level_metadata_plan_2eproto, 17, file_level_enum_descriptors_plan_2eproto, file_level_service_descriptors_plan_2eproto, file_level_metadata_plan_2eproto, 17, file_level_enum_descriptors_plan_2eproto, file_level_service_descriptors_plan_2eproto,
@ -729,6 +729,9 @@ bool OpType_IsValid(int value) {
case 7: case 7:
case 8: case 8:
case 9: case 9:
case 10:
case 11:
case 12:
return true; return true;
default: default:
return false; return false;

View File

@ -198,12 +198,15 @@ enum OpType : int {
PrefixMatch = 7, PrefixMatch = 7,
PostfixMatch = 8, PostfixMatch = 8,
Match = 9, Match = 9,
Range = 10,
In = 11,
NotIn = 12,
OpType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(), OpType_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
OpType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max() OpType_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
}; };
bool OpType_IsValid(int value); bool OpType_IsValid(int value);
constexpr OpType OpType_MIN = Invalid; constexpr OpType OpType_MIN = Invalid;
constexpr OpType OpType_MAX = Match; constexpr OpType OpType_MAX = NotIn;
constexpr int OpType_ARRAYSIZE = OpType_MAX + 1; constexpr int OpType_ARRAYSIZE = OpType_MAX + 1;
const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* OpType_descriptor(); const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* OpType_descriptor();

View File

@ -25,6 +25,7 @@
#include <vector> #include <vector>
#include "common/Schema.h" #include "common/Schema.h"
#include "pb/plan.pb.h"
namespace milvus::query { namespace milvus::query {
@ -101,27 +102,6 @@ struct TermExpr : Expr {
accept(ExprVisitor&) override; accept(ExprVisitor&) override;
}; };
enum class OpType {
Invalid = 0,
GreaterThan = 1,
GreaterEqual = 2,
LessThan = 3,
LessEqual = 4,
Equal = 5,
NotEqual = 6,
PrefixMatch = 7,
PostfixMatch = 8,
};
enum class ArithOpType {
Unknown = 0,
Add = 1,
Sub = 2,
Mul = 3,
Div = 4,
Mod = 5,
};
static const std::map<std::string, ArithOpType> arith_op_mapping_ = { static const std::map<std::string, ArithOpType> arith_op_mapping_ = {
// arith_op_name -> arith_op // arith_op_name -> arith_op
{"add", ArithOpType::Add}, {"sub", ArithOpType::Sub}, {"mul", ArithOpType::Mul}, {"add", ArithOpType::Add}, {"sub", ArithOpType::Sub}, {"mul", ArithOpType::Mul},

View File

@ -211,7 +211,6 @@ auto
ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType { ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType {
auto& expr = static_cast<UnaryRangeExprImpl<T>&>(expr_raw); auto& expr = static_cast<UnaryRangeExprImpl<T>&>(expr_raw);
using Index = scalar::ScalarIndex<T>; using Index = scalar::ScalarIndex<T>;
using Operator = scalar::OperatorType;
auto op = expr.op_type_; auto op = expr.op_type_;
auto val = expr.value_; auto val = expr.value_;
switch (op) { switch (op) {
@ -226,29 +225,29 @@ ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> Bi
return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func); return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func);
} }
case OpType::GreaterEqual: { case OpType::GreaterEqual: {
auto index_func = [val](Index* index) { return index->Range(val, Operator::GE); }; auto index_func = [val](Index* index) { return index->Range(val, OpType::GreaterEqual); };
auto elem_func = [val](T x) { return (x >= val); }; auto elem_func = [val](T x) { return (x >= val); };
return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func); return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func);
} }
case OpType::GreaterThan: { case OpType::GreaterThan: {
auto index_func = [val](Index* index) { return index->Range(val, Operator::GT); }; auto index_func = [val](Index* index) { return index->Range(val, OpType::GreaterThan); };
auto elem_func = [val](T x) { return (x > val); }; auto elem_func = [val](T x) { return (x > val); };
return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func); return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func);
} }
case OpType::LessEqual: { case OpType::LessEqual: {
auto index_func = [val](Index* index) { return index->Range(val, Operator::LE); }; auto index_func = [val](Index* index) { return index->Range(val, OpType::LessEqual); };
auto elem_func = [val](T x) { return (x <= val); }; auto elem_func = [val](T x) { return (x <= val); };
return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func); return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func);
} }
case OpType::LessThan: { case OpType::LessThan: {
auto index_func = [val](Index* index) { return index->Range(val, Operator::LT); }; auto index_func = [val](Index* index) { return index->Range(val, OpType::LessThan); };
auto elem_func = [val](T x) { return (x < val); }; auto elem_func = [val](T x) { return (x < val); };
return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func); return ExecRangeVisitorImpl<T>(expr.field_id_, index_func, elem_func);
} }
case OpType::PrefixMatch: { case OpType::PrefixMatch: {
auto index_func = [val](Index* index) { auto index_func = [val](Index* index) {
auto dataset = std::make_unique<knowhere::Dataset>(); auto dataset = std::make_unique<knowhere::Dataset>();
dataset->Set(scalar::OPERATOR_TYPE, Operator::PrefixMatchOp); dataset->Set(scalar::OPERATOR_TYPE, OpType::PrefixMatch);
dataset->Set(scalar::PREFIX_VALUE, val); dataset->Set(scalar::PREFIX_VALUE, val);
return index->Query(std::move(dataset)); return index->Query(std::move(dataset));
}; };
@ -706,7 +705,6 @@ ExecExprVisitor::ExecTermVisitorImpl<std::string>(TermExpr& expr_raw) -> BitsetT
using T = std::string; using T = std::string;
auto& expr = static_cast<TermExprImpl<T>&>(expr_raw); auto& expr = static_cast<TermExprImpl<T>&>(expr_raw);
using Index = scalar::ScalarIndex<T>; using Index = scalar::ScalarIndex<T>;
using Operator = scalar::OperatorType;
const auto& terms = expr.terms_; const auto& terms = expr.terms_;
auto n = terms.size(); auto n = terms.size();
std::unordered_set<T> term_set(expr.terms_.begin(), expr.terms_.end()); std::unordered_set<T> term_set(expr.terms_.begin(), expr.terms_.end());

View File

@ -25,7 +25,7 @@ TEST(Bitmap, Naive) {
auto sort_index = std::make_shared<scalar::ScalarIndexSort<float>>(); auto sort_index = std::make_shared<scalar::ScalarIndexSort<float>>();
sort_index->Build(N, vec.data()); sort_index->Build(N, vec.data());
{ {
auto res = sort_index->Range(0, scalar::OperatorType::LT); auto res = sort_index->Range(0, OpType::LessThan);
double count = res->count(); double count = res->count();
ASSERT_NEAR(count / N, 0.5, 0.01); ASSERT_NEAR(count / N, 0.5, 0.01);
} }

View File

@ -1008,9 +1008,9 @@ testReduceSearchWithExpr(int N, int topK, int num_queries) {
std::vector<CSearchResult> results; std::vector<CSearchResult> results;
CSearchResult res1; CSearchResult res1;
CSearchResult res2; CSearchResult res2;
auto res = Search(segment, plan, placeholderGroup, dataset.timestamps_[0], &res1, -1); auto res = Search(segment, plan, placeholderGroup, dataset.timestamps_[N - 1], &res1, -1);
assert(res.error_code == Success); assert(res.error_code == Success);
res = Search(segment, plan, placeholderGroup, dataset.timestamps_[0], &res2, -1); res = Search(segment, plan, placeholderGroup, dataset.timestamps_[N - 1], &res2, -1);
assert(res.error_code == Success); assert(res.error_code == Success);
results.push_back(res1); results.push_back(res1);
results.push_back(res2); results.push_back(res2);

View File

@ -36,8 +36,9 @@ TEST(Relational, Basic) {
ASSERT_EQ(Relational<decltype(std::greater<>{})>()(s, another_s), s > another_s); ASSERT_EQ(Relational<decltype(std::greater<>{})>()(s, another_s), s > another_s);
ASSERT_EQ(Relational<decltype(std::less_equal<>{})>()(s, another_s), s <= another_s); ASSERT_EQ(Relational<decltype(std::less_equal<>{})>()(s, another_s), s <= another_s);
ASSERT_EQ(Relational<decltype(std::less<>{})>()(s, another_s), s < another_s); ASSERT_EQ(Relational<decltype(std::less<>{})>()(s, another_s), s < another_s);
ASSERT_EQ(Relational<decltype(MatchOp<OpType::PrefixMatch>{})>()(s, another_s), milvus::PrefixMatch(s, another_s)); ASSERT_EQ(Relational<decltype(MatchOp<milvus::OpType::PrefixMatch>{})>()(s, another_s),
ASSERT_EQ(Relational<decltype(MatchOp<OpType::PostfixMatch>{})>()(s, another_s), milvus::PrefixMatch(s, another_s));
ASSERT_EQ(Relational<decltype(MatchOp<milvus::OpType::PostfixMatch>{})>()(s, another_s),
milvus::PostfixMatch(s, another_s)); milvus::PostfixMatch(s, another_s));
} }
@ -67,8 +68,8 @@ TEST(Relational, DifferentInCompatibleType) {
ASSERT_ANY_THROW(Relational<decltype(std::greater<>{})>()(s, i64)); ASSERT_ANY_THROW(Relational<decltype(std::greater<>{})>()(s, i64));
ASSERT_ANY_THROW(Relational<decltype(std::less_equal<>{})>()(s, i64)); ASSERT_ANY_THROW(Relational<decltype(std::less_equal<>{})>()(s, i64));
ASSERT_ANY_THROW(Relational<decltype(std::less<>{})>()(s, i64)); ASSERT_ANY_THROW(Relational<decltype(std::less<>{})>()(s, i64));
ASSERT_ANY_THROW(Relational<decltype(MatchOp<OpType::PrefixMatch>{})>()(s, i64)); ASSERT_ANY_THROW(Relational<decltype(MatchOp<milvus::OpType::PrefixMatch>{})>()(s, i64));
ASSERT_ANY_THROW(Relational<decltype(MatchOp<OpType::PostfixMatch>{})>()(s, i64)); ASSERT_ANY_THROW(Relational<decltype(MatchOp<milvus::OpType::PostfixMatch>{})>()(s, i64));
ASSERT_ANY_THROW(Relational<decltype(std::equal_to<>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(std::equal_to<>{})>()(i64, s));
ASSERT_ANY_THROW(Relational<decltype(std::not_equal_to<>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(std::not_equal_to<>{})>()(i64, s));
@ -76,6 +77,6 @@ TEST(Relational, DifferentInCompatibleType) {
ASSERT_ANY_THROW(Relational<decltype(std::greater<>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(std::greater<>{})>()(i64, s));
ASSERT_ANY_THROW(Relational<decltype(std::less_equal<>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(std::less_equal<>{})>()(i64, s));
ASSERT_ANY_THROW(Relational<decltype(std::less<>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(std::less<>{})>()(i64, s));
ASSERT_ANY_THROW(Relational<decltype(MatchOp<OpType::PrefixMatch>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(MatchOp<milvus::OpType::PrefixMatch>{})>()(i64, s));
ASSERT_ANY_THROW(Relational<decltype(MatchOp<OpType::PostfixMatch>{})>()(i64, s)); ASSERT_ANY_THROW(Relational<decltype(MatchOp<milvus::OpType::PostfixMatch>{})>()(i64, s));
} }

View File

@ -32,7 +32,6 @@ namespace indexcgo = milvus::proto::indexcgo;
namespace schemapb = milvus::proto::schema; namespace schemapb = milvus::proto::schema;
using milvus::indexbuilder::MapParams; using milvus::indexbuilder::MapParams;
using milvus::indexbuilder::ScalarIndexCreatorPtr; using milvus::indexbuilder::ScalarIndexCreatorPtr;
using milvus::scalar::OperatorType;
using ScalarTestParams = std::pair<MapParams, MapParams>; using ScalarTestParams = std::pair<MapParams, MapParams>;
namespace { namespace {

View File

@ -20,7 +20,9 @@
#include "index/ScalarIndex.h" #include "index/ScalarIndex.h"
#include "index/StringIndex.h" #include "index/StringIndex.h"
#include "index/StringIndexMarisa.h" #include "index/StringIndexMarisa.h"
#include "index/IndexFactory.h"
#include "test_utils/indexbuilder_test_utils.h" #include "test_utils/indexbuilder_test_utils.h"
#include "test_utils/AssertUtils.h"
constexpr int64_t nb = 100; constexpr int64_t nb = 100;
namespace schemapb = milvus::proto::schema; namespace schemapb = milvus::proto::schema;
@ -87,7 +89,7 @@ TEST_F(StringIndexMarisaTest, Range) {
auto index = milvus::scalar::CreateStringIndexMarisa(); auto index = milvus::scalar::CreateStringIndexMarisa();
index->BuildWithDataset(str_ds); index->BuildWithDataset(str_ds);
ASSERT_ANY_THROW(index->Range("not important", milvus::scalar::OperatorType::LE)); ASSERT_ANY_THROW(index->Range("not important", milvus::OpType::LessEqual));
ASSERT_ANY_THROW(index->Range("not important", true, "not important", true)); ASSERT_ANY_THROW(index->Range("not important", true, "not important", true));
} }
@ -109,28 +111,28 @@ TEST_F(StringIndexMarisaTest, Query) {
{ {
auto ds = knowhere::GenDataset(strs.size(), 8, strs.data()); auto ds = knowhere::GenDataset(strs.size(), 8, strs.data());
ds->Set<milvus::scalar::OperatorType>(milvus::scalar::OPERATOR_TYPE, milvus::scalar::OperatorType::InOp); ds->Set<milvus::OpType>(milvus::scalar::OPERATOR_TYPE, milvus::OpType::In);
auto bitset = index->Query(ds); auto bitset = index->Query(ds);
ASSERT_TRUE(bitset->any()); ASSERT_TRUE(bitset->any());
} }
{ {
auto ds = knowhere::GenDataset(strs.size(), 8, strs.data()); auto ds = knowhere::GenDataset(strs.size(), 8, strs.data());
ds->Set<milvus::scalar::OperatorType>(milvus::scalar::OPERATOR_TYPE, milvus::scalar::OperatorType::NotInOp); ds->Set<milvus::OpType>(milvus::scalar::OPERATOR_TYPE, milvus::OpType::NotIn);
auto bitset = index->Query(ds); auto bitset = index->Query(ds);
ASSERT_TRUE(bitset->none()); ASSERT_TRUE(bitset->none());
} }
{ {
auto ds = std::make_shared<knowhere::Dataset>(); auto ds = std::make_shared<knowhere::Dataset>();
ds->Set<milvus::scalar::OperatorType>(milvus::scalar::OPERATOR_TYPE, milvus::scalar::OperatorType::GE); ds->Set<milvus::OpType>(milvus::scalar::OPERATOR_TYPE, milvus::OpType::GreaterEqual);
ds->Set<std::string>(milvus::scalar::RANGE_VALUE, "range"); ds->Set<std::string>(milvus::scalar::RANGE_VALUE, "range");
ASSERT_ANY_THROW(index->Query(ds)); ASSERT_ANY_THROW(index->Query(ds));
} }
{ {
auto ds = std::make_shared<knowhere::Dataset>(); auto ds = std::make_shared<knowhere::Dataset>();
ds->Set<milvus::scalar::OperatorType>(milvus::scalar::OPERATOR_TYPE, milvus::scalar::OperatorType::RangeOp); ds->Set<milvus::OpType>(milvus::scalar::OPERATOR_TYPE, milvus::OpType::Range);
ds->Set<std::string>(milvus::scalar::LOWER_BOUND_VALUE, "range"); ds->Set<std::string>(milvus::scalar::LOWER_BOUND_VALUE, "range");
ds->Set<std::string>(milvus::scalar::UPPER_BOUND_VALUE, "range"); ds->Set<std::string>(milvus::scalar::UPPER_BOUND_VALUE, "range");
ds->Set<bool>(milvus::scalar::LOWER_BOUND_INCLUSIVE, true); ds->Set<bool>(milvus::scalar::LOWER_BOUND_INCLUSIVE, true);
@ -141,8 +143,7 @@ TEST_F(StringIndexMarisaTest, Query) {
{ {
for (size_t i = 0; i < strs.size(); i++) { for (size_t i = 0; i < strs.size(); i++) {
auto ds = std::make_shared<knowhere::Dataset>(); auto ds = std::make_shared<knowhere::Dataset>();
ds->Set<milvus::scalar::OperatorType>(milvus::scalar::OPERATOR_TYPE, ds->Set<milvus::OpType>(milvus::scalar::OPERATOR_TYPE, milvus::OpType::PrefixMatch);
milvus::scalar::OperatorType::PrefixMatchOp);
ds->Set<std::string>(milvus::scalar::PREFIX_VALUE, std::move(strs[i])); ds->Set<std::string>(milvus::scalar::PREFIX_VALUE, std::move(strs[i]));
auto bitset = index->Query(ds); auto bitset = index->Query(ds);
ASSERT_EQ(bitset->size(), strs.size()); ASSERT_EQ(bitset->size(), strs.size());
@ -175,7 +176,7 @@ TEST_F(StringIndexMarisaTest, Codec) {
} }
{ {
ASSERT_ANY_THROW(copy_index->Range("not important", milvus::scalar::OperatorType::LE)); ASSERT_ANY_THROW(copy_index->Range("not important", milvus::OpType::LessEqual));
ASSERT_ANY_THROW(copy_index->Range("not important", true, "not important", true)); ASSERT_ANY_THROW(copy_index->Range("not important", true, "not important", true));
} }

View File

@ -53,19 +53,19 @@ assert_range(const ScalarIndexPtr<T>& index, const std::vector<T>& arr) {
auto test_min = arr[0]; auto test_min = arr[0];
auto test_max = arr[arr.size() - 1]; auto test_max = arr[arr.size() - 1];
auto bitset1 = index->Range(test_min - 1, milvus::scalar::OperatorType::GT); auto bitset1 = index->Range(test_min - 1, milvus::OpType::GreaterThan);
ASSERT_EQ(arr.size(), bitset1->size()); ASSERT_EQ(arr.size(), bitset1->size());
ASSERT_TRUE(bitset1->any()); ASSERT_TRUE(bitset1->any());
auto bitset2 = index->Range(test_min, milvus::scalar::OperatorType::GE); auto bitset2 = index->Range(test_min, milvus::OpType::GreaterEqual);
ASSERT_EQ(arr.size(), bitset2->size()); ASSERT_EQ(arr.size(), bitset2->size());
ASSERT_TRUE(bitset2->any()); ASSERT_TRUE(bitset2->any());
auto bitset3 = index->Range(test_max + 1, milvus::scalar::OperatorType::LT); auto bitset3 = index->Range(test_max + 1, milvus::OpType::LessThan);
ASSERT_EQ(arr.size(), bitset3->size()); ASSERT_EQ(arr.size(), bitset3->size());
ASSERT_TRUE(bitset3->any()); ASSERT_TRUE(bitset3->any());
auto bitset4 = index->Range(test_max, milvus::scalar::OperatorType::LE); auto bitset4 = index->Range(test_max, milvus::OpType::LessEqual);
ASSERT_EQ(arr.size(), bitset4->size()); ASSERT_EQ(arr.size(), bitset4->size());
ASSERT_TRUE(bitset4->any()); ASSERT_TRUE(bitset4->any());
@ -96,11 +96,11 @@ assert_range(const ScalarIndexPtr<std::string>& index, const std::vector<std::st
auto test_min = arr[0]; auto test_min = arr[0];
auto test_max = arr[arr.size() - 1]; auto test_max = arr[arr.size() - 1];
auto bitset2 = index->Range(test_min, milvus::scalar::OperatorType::GE); auto bitset2 = index->Range(test_min, milvus::OpType::GreaterEqual);
ASSERT_EQ(arr.size(), bitset2->size()); ASSERT_EQ(arr.size(), bitset2->size());
ASSERT_TRUE(bitset2->any()); ASSERT_TRUE(bitset2->any());
auto bitset4 = index->Range(test_max, milvus::scalar::OperatorType::LE); auto bitset4 = index->Range(test_max, milvus::OpType::LessEqual);
ASSERT_EQ(arr.size(), bitset4->size()); ASSERT_EQ(arr.size(), bitset4->size());
ASSERT_TRUE(bitset4->any()); ASSERT_TRUE(bitset4->any());

View File

@ -43,7 +43,6 @@ namespace indexcgo = milvus::proto::indexcgo;
namespace schemapb = milvus::proto::schema; namespace schemapb = milvus::proto::schema;
using milvus::indexbuilder::MapParams; using milvus::indexbuilder::MapParams;
using milvus::indexbuilder::ScalarIndexCreator; using milvus::indexbuilder::ScalarIndexCreator;
using milvus::scalar::OperatorType;
using ScalarTestParams = std::pair<MapParams, MapParams>; using ScalarTestParams = std::pair<MapParams, MapParams>;
using milvus::scalar::ScalarIndexPtr; using milvus::scalar::ScalarIndexPtr;
using milvus::scalar::StringIndexPtr; using milvus::scalar::StringIndexPtr;

View File

@ -318,7 +318,7 @@ func (replica *SegmentReplica) filterSegments(channelName string, partitionID Un
results := make([]*Segment, 0) results := make([]*Segment, 0)
isMatched := func(segment *Segment, chanName string, partID UniqueID) bool { isMatched := func(segment *Segment, chanName string, partID UniqueID) bool {
return segment.channelName == chanName && (partID == common.InvalidFieldID || segment.partitionID == partID) return segment.channelName == chanName && (partID == common.InvalidPartitionID || segment.partitionID == partID)
} }
for _, seg := range replica.newSegments { for _, seg := range replica.newSegments {
if isMatched(seg, channelName, partitionID) { if isMatched(seg, channelName, partitionID) {

View File

@ -15,6 +15,9 @@ enum OpType {
PrefixMatch = 7; // startsWith PrefixMatch = 7; // startsWith
PostfixMatch = 8; // endsWith PostfixMatch = 8; // endsWith
Match = 9; // like Match = 9; // like
Range = 10; // for case 1 < a < b
In = 11; // TODO:: used for term expr
NotIn = 12;
}; };
enum ArithOpType { enum ArithOpType {

View File

@ -34,19 +34,25 @@ const (
OpType_PrefixMatch OpType = 7 OpType_PrefixMatch OpType = 7
OpType_PostfixMatch OpType = 8 OpType_PostfixMatch OpType = 8
OpType_Match OpType = 9 OpType_Match OpType = 9
OpType_Range OpType = 10
OpType_In OpType = 11
OpType_NotIn OpType = 12
) )
var OpType_name = map[int32]string{ var OpType_name = map[int32]string{
0: "Invalid", 0: "Invalid",
1: "GreaterThan", 1: "GreaterThan",
2: "GreaterEqual", 2: "GreaterEqual",
3: "LessThan", 3: "LessThan",
4: "LessEqual", 4: "LessEqual",
5: "Equal", 5: "Equal",
6: "NotEqual", 6: "NotEqual",
7: "PrefixMatch", 7: "PrefixMatch",
8: "PostfixMatch", 8: "PostfixMatch",
9: "Match", 9: "Match",
10: "Range",
11: "In",
12: "NotIn",
} }
var OpType_value = map[string]int32{ var OpType_value = map[string]int32{
@ -60,6 +66,9 @@ var OpType_value = map[string]int32{
"PrefixMatch": 7, "PrefixMatch": 7,
"PostfixMatch": 8, "PostfixMatch": 8,
"Match": 9, "Match": 9,
"Range": 10,
"In": 11,
"NotIn": 12,
} }
func (x OpType) String() string { func (x OpType) String() string {
@ -1371,92 +1380,93 @@ func init() {
func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) }
var fileDescriptor_2d655ab2f7683c23 = []byte{ var fileDescriptor_2d655ab2f7683c23 = []byte{
// 1387 bytes of a gzipped FileDescriptorProto // 1407 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcd, 0x73, 0xdb, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x57, 0xcd, 0x72, 0xdc, 0x44,
0x14, 0xb7, 0x2c, 0x3b, 0x96, 0x9e, 0x1d, 0x47, 0xd5, 0x85, 0x7e, 0xd0, 0x26, 0x88, 0x0e, 0x0d, 0x10, 0x5e, 0xad, 0x76, 0xbd, 0x52, 0xef, 0x7a, 0xad, 0xe8, 0x42, 0x7e, 0x48, 0x6c, 0x44, 0x8a,
0x65, 0x9a, 0x4c, 0x69, 0x69, 0xa7, 0x65, 0x0a, 0xf9, 0x2a, 0x49, 0x86, 0x36, 0x09, 0x6a, 0x9a, 0x98, 0x50, 0xb1, 0x2b, 0x24, 0x24, 0x95, 0x50, 0x01, 0xff, 0x05, 0x7b, 0x8b, 0xc4, 0x36, 0x8a,
0x03, 0x17, 0xcd, 0x5a, 0xda, 0xd8, 0x3b, 0x95, 0xb5, 0xea, 0x6a, 0xe5, 0xd6, 0x67, 0x6e, 0xdc, 0xe3, 0x03, 0x17, 0xd5, 0xac, 0x34, 0xf6, 0x4e, 0x45, 0xab, 0x51, 0x46, 0xa3, 0x4d, 0xf6, 0xcc,
0xb8, 0xc3, 0x15, 0xee, 0xdc, 0x38, 0xf1, 0x0f, 0x70, 0xe0, 0xc8, 0x9d, 0xff, 0x82, 0x13, 0xb3, 0x8d, 0x1b, 0x0f, 0xc0, 0x15, 0xee, 0xdc, 0xe0, 0xc2, 0x0b, 0x70, 0xe0, 0xc8, 0x9d, 0xb7, 0xe0,
0x6f, 0xe5, 0xaf, 0x8e, 0xdd, 0x38, 0x43, 0x67, 0xb8, 0xed, 0xbe, 0x7d, 0xef, 0xb7, 0xef, 0xfd, 0x44, 0x4d, 0x8f, 0xf6, 0x2f, 0xb5, 0x1b, 0xaf, 0x8b, 0x54, 0x71, 0x1b, 0xf5, 0x74, 0x7f, 0xd3,
0xf6, 0xed, 0xdb, 0xb7, 0x00, 0x69, 0x4c, 0x92, 0xb5, 0x54, 0x70, 0xc9, 0xdd, 0x0b, 0x5d, 0x16, 0xfd, 0x4d, 0x77, 0x4f, 0x0b, 0x20, 0x8d, 0x49, 0xb2, 0x96, 0x0a, 0x2e, 0xb9, 0x7b, 0xa1, 0xcb,
0xf7, 0xf2, 0x4c, 0xcf, 0xd6, 0xd4, 0xc2, 0xe5, 0x46, 0x16, 0x76, 0x68, 0x97, 0x68, 0x91, 0xf7, 0xe2, 0x5e, 0x9e, 0xe9, 0xaf, 0x35, 0xb5, 0x71, 0xb9, 0x91, 0x85, 0x1d, 0xda, 0x25, 0x5a, 0xe4,
0x83, 0x01, 0x8d, 0x5d, 0x9a, 0x50, 0xc1, 0xc2, 0x13, 0x12, 0xe7, 0xd4, 0xbd, 0x02, 0x56, 0x8b, 0xfd, 0x60, 0x40, 0x63, 0x97, 0x26, 0x54, 0xb0, 0xf0, 0x98, 0xc4, 0x39, 0x75, 0xaf, 0x80, 0xd5,
0xf3, 0x38, 0xe8, 0x91, 0xf8, 0xa2, 0xb1, 0x62, 0xac, 0x5a, 0x7b, 0x25, 0xbf, 0xa6, 0x24, 0x27, 0xe6, 0x3c, 0x0e, 0x7a, 0x24, 0xbe, 0x68, 0xac, 0x18, 0xab, 0xd6, 0x5e, 0xc9, 0xaf, 0x29, 0xc9,
0x24, 0x76, 0xaf, 0x82, 0xcd, 0x12, 0x79, 0xef, 0x2e, 0xae, 0x96, 0x57, 0x8c, 0x55, 0x73, 0xaf, 0x31, 0x89, 0xdd, 0xab, 0x60, 0xb3, 0x44, 0xde, 0xbb, 0x8b, 0xbb, 0xe5, 0x15, 0x63, 0xd5, 0xdc,
0xe4, 0x5b, 0x28, 0x2a, 0x96, 0x4f, 0x63, 0x4e, 0x24, 0x2e, 0x9b, 0x2b, 0xc6, 0xaa, 0xa1, 0x96, 0x2b, 0xf9, 0x16, 0x8a, 0x8a, 0xed, 0x93, 0x98, 0x13, 0x89, 0xdb, 0xe6, 0x8a, 0xb1, 0x6a, 0xa8,
0x51, 0xa4, 0x96, 0x97, 0x01, 0x32, 0x29, 0x58, 0xd2, 0xc6, 0xf5, 0xca, 0x8a, 0xb1, 0x6a, 0xef, 0x6d, 0x14, 0xa9, 0xed, 0x65, 0x80, 0x4c, 0x0a, 0x96, 0x9c, 0xe2, 0x7e, 0x65, 0xc5, 0x58, 0xb5,
0x95, 0x7c, 0x5b, 0xcb, 0x4e, 0x48, 0xbc, 0x55, 0x05, 0xb3, 0x47, 0x62, 0xef, 0x7b, 0x03, 0xec, 0xf7, 0x4a, 0xbe, 0xad, 0x65, 0xc7, 0x24, 0xde, 0xaa, 0x82, 0xd9, 0x23, 0xb1, 0xf7, 0xbd, 0x01,
0x6f, 0x72, 0x2a, 0xfa, 0xfb, 0xc9, 0x29, 0x77, 0x5d, 0xa8, 0x48, 0x9e, 0xbe, 0x40, 0x67, 0x4c, 0xf6, 0x37, 0x39, 0x15, 0xfd, 0x56, 0x72, 0xc2, 0x5d, 0x17, 0x2a, 0x92, 0xa7, 0x2f, 0xd0, 0x19,
0x1f, 0xc7, 0xee, 0x32, 0xd4, 0xbb, 0x54, 0x0a, 0x16, 0x06, 0xb2, 0x9f, 0x52, 0xdc, 0xca, 0xf6, 0xd3, 0xc7, 0xb5, 0xbb, 0x0c, 0xf5, 0x2e, 0x95, 0x82, 0x85, 0x81, 0xec, 0xa7, 0x14, 0x8f, 0xb2,
0x41, 0x8b, 0x8e, 0xfb, 0x29, 0x75, 0x3f, 0x84, 0xc5, 0x8c, 0x12, 0x11, 0x76, 0x82, 0x94, 0x08, 0x7d, 0xd0, 0xa2, 0xa3, 0x7e, 0x4a, 0xdd, 0x0f, 0x61, 0x31, 0xa3, 0x44, 0x84, 0x9d, 0x20, 0x25,
0xd2, 0xcd, 0xf4, 0x6e, 0x7e, 0x43, 0x0b, 0x8f, 0x50, 0xa6, 0x94, 0x04, 0xcf, 0x93, 0x28, 0x88, 0x82, 0x74, 0x33, 0x7d, 0x9a, 0xdf, 0xd0, 0xc2, 0x43, 0x94, 0x29, 0x25, 0xc1, 0xf3, 0x24, 0x0a,
0x68, 0xc8, 0xba, 0x24, 0xbe, 0x58, 0xc5, 0x2d, 0x1a, 0x28, 0xdc, 0xd1, 0x32, 0xef, 0x67, 0x03, 0x22, 0x1a, 0xb2, 0x2e, 0x89, 0x2f, 0x56, 0xf1, 0x88, 0x06, 0x0a, 0x77, 0xb4, 0xcc, 0xfb, 0xc9,
0x60, 0x9b, 0xc7, 0x79, 0x37, 0x41, 0x6f, 0x2e, 0x81, 0x75, 0xca, 0x68, 0x1c, 0x05, 0x2c, 0x2a, 0x00, 0xd8, 0xe6, 0x71, 0xde, 0x4d, 0xd0, 0x9b, 0x4b, 0x60, 0x9d, 0x30, 0x1a, 0x47, 0x01, 0x8b,
0x3c, 0xaa, 0xe1, 0x7c, 0x3f, 0x72, 0x1f, 0x82, 0x1d, 0x11, 0x49, 0xb4, 0x4b, 0x8a, 0x9c, 0xe6, 0x0a, 0x8f, 0x6a, 0xf8, 0xdd, 0x8a, 0xdc, 0x87, 0x60, 0x47, 0x44, 0x12, 0xed, 0x92, 0x22, 0xa7,
0xa7, 0x57, 0xd7, 0x26, 0xf8, 0x2f, 0x98, 0xdf, 0x21, 0x92, 0x28, 0x2f, 0x7d, 0x2b, 0x2a, 0x46, 0xf9, 0xe9, 0xd5, 0xb5, 0x09, 0xfe, 0x0b, 0xe6, 0x77, 0x88, 0x24, 0xca, 0x4b, 0xdf, 0x8a, 0x8a,
0xee, 0x75, 0x68, 0xb2, 0x2c, 0x48, 0x05, 0xeb, 0x12, 0xd1, 0x0f, 0x5e, 0xd0, 0x3e, 0xc6, 0x64, 0x95, 0x7b, 0x1d, 0x9a, 0x2c, 0x0b, 0x52, 0xc1, 0xba, 0x44, 0xf4, 0x83, 0x17, 0xb4, 0x8f, 0x31,
0xf9, 0x0d, 0x96, 0x1d, 0x69, 0xe1, 0xd7, 0xb4, 0xef, 0x5e, 0x01, 0x9b, 0x65, 0x01, 0xc9, 0x25, 0x59, 0x7e, 0x83, 0x65, 0x87, 0x5a, 0xf8, 0x35, 0xed, 0xbb, 0x57, 0xc0, 0x66, 0x59, 0x40, 0x72,
0xdf, 0xdf, 0xc1, 0x88, 0x2c, 0xdf, 0x62, 0xd9, 0x26, 0xce, 0xbd, 0x2f, 0x07, 0x7e, 0x3e, 0x7e, 0xc9, 0x5b, 0x3b, 0x18, 0x91, 0xe5, 0x5b, 0x2c, 0xdb, 0xc4, 0x6f, 0xef, 0xcb, 0x81, 0x9f, 0x8f,
0x9d, 0x0a, 0xf7, 0x36, 0x54, 0x58, 0x72, 0xca, 0xd1, 0xc7, 0xfa, 0x9b, 0x7e, 0x60, 0x82, 0x8c, 0x5f, 0xa7, 0xc2, 0xbd, 0x0d, 0x15, 0x96, 0x9c, 0x70, 0xf4, 0xb1, 0xfe, 0xa6, 0x1f, 0x98, 0x20,
0x82, 0xf2, 0x51, 0xd5, 0xdb, 0x02, 0x1b, 0x53, 0x00, 0xed, 0x3f, 0x83, 0x6a, 0x4f, 0x4d, 0x0a, 0xa3, 0xa0, 0x7c, 0x54, 0xf5, 0xb6, 0xc0, 0xc6, 0x14, 0x40, 0xfb, 0xcf, 0xa0, 0xda, 0x53, 0x1f,
0x80, 0xe5, 0x29, 0x00, 0xe3, 0x69, 0xe3, 0x6b, 0x6d, 0xef, 0x57, 0x03, 0x9a, 0xcf, 0x13, 0x22, 0x05, 0xc0, 0xf2, 0x14, 0x80, 0xf1, 0xb4, 0xf1, 0xb5, 0xb6, 0xf7, 0x8b, 0x01, 0xcd, 0xe7, 0x09,
0xfa, 0x3e, 0x49, 0xda, 0x1a, 0xe9, 0x0b, 0xa8, 0x87, 0xb8, 0x55, 0x30, 0xbf, 0x43, 0x10, 0x8e, 0x11, 0x7d, 0x9f, 0x24, 0xa7, 0x1a, 0xe9, 0x0b, 0xa8, 0x87, 0x78, 0x54, 0x30, 0xbf, 0x43, 0x10,
0x18, 0xff, 0x18, 0xca, 0x3c, 0x2d, 0xf8, 0xbc, 0x34, 0xc5, 0xec, 0x30, 0x45, 0x2e, 0xcb, 0x3c, 0x8e, 0x18, 0xff, 0x18, 0xca, 0x3c, 0x2d, 0xf8, 0xbc, 0x34, 0xc5, 0xec, 0x20, 0x45, 0x2e, 0xcb,
0x1d, 0x39, 0x6d, 0x9e, 0xcb, 0xe9, 0x5f, 0xca, 0xb0, 0xb4, 0xc5, 0xde, 0xad, 0xd7, 0x37, 0x60, 0x3c, 0x1d, 0x39, 0x6d, 0x9e, 0xcb, 0xe9, 0x9f, 0xcb, 0xb0, 0xb4, 0xc5, 0xde, 0xad, 0xd7, 0x37,
0x29, 0xe6, 0xaf, 0xa8, 0x08, 0x58, 0x12, 0xc6, 0x79, 0xc6, 0x7a, 0x3a, 0x25, 0x2c, 0xbf, 0x89, 0x60, 0x29, 0xe6, 0xaf, 0xa8, 0x08, 0x58, 0x12, 0xc6, 0x79, 0xc6, 0x7a, 0x3a, 0x25, 0x2c, 0xbf,
0xe2, 0xfd, 0x81, 0x54, 0x29, 0xe6, 0x69, 0x3a, 0xa1, 0xa8, 0x8f, 0xbe, 0x89, 0xe2, 0x91, 0xe2, 0x89, 0xe2, 0xd6, 0x40, 0xaa, 0x14, 0xf3, 0x34, 0x9d, 0x50, 0xd4, 0x57, 0xdf, 0x44, 0xf1, 0x48,
0x06, 0xd4, 0x35, 0xa2, 0x0e, 0xb1, 0x32, 0x5f, 0x88, 0x80, 0x36, 0xfa, 0x6a, 0x6f, 0x40, 0x5d, 0x71, 0x03, 0xea, 0x1a, 0x51, 0x87, 0x58, 0x99, 0x2f, 0x44, 0x40, 0x1b, 0x5d, 0xda, 0x1b, 0x50,
0x6f, 0xa5, 0x11, 0xaa, 0x73, 0x22, 0xa0, 0x0d, 0x8e, 0xbd, 0x3f, 0x0c, 0xa8, 0x6f, 0xf3, 0x6e, 0xd7, 0x47, 0x69, 0x84, 0xea, 0x9c, 0x08, 0x68, 0x83, 0x6b, 0xef, 0x0f, 0x03, 0xea, 0xdb, 0xbc,
0x4a, 0x84, 0x66, 0x69, 0x17, 0x9c, 0x98, 0x9e, 0xca, 0xe0, 0xdc, 0x54, 0x35, 0x95, 0xd9, 0xd8, 0x9b, 0x12, 0xa1, 0x59, 0xda, 0x05, 0x27, 0xa6, 0x27, 0x32, 0x38, 0x37, 0x55, 0x4d, 0x65, 0x36,
0xb5, 0xda, 0x87, 0x0b, 0x82, 0xb5, 0x3b, 0x93, 0x48, 0xe5, 0x79, 0x90, 0x96, 0xd0, 0x6e, 0xfb, 0x56, 0x56, 0x2d, 0xb8, 0x20, 0xd8, 0x69, 0x67, 0x12, 0xa9, 0x3c, 0x0f, 0xd2, 0x12, 0xda, 0x6d,
0xcd, 0x7c, 0x31, 0xe7, 0xc8, 0x17, 0xef, 0x3b, 0x03, 0xac, 0x63, 0x2a, 0xba, 0xef, 0xe4, 0xc4, 0xbf, 0x99, 0x2f, 0xe6, 0x1c, 0xf9, 0xe2, 0x7d, 0x67, 0x80, 0x75, 0x44, 0x45, 0xf7, 0x9d, 0xdc,
0xef, 0xc3, 0x02, 0xf2, 0x9a, 0x5d, 0x2c, 0xaf, 0x98, 0xf3, 0x10, 0x5b, 0xa8, 0xab, 0x12, 0x6c, 0xf8, 0x7d, 0x58, 0x40, 0x5e, 0xb3, 0x8b, 0xe5, 0x15, 0x73, 0x1e, 0x62, 0x0b, 0x75, 0xd5, 0x82,
0xe3, 0x9d, 0x41, 0x37, 0xee, 0xa2, 0xfb, 0x06, 0xba, 0x7f, 0x7d, 0x0a, 0xc4, 0x50, 0x53, 0x8f, 0x6d, 0xac, 0x19, 0x74, 0xe3, 0x2e, 0xba, 0x6f, 0xa0, 0xfb, 0xd7, 0xa7, 0x40, 0x0c, 0x35, 0xf5,
0x0e, 0x53, 0xcc, 0xfc, 0x5b, 0x50, 0x0d, 0x3b, 0x2c, 0x8e, 0x0a, 0xce, 0xde, 0x9b, 0x62, 0xa8, 0xea, 0x20, 0xc5, 0xcc, 0xbf, 0x05, 0xd5, 0xb0, 0xc3, 0xe2, 0xa8, 0xe0, 0xec, 0xbd, 0x29, 0x86,
0x6c, 0x7c, 0xad, 0xe5, 0x2d, 0x43, 0xad, 0xb0, 0x76, 0xeb, 0x50, 0xdb, 0x4f, 0x7a, 0x24, 0x66, 0xca, 0xc6, 0xd7, 0x5a, 0xde, 0x32, 0xd4, 0x0a, 0x6b, 0xb7, 0x0e, 0xb5, 0x56, 0xd2, 0x23, 0x31,
0x91, 0x53, 0x72, 0x6b, 0x60, 0x1e, 0x70, 0xe9, 0x18, 0xde, 0x5f, 0x06, 0x80, 0xbe, 0x12, 0xe8, 0x8b, 0x9c, 0x92, 0x5b, 0x03, 0x73, 0x9f, 0x4b, 0xc7, 0xf0, 0xfe, 0x32, 0x00, 0x74, 0x49, 0xa0,
0xd4, 0xbd, 0x31, 0xa7, 0x3e, 0x9a, 0x82, 0x3d, 0x52, 0x2d, 0x86, 0x85, 0x5b, 0x9f, 0x40, 0x45, 0x53, 0xf7, 0xc6, 0x9c, 0xfa, 0x68, 0x0a, 0xf6, 0x48, 0xb5, 0x58, 0x16, 0x6e, 0x7d, 0x02, 0x15,
0x1d, 0xf4, 0x59, 0x5e, 0xa1, 0x92, 0x8a, 0x01, 0xcf, 0xb2, 0xb8, 0xbd, 0xb3, 0x63, 0x40, 0x2d, 0x75, 0xd1, 0x67, 0x79, 0x85, 0x4a, 0x2a, 0x06, 0xbc, 0xcb, 0xa2, 0x7a, 0x67, 0xc7, 0x80, 0x5a,
0xef, 0x1e, 0x58, 0x83, 0xbd, 0x26, 0x83, 0x68, 0x02, 0x3c, 0xe1, 0x6d, 0x16, 0x92, 0x78, 0x33, 0xde, 0x3d, 0xb0, 0x06, 0x67, 0x4d, 0x06, 0xd1, 0x04, 0x78, 0xc2, 0x4f, 0x59, 0x48, 0xe2, 0xcd,
0x89, 0x1c, 0xc3, 0x5d, 0x04, 0xbb, 0x98, 0x1f, 0x0a, 0xa7, 0xec, 0xfd, 0x69, 0xc0, 0xa2, 0x36, 0x24, 0x72, 0x0c, 0x77, 0x11, 0xec, 0xe2, 0xfb, 0x40, 0x38, 0x65, 0xef, 0x4f, 0x03, 0x16, 0xb5,
0xdc, 0x14, 0x4c, 0x76, 0x0e, 0xd3, 0xff, 0x7c, 0xf2, 0x0f, 0xc0, 0x22, 0x0a, 0x2a, 0x18, 0xd6, 0xe1, 0xa6, 0x60, 0xb2, 0x73, 0x90, 0xfe, 0xe7, 0x9b, 0x7f, 0x00, 0x16, 0x51, 0x50, 0xc1, 0xb0,
0xa9, 0x6b, 0x53, 0x8c, 0x8b, 0xdd, 0x30, 0xf9, 0x6a, 0xa4, 0xd8, 0x7a, 0x07, 0x16, 0x75, 0xde, 0x4f, 0x5d, 0x9b, 0x62, 0x5c, 0x9c, 0x86, 0xc9, 0x57, 0x23, 0xc5, 0xd1, 0x3b, 0xb0, 0xa8, 0xf3,
0xf3, 0x94, 0x0a, 0x92, 0x44, 0xf3, 0x56, 0xae, 0x06, 0x5a, 0x1d, 0x6a, 0x23, 0xef, 0x27, 0x63, 0x9e, 0xa7, 0x54, 0x90, 0x24, 0x9a, 0xb7, 0x73, 0x35, 0xd0, 0xea, 0x40, 0x1b, 0x79, 0x3f, 0x1a,
0x50, 0xc0, 0x70, 0x13, 0x3c, 0xb2, 0x01, 0xf5, 0xc6, 0xb9, 0xa8, 0x2f, 0xcf, 0x43, 0xbd, 0xbb, 0x83, 0x06, 0x86, 0x87, 0xe0, 0x95, 0x0d, 0xa8, 0x37, 0xce, 0x45, 0x7d, 0x79, 0x1e, 0xea, 0xdd,
0x36, 0x76, 0xc5, 0xce, 0x0a, 0x55, 0xdd, 0xb3, 0xdf, 0xcb, 0x70, 0x79, 0x82, 0xf2, 0xc7, 0x3d, 0xb5, 0xb1, 0x12, 0x3b, 0x2b, 0x54, 0x55, 0x67, 0xbf, 0x97, 0xe1, 0xf2, 0x04, 0xe5, 0x8f, 0x7b,
0x12, 0xbf, 0xbb, 0x5a, 0xfb, 0x7f, 0xf3, 0x5f, 0x94, 0x9c, 0xca, 0xb9, 0x9e, 0xa8, 0xea, 0xb9, 0x24, 0x7e, 0x77, 0xbd, 0xf6, 0xff, 0xe6, 0xbf, 0x68, 0x39, 0x95, 0x73, 0x3d, 0x51, 0xd5, 0x73,
0x9e, 0xa8, 0x7f, 0xaa, 0x50, 0x41, 0xae, 0x1e, 0x82, 0x2d, 0xa9, 0xe8, 0x06, 0xf4, 0x75, 0x2a, 0x3d, 0x51, 0xff, 0x54, 0xa1, 0x82, 0x5c, 0x3d, 0x04, 0x5b, 0x52, 0xd1, 0x0d, 0xe8, 0xeb, 0x54,
0x0a, 0xa6, 0xae, 0x4c, 0xc1, 0x18, 0x54, 0x35, 0xd5, 0x7f, 0xc9, 0x41, 0x85, 0x7b, 0x04, 0x90, 0x14, 0x4c, 0x5d, 0x99, 0x82, 0x31, 0xe8, 0x6a, 0x6a, 0xfe, 0x92, 0x83, 0x0e, 0xf7, 0x08, 0x20,
0xab, 0x43, 0xd0, 0xc6, 0xfa, 0xa8, 0xdf, 0x7f, 0x5b, 0x89, 0x51, 0xdd, 0x59, 0x3e, 0x2c, 0x02, 0x57, 0x97, 0xa0, 0x8d, 0xf5, 0x55, 0xbf, 0xff, 0xb6, 0x16, 0xa3, 0xa6, 0xb3, 0x7c, 0xd8, 0x04,
0x1b, 0x50, 0x6f, 0xb1, 0x91, 0xbd, 0x39, 0xf3, 0x98, 0x46, 0xd5, 0x60, 0xaf, 0xe4, 0x43, 0x6b, 0x36, 0xa0, 0xde, 0x66, 0x23, 0x7b, 0x73, 0xe6, 0x35, 0x8d, 0xba, 0xc1, 0x5e, 0xc9, 0x87, 0xf6,
0x54, 0x46, 0xb6, 0xa1, 0x11, 0xea, 0xd7, 0x43, 0x43, 0xe8, 0x37, 0xec, 0xda, 0xd4, 0x93, 0x1e, 0xa8, 0x8d, 0x6c, 0x43, 0x23, 0xd4, 0xaf, 0x87, 0x86, 0xd0, 0x6f, 0xd8, 0xb5, 0xa9, 0x37, 0x3d,
0x3e, 0x32, 0x7b, 0x25, 0xbf, 0x1e, 0x8e, 0xbd, 0x39, 0x4f, 0xc1, 0xd1, 0x51, 0x08, 0x95, 0x40, 0x7c, 0x64, 0xf6, 0x4a, 0x7e, 0x3d, 0x1c, 0x7b, 0x73, 0x9e, 0x82, 0xa3, 0xa3, 0x10, 0x2a, 0x81,
0x1a, 0x48, 0x93, 0xf9, 0xc1, 0xac, 0x58, 0x86, 0xa9, 0xb6, 0x57, 0xf2, 0x9b, 0xf9, 0xe4, 0x43, 0x34, 0x90, 0x26, 0xf3, 0x83, 0x59, 0xb1, 0x0c, 0x53, 0x6d, 0xaf, 0xe4, 0x37, 0xf3, 0xc9, 0x87,
0x7f, 0x04, 0x17, 0x8a, 0xa8, 0xc6, 0xf0, 0x16, 0x10, 0xcf, 0x9b, 0x19, 0xdb, 0x38, 0xe0, 0x52, 0xfe, 0x10, 0x2e, 0x14, 0x51, 0x8d, 0xe1, 0x2d, 0x20, 0x9e, 0x37, 0x33, 0xb6, 0x71, 0xc0, 0xa5,
0xeb, 0x8d, 0xd6, 0x41, 0xc2, 0x72, 0x81, 0x38, 0xc8, 0xca, 0x80, 0xf6, 0x48, 0x3c, 0x8e, 0x5f, 0xf6, 0x1b, 0xa3, 0x83, 0x84, 0xe5, 0x02, 0x71, 0x90, 0x95, 0x01, 0xed, 0x91, 0x78, 0x1c, 0xbf,
0x43, 0xfc, 0x5b, 0x33, 0xf1, 0xa7, 0x5d, 0x93, 0xbd, 0x92, 0x7f, 0xb9, 0x35, 0xfb, 0x12, 0x8d, 0x86, 0xf8, 0xb7, 0x66, 0xe2, 0x4f, 0x2b, 0x93, 0xbd, 0x92, 0x7f, 0xb9, 0x3d, 0xbb, 0x88, 0x46,
0xe2, 0xd0, 0xbb, 0xe2, 0x3e, 0xd6, 0x19, 0x71, 0x0c, 0xcb, 0xc5, 0x28, 0x8e, 0x51, 0x05, 0x79, 0x71, 0xe8, 0x53, 0xf1, 0x1c, 0xeb, 0x8c, 0x38, 0x86, 0xed, 0x62, 0x14, 0xc7, 0xa8, 0x83, 0x3c,
0x04, 0x80, 0xc9, 0xa7, 0xa1, 0xec, 0x99, 0xe9, 0x32, 0x6c, 0x1a, 0x55, 0xba, 0xf4, 0x86, 0x1d, 0x02, 0xc0, 0xe4, 0xd3, 0x50, 0xf6, 0xcc, 0x74, 0x19, 0x0e, 0x8d, 0x2a, 0x5d, 0x7a, 0xc3, 0x09,
0xe4, 0xc6, 0xf0, 0x56, 0xa3, 0x3d, 0x9c, 0x71, 0xab, 0x07, 0xe9, 0x12, 0x0e, 0x67, 0x5b, 0x0b, 0x72, 0x63, 0x58, 0xd5, 0x68, 0x0f, 0x67, 0x54, 0xf5, 0x20, 0x5d, 0xc2, 0xe1, 0xd7, 0xd6, 0x02,
0x50, 0x51, 0xa6, 0xde, 0xdf, 0x06, 0xc0, 0x09, 0x0d, 0x25, 0x17, 0x9b, 0x07, 0x07, 0xcf, 0x8a, 0x54, 0x94, 0xa9, 0xf7, 0xb7, 0x01, 0x70, 0x4c, 0x43, 0xc9, 0xc5, 0xe6, 0xfe, 0xfe, 0xb3, 0x62,
0x2e, 0x58, 0x7b, 0xab, 0xbf, 0x28, 0xaa, 0x0b, 0xd6, 0x01, 0x4d, 0xf4, 0xe7, 0xe5, 0xc9, 0xfe, 0x0a, 0xd6, 0xde, 0xea, 0x5f, 0x14, 0x35, 0x05, 0xeb, 0x80, 0x26, 0xe6, 0xf3, 0xf2, 0xe4, 0x7c,
0xfc, 0x3e, 0x40, 0x2a, 0x68, 0xc4, 0x42, 0x22, 0x69, 0x76, 0xd6, 0x23, 0x33, 0xa6, 0xea, 0x7e, 0x7e, 0x1f, 0x20, 0x15, 0x34, 0x62, 0x21, 0x91, 0x34, 0x3b, 0xeb, 0x91, 0x19, 0x53, 0x75, 0x3f,
0x0e, 0xf0, 0x52, 0x7d, 0x47, 0x74, 0x79, 0xaa, 0xcc, 0x24, 0x62, 0xf8, 0x67, 0xf1, 0xed, 0x97, 0x07, 0x78, 0xa9, 0x7e, 0x47, 0x74, 0x7b, 0xaa, 0xcc, 0x24, 0x62, 0xf8, 0xcf, 0xe2, 0xdb, 0x2f,
0xc3, 0xef, 0xcb, 0x0d, 0x58, 0x4a, 0x63, 0x12, 0xd2, 0x0e, 0x8f, 0x23, 0x2a, 0x02, 0x49, 0xda, 0x87, 0xbf, 0x2f, 0x37, 0x60, 0x29, 0x8d, 0x49, 0x48, 0x3b, 0x3c, 0x8e, 0xa8, 0x08, 0x24, 0x39,
0x98, 0xad, 0xb6, 0xdf, 0x1c, 0x13, 0x1f, 0x93, 0xb6, 0xf7, 0x9b, 0x01, 0xd6, 0x51, 0x4c, 0x92, 0xc5, 0x6c, 0xb5, 0xfd, 0xe6, 0x98, 0xf8, 0x88, 0x9c, 0x7a, 0xbf, 0x1a, 0x60, 0x1d, 0xc6, 0x24,
0x03, 0x1e, 0x61, 0xab, 0xd6, 0xc3, 0x88, 0x03, 0x92, 0x24, 0xd9, 0x5b, 0x4a, 0xe2, 0x88, 0x17, 0xd9, 0xe7, 0x11, 0x8e, 0x6a, 0x3d, 0x8c, 0x38, 0x20, 0x49, 0x92, 0xbd, 0xa5, 0x25, 0x8e, 0x78,
0x45, 0x9e, 0xb6, 0xd9, 0x4c, 0x92, 0xcc, 0x7d, 0x30, 0x11, 0xed, 0xdb, 0xeb, 0xba, 0x32, 0x1d, 0x51, 0xe4, 0x69, 0x9b, 0xcd, 0x24, 0xc9, 0xdc, 0x07, 0x13, 0xd1, 0xbe, 0xbd, 0xaf, 0x2b, 0xd3,
0x8b, 0x77, 0x15, 0x1c, 0x9e, 0xcb, 0x34, 0x97, 0xc1, 0x80, 0x4a, 0x45, 0x97, 0xb9, 0x6a, 0xfa, 0xb1, 0x78, 0x57, 0xc1, 0xe1, 0xb9, 0x4c, 0x73, 0x19, 0x0c, 0xa8, 0x54, 0x74, 0x99, 0xab, 0xa6,
0x4d, 0x2d, 0xff, 0x4a, 0x33, 0x9a, 0xa9, 0x13, 0x4a, 0x78, 0x44, 0x6f, 0xfe, 0x68, 0xc0, 0x82, 0xdf, 0xd4, 0xf2, 0xaf, 0x34, 0xa3, 0x99, 0xba, 0xa1, 0x84, 0x47, 0xf4, 0xe6, 0x6f, 0x06, 0x2c,
0x2e, 0x72, 0x93, 0x4f, 0xf1, 0x12, 0xd4, 0x77, 0x05, 0x25, 0x92, 0x8a, 0xe3, 0x0e, 0x49, 0x1c, 0xe8, 0x26, 0x37, 0xf9, 0x14, 0x2f, 0x41, 0x7d, 0x57, 0x50, 0x22, 0xa9, 0x38, 0xea, 0x90, 0xc4,
0xc3, 0x75, 0xa0, 0x51, 0x08, 0x1e, 0xbf, 0xcc, 0x49, 0xec, 0x94, 0xdd, 0x06, 0x58, 0x4f, 0x68, 0x31, 0x5c, 0x07, 0x1a, 0x85, 0xe0, 0xf1, 0xcb, 0x9c, 0xc4, 0x4e, 0xd9, 0x6d, 0x80, 0xf5, 0x84,
0x96, 0xe1, 0xba, 0x89, 0x6f, 0x35, 0xcd, 0x32, 0xbd, 0x58, 0x71, 0x6d, 0xa8, 0xea, 0x61, 0x55, 0x66, 0x19, 0xee, 0x9b, 0xf8, 0x56, 0xd3, 0x2c, 0xd3, 0x9b, 0x15, 0xd7, 0x86, 0xaa, 0x5e, 0x56,
0xe9, 0x1d, 0x70, 0xa9, 0x67, 0x0b, 0x0a, 0xf8, 0x48, 0xd0, 0x53, 0xf6, 0xfa, 0x29, 0x91, 0x61, 0x95, 0xde, 0x3e, 0x97, 0xfa, 0x6b, 0x41, 0x01, 0x1f, 0x0a, 0x7a, 0xc2, 0x5e, 0x3f, 0x25, 0x32,
0xc7, 0xa9, 0x29, 0xe0, 0x23, 0x9e, 0xc9, 0xa1, 0xc4, 0x52, 0xb6, 0x7a, 0x68, 0xdf, 0xdc, 0x85, 0xec, 0x38, 0x35, 0x05, 0x7c, 0xc8, 0x33, 0x39, 0x94, 0x58, 0xca, 0x56, 0x2f, 0x6d, 0xb5, 0xc4,
0xfa, 0x58, 0xf5, 0x57, 0x2e, 0x3e, 0x4f, 0x5e, 0x24, 0xfc, 0x55, 0xa2, 0x5b, 0x9e, 0xcd, 0x48, 0x42, 0x71, 0xc0, 0x5d, 0x80, 0x72, 0x2b, 0x71, 0xea, 0x4a, 0xb4, 0xcf, 0x65, 0x2b, 0x71, 0x1a,
0xb5, 0x09, 0x35, 0x30, 0x9f, 0xe5, 0x2d, 0xa7, 0xac, 0x06, 0x4f, 0xf3, 0xd8, 0x31, 0xd5, 0x60, 0x37, 0x77, 0xa1, 0x3e, 0xf6, 0x36, 0xa8, 0x00, 0x9e, 0x27, 0x2f, 0x12, 0xfe, 0x2a, 0xd1, 0x03,
0x87, 0xf5, 0x9c, 0x0a, 0x4a, 0x78, 0xe4, 0x54, 0xb7, 0xee, 0x7c, 0x7b, 0xbb, 0xcd, 0x64, 0x27, 0xd1, 0x66, 0xa4, 0x86, 0x88, 0x1a, 0x98, 0xcf, 0xf2, 0xb6, 0x53, 0x56, 0x8b, 0xa7, 0x79, 0xec,
0x6f, 0xad, 0x85, 0xbc, 0xbb, 0xae, 0xc9, 0xbc, 0xc5, 0x78, 0x31, 0x5a, 0x67, 0x89, 0xa4, 0x22, 0x98, 0x6a, 0xb1, 0xc3, 0x7a, 0x4e, 0x05, 0x25, 0x3c, 0x72, 0xaa, 0x5b, 0x77, 0xbe, 0xbd, 0x7d,
0x21, 0xf1, 0x3a, 0xf2, 0xbb, 0xae, 0xf8, 0x4d, 0x5b, 0xad, 0x05, 0x9c, 0xdd, 0xf9, 0x37, 0x00, 0xca, 0x64, 0x27, 0x6f, 0xaf, 0x85, 0xbc, 0xbb, 0xae, 0xa9, 0xbe, 0xc5, 0x78, 0xb1, 0x5a, 0x67,
0x00, 0xff, 0xff, 0xc8, 0xcd, 0x73, 0x91, 0x98, 0x0f, 0x00, 0x00, 0x89, 0xa4, 0x22, 0x21, 0xf1, 0x3a, 0xb2, 0xbf, 0xae, 0xd8, 0x4f, 0xdb, 0xed, 0x05, 0xfc, 0xba,
0xf3, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x32, 0x23, 0x5b, 0x87, 0xb6, 0x0f, 0x00, 0x00,
} }