Spade A 0114bd1dc9
feat: support match operator family (#46518)
issue: https://github.com/milvus-io/milvus/issues/46517
ref: https://github.com/milvus-io/milvus/issues/42148

This PR supports match operator family with struct array and brute force
search only.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
- Core invariant: match operators only target struct-array element-level
predicates and assume callers provide a correct row_start so element
indices form a contiguous range; IArrayOffsets implementations convert
row-level bitmaps/rows (starting at row_start) into element-level
bitmaps or a contiguous element-offset vector used by brute-force
evaluation.

- New capability added: end-to-end support for MATCH_* semantics
(match_any, match_all, match_least, match_most, match_exact) — parser
(grammar + proto), planner (ParseMatchExprs), expr model
(expr::MatchExpr), compilation (Expr→PhyMatchFilterExpr), execution
(PhyMatchFilterExpr::Eval uses element offsets/bitmaps), and unit tests
(MatchExprTest + parser tests). Implementation currently works for
struct-array inputs and uses brute-force element counting via
RowBitsetToElementOffsets/RowBitsetToElementBitset.

- Logic removed or simplified and why: removed the ad-hoc
DocBitsetToElementOffsets helper and consolidated offset/bitset
derivation into IArrayOffsets::RowBitsetToElementOffsets and a
row_start-aware RowBitsetToElementBitset, and removed EvalCtx overloads
that embedded ExprSet (now EvalCtx(exec_ctx, offset_input)). This
centralizes array-layout logic in ArrayOffsets and removes duplicated
offset conversion and EvalCtx variants that were redundant for
element-level evaluation.

- No data loss / no behavior regression: persistent formats are
unchanged (no proto storage or on-disk layout changed); callers were
updated to supply row_start and now route through the centralized
ArrayOffsets APIs which still use the authoritative
row_to_element_start_ mapping, preserving exact element index mappings.
Eval logic changes are limited to in-memory plumbing (how
offsets/bitmaps are produced and how EvalCtx is constructed); expression
evaluation still invokes exprs_->Eval where needed, so existing behavior
and stored data remain intact.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: SpadeA <tangchenjie1210@gmail.com>
Signed-off-by: SpadeA-Tang <tangchenjie1210@gmail.com>
2025-12-29 11:03:26 +08:00

161 lines
11 KiB
Plaintext

token literal names:
null
'('
')'
'['
','
']'
'{'
'}'
'<'
'<='
'>'
'>='
'=='
'!='
null
null
null
null
null
null
null
null
null
null
null
null
null
null
'='
'+'
'-'
'*'
'/'
'%'
'**'
'<<'
'>>'
'&'
'|'
'^'
null
null
null
null
'~'
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
'$meta'
null
null
null
null
null
token symbolic names:
null
null
null
null
null
null
LBRACE
RBRACE
LT
LE
GT
GE
EQ
NE
LIKE
EXISTS
TEXTMATCH
PHRASEMATCH
RANDOMSAMPLE
MATCH_ALL
MATCH_ANY
MATCH_LEAST
MATCH_MOST
MATCH_EXACT
INTERVAL
ISO
MINIMUM_SHOULD_MATCH
THRESHOLD
ASSIGN
ADD
SUB
MUL
DIV
MOD
POW
SHL
SHR
BAND
BOR
BXOR
AND
OR
ISNULL
ISNOTNULL
BNOT
NOT
IN
EmptyArray
JSONContains
JSONContainsAll
JSONContainsAny
ArrayContains
ArrayContainsAll
ArrayContainsAny
ArrayLength
ElementFilter
STEuqals
STTouches
STOverlaps
STCrosses
STContains
STIntersects
STWithin
STDWithin
STIsValid
BooleanConstant
IntegerConstant
FloatingConstant
Identifier
Meta
StringLiteral
JSONIdentifier
StructSubFieldIdentifier
Whitespace
Newline
rule names:
expr
textMatchOption
atn:
[4, 1, 74, 299, 2, 0, 7, 0, 2, 1, 7, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 10, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 22, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 42, 8, 0, 10, 0, 12, 0, 45, 9, 0, 1, 0, 3, 0, 48, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 62, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 72, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 221, 8, 0, 10, 0, 12, 0, 224, 9, 0, 1, 0, 3, 0, 227, 8, 0, 3, 0, 229, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 236, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 3, 0, 252, 8, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 5, 0, 290, 8, 0, 10, 0, 12, 0, 293, 9, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 2, 0, 2, 0, 15, 1, 0, 29, 30, 1, 0, 8, 13, 1, 0, 68, 69, 2, 0, 29, 30, 44, 45, 2, 0, 48, 48, 51, 51, 2, 0, 49, 49, 52, 52, 2, 0, 50, 50, 53, 53, 2, 0, 68, 68, 71, 71, 1, 0, 31, 33, 1, 0, 35, 36, 1, 0, 8, 9, 2, 0, 68, 68, 71, 72, 1, 0, 10, 11, 1, 0, 8, 11, 1, 0, 12, 13, 360, 0, 235, 1, 0, 0, 0, 2, 294, 1, 0, 0, 0, 4, 5, 6, 0, -1, 0, 5, 9, 5, 68, 0, 0, 6, 7, 7, 0, 0, 0, 7, 8, 5, 24, 0, 0, 8, 10, 5, 70, 0, 0, 9, 6, 1, 0, 0, 0, 9, 10, 1, 0, 0, 0, 10, 11, 1, 0, 0, 0, 11, 12, 7, 1, 0, 0, 12, 13, 5, 25, 0, 0, 13, 236, 5, 70, 0, 0, 14, 15, 5, 25, 0, 0, 15, 16, 5, 70, 0, 0, 16, 17, 7, 1, 0, 0, 17, 21, 5, 68, 0, 0, 18, 19, 7, 0, 0, 0, 19, 20, 5, 24, 0, 0, 20, 22, 5, 70, 0, 0, 21, 18, 1, 0, 0, 0, 21, 22, 1, 0, 0, 0, 22, 236, 1, 0, 0, 0, 23, 236, 5, 66, 0, 0, 24, 236, 5, 67, 0, 0, 25, 236, 5, 65, 0, 0, 26, 236, 5, 70, 0, 0, 27, 236, 7, 2, 0, 0, 28, 236, 5, 71, 0, 0, 29, 236, 5, 72, 0, 0, 30, 31, 5, 6, 0, 0, 31, 32, 5, 68, 0, 0, 32, 236, 5, 7, 0, 0, 33, 34, 5, 1, 0, 0, 34, 35, 3, 0, 0, 0, 35, 36, 5, 2, 0, 0, 36, 236, 1, 0, 0, 0, 37, 38, 5, 3, 0, 0, 38, 43, 3, 0, 0, 0, 39, 40, 5, 4, 0, 0, 40, 42, 3, 0, 0, 0, 41, 39, 1, 0, 0, 0, 42, 45, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 47, 1, 0, 0, 0, 45, 43, 1, 0, 0, 0, 46, 48, 5, 4, 0, 0, 47, 46, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 49, 1, 0, 0, 0, 49, 50, 5, 5, 0, 0, 50, 236, 1, 0, 0, 0, 51, 236, 5, 47, 0, 0, 52, 53, 5, 15, 0, 0, 53, 236, 3, 0, 0, 42, 54, 55, 5, 16, 0, 0, 55, 56, 5, 1, 0, 0, 56, 57, 5, 68, 0, 0, 57, 58, 5, 4, 0, 0, 58, 61, 5, 70, 0, 0, 59, 60, 5, 4, 0, 0, 60, 62, 3, 2, 1, 0, 61, 59, 1, 0, 0, 0, 61, 62, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 236, 5, 2, 0, 0, 64, 65, 5, 17, 0, 0, 65, 66, 5, 1, 0, 0, 66, 67, 5, 68, 0, 0, 67, 68, 5, 4, 0, 0, 68, 71, 5, 70, 0, 0, 69, 70, 5, 4, 0, 0, 70, 72, 3, 0, 0, 0, 71, 69, 1, 0, 0, 0, 71, 72, 1, 0, 0, 0, 72, 73, 1, 0, 0, 0, 73, 236, 5, 2, 0, 0, 74, 75, 5, 18, 0, 0, 75, 76, 5, 1, 0, 0, 76, 77, 3, 0, 0, 0, 77, 78, 5, 2, 0, 0, 78, 236, 1, 0, 0, 0, 79, 80, 5, 55, 0, 0, 80, 81, 5, 1, 0, 0, 81, 82, 5, 68, 0, 0, 82, 83, 5, 4, 0, 0, 83, 84, 3, 0, 0, 0, 84, 85, 5, 2, 0, 0, 85, 236, 1, 0, 0, 0, 86, 87, 5, 19, 0, 0, 87, 88, 5, 1, 0, 0, 88, 89, 5, 68, 0, 0, 89, 90, 5, 4, 0, 0, 90, 91, 3, 0, 0, 0, 91, 92, 5, 2, 0, 0, 92, 236, 1, 0, 0, 0, 93, 94, 5, 20, 0, 0, 94, 95, 5, 1, 0, 0, 95, 96, 5, 68, 0, 0, 96, 97, 5, 4, 0, 0, 97, 98, 3, 0, 0, 0, 98, 99, 5, 2, 0, 0, 99, 236, 1, 0, 0, 0, 100, 101, 5, 21, 0, 0, 101, 102, 5, 1, 0, 0, 102, 103, 5, 68, 0, 0, 103, 104, 5, 4, 0, 0, 104, 105, 3, 0, 0, 0, 105, 106, 5, 4, 0, 0, 106, 107, 5, 27, 0, 0, 107, 108, 5, 28, 0, 0, 108, 109, 5, 66, 0, 0, 109, 110, 5, 2, 0, 0, 110, 236, 1, 0, 0, 0, 111, 112, 5, 22, 0, 0, 112, 113, 5, 1, 0, 0, 113, 114, 5, 68, 0, 0, 114, 115, 5, 4, 0, 0, 115, 116, 3, 0, 0, 0, 116, 117, 5, 4, 0, 0, 117, 118, 5, 27, 0, 0, 118, 119, 5, 28, 0, 0, 119, 120, 5, 66, 0, 0, 120, 121, 5, 2, 0, 0, 121, 236, 1, 0, 0, 0, 122, 123, 5, 23, 0, 0, 123, 124, 5, 1, 0, 0, 124, 125, 5, 68, 0, 0, 125, 126, 5, 4, 0, 0, 126, 127, 3, 0, 0, 0, 127, 128, 5, 4, 0, 0, 128, 129, 5, 27, 0, 0, 129, 130, 5, 28, 0, 0, 130, 131, 5, 66, 0, 0, 131, 132, 5, 2, 0, 0, 132, 236, 1, 0, 0, 0, 133, 134, 7, 3, 0, 0, 134, 236, 3, 0, 0, 30, 135, 136, 7, 4, 0, 0, 136, 137, 5, 1, 0, 0, 137, 138, 3, 0, 0, 0, 138, 139, 5, 4, 0, 0, 139, 140, 3, 0, 0, 0, 140, 141, 5, 2, 0, 0, 141, 236, 1, 0, 0, 0, 142, 143, 7, 5, 0, 0, 143, 144, 5, 1, 0, 0, 144, 145, 3, 0, 0, 0, 145, 146, 5, 4, 0, 0, 146, 147, 3, 0, 0, 0, 147, 148, 5, 2, 0, 0, 148, 236, 1, 0, 0, 0, 149, 150, 7, 6, 0, 0, 150, 151, 5, 1, 0, 0, 151, 152, 3, 0, 0, 0, 152, 153, 5, 4, 0, 0, 153, 154, 3, 0, 0, 0, 154, 155, 5, 2, 0, 0, 155, 236, 1, 0, 0, 0, 156, 157, 5, 56, 0, 0, 157, 158, 5, 1, 0, 0, 158, 159, 5, 68, 0, 0, 159, 160, 5, 4, 0, 0, 160, 161, 5, 70, 0, 0, 161, 236, 5, 2, 0, 0, 162, 163, 5, 57, 0, 0, 163, 164, 5, 1, 0, 0, 164, 165, 5, 68, 0, 0, 165, 166, 5, 4, 0, 0, 166, 167, 5, 70, 0, 0, 167, 236, 5, 2, 0, 0, 168, 169, 5, 58, 0, 0, 169, 170, 5, 1, 0, 0, 170, 171, 5, 68, 0, 0, 171, 172, 5, 4, 0, 0, 172, 173, 5, 70, 0, 0, 173, 236, 5, 2, 0, 0, 174, 175, 5, 59, 0, 0, 175, 176, 5, 1, 0, 0, 176, 177, 5, 68, 0, 0, 177, 178, 5, 4, 0, 0, 178, 179, 5, 70, 0, 0, 179, 236, 5, 2, 0, 0, 180, 181, 5, 60, 0, 0, 181, 182, 5, 1, 0, 0, 182, 183, 5, 68, 0, 0, 183, 184, 5, 4, 0, 0, 184, 185, 5, 70, 0, 0, 185, 236, 5, 2, 0, 0, 186, 187, 5, 61, 0, 0, 187, 188, 5, 1, 0, 0, 188, 189, 5, 68, 0, 0, 189, 190, 5, 4, 0, 0, 190, 191, 5, 70, 0, 0, 191, 236, 5, 2, 0, 0, 192, 193, 5, 62, 0, 0, 193, 194, 5, 1, 0, 0, 194, 195, 5, 68, 0, 0, 195, 196, 5, 4, 0, 0, 196, 197, 5, 70, 0, 0, 197, 236, 5, 2, 0, 0, 198, 199, 5, 63, 0, 0, 199, 200, 5, 1, 0, 0, 200, 201, 5, 68, 0, 0, 201, 202, 5, 4, 0, 0, 202, 203, 5, 70, 0, 0, 203, 204, 5, 4, 0, 0, 204, 205, 3, 0, 0, 0, 205, 206, 5, 2, 0, 0, 206, 236, 1, 0, 0, 0, 207, 208, 5, 64, 0, 0, 208, 209, 5, 1, 0, 0, 209, 210, 5, 68, 0, 0, 210, 236, 5, 2, 0, 0, 211, 212, 5, 54, 0, 0, 212, 213, 5, 1, 0, 0, 213, 214, 7, 7, 0, 0, 214, 236, 5, 2, 0, 0, 215, 216, 5, 68, 0, 0, 216, 228, 5, 1, 0, 0, 217, 222, 3, 0, 0, 0, 218, 219, 5, 4, 0, 0, 219, 221, 3, 0, 0, 0, 220, 218, 1, 0, 0, 0, 221, 224, 1, 0, 0, 0, 222, 220, 1, 0, 0, 0, 222, 223, 1, 0, 0, 0, 223, 226, 1, 0, 0, 0, 224, 222, 1, 0, 0, 0, 225, 227, 5, 4, 0, 0, 226, 225, 1, 0, 0, 0, 226, 227, 1, 0, 0, 0, 227, 229, 1, 0, 0, 0, 228, 217, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 236, 5, 2, 0, 0, 231, 232, 7, 7, 0, 0, 232, 236, 5, 42, 0, 0, 233, 234, 7, 7, 0, 0, 234, 236, 5, 43, 0, 0, 235, 4, 1, 0, 0, 0, 235, 14, 1, 0, 0, 0, 235, 23, 1, 0, 0, 0, 235, 24, 1, 0, 0, 0, 235, 25, 1, 0, 0, 0, 235, 26, 1, 0, 0, 0, 235, 27, 1, 0, 0, 0, 235, 28, 1, 0, 0, 0, 235, 29, 1, 0, 0, 0, 235, 30, 1, 0, 0, 0, 235, 33, 1, 0, 0, 0, 235, 37, 1, 0, 0, 0, 235, 51, 1, 0, 0, 0, 235, 52, 1, 0, 0, 0, 235, 54, 1, 0, 0, 0, 235, 64, 1, 0, 0, 0, 235, 74, 1, 0, 0, 0, 235, 79, 1, 0, 0, 0, 235, 86, 1, 0, 0, 0, 235, 93, 1, 0, 0, 0, 235, 100, 1, 0, 0, 0, 235, 111, 1, 0, 0, 0, 235, 122, 1, 0, 0, 0, 235, 133, 1, 0, 0, 0, 235, 135, 1, 0, 0, 0, 235, 142, 1, 0, 0, 0, 235, 149, 1, 0, 0, 0, 235, 156, 1, 0, 0, 0, 235, 162, 1, 0, 0, 0, 235, 168, 1, 0, 0, 0, 235, 174, 1, 0, 0, 0, 235, 180, 1, 0, 0, 0, 235, 186, 1, 0, 0, 0, 235, 192, 1, 0, 0, 0, 235, 198, 1, 0, 0, 0, 235, 207, 1, 0, 0, 0, 235, 211, 1, 0, 0, 0, 235, 215, 1, 0, 0, 0, 235, 231, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 236, 291, 1, 0, 0, 0, 237, 238, 10, 31, 0, 0, 238, 239, 5, 34, 0, 0, 239, 290, 3, 0, 0, 32, 240, 241, 10, 29, 0, 0, 241, 242, 7, 8, 0, 0, 242, 290, 3, 0, 0, 30, 243, 244, 10, 28, 0, 0, 244, 245, 7, 0, 0, 0, 245, 290, 3, 0, 0, 29, 246, 247, 10, 27, 0, 0, 247, 248, 7, 9, 0, 0, 248, 290, 3, 0, 0, 28, 249, 251, 10, 26, 0, 0, 250, 252, 5, 45, 0, 0, 251, 250, 1, 0, 0, 0, 251, 252, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 254, 5, 46, 0, 0, 254, 290, 3, 0, 0, 27, 255, 256, 10, 11, 0, 0, 256, 257, 7, 10, 0, 0, 257, 258, 7, 11, 0, 0, 258, 259, 7, 10, 0, 0, 259, 290, 3, 0, 0, 12, 260, 261, 10, 10, 0, 0, 261, 262, 7, 12, 0, 0, 262, 263, 7, 11, 0, 0, 263, 264, 7, 12, 0, 0, 264, 290, 3, 0, 0, 11, 265, 266, 10, 9, 0, 0, 266, 267, 7, 13, 0, 0, 267, 290, 3, 0, 0, 10, 268, 269, 10, 8, 0, 0, 269, 270, 7, 14, 0, 0, 270, 290, 3, 0, 0, 9, 271, 272, 10, 7, 0, 0, 272, 273, 5, 37, 0, 0, 273, 290, 3, 0, 0, 8, 274, 275, 10, 6, 0, 0, 275, 276, 5, 39, 0, 0, 276, 290, 3, 0, 0, 7, 277, 278, 10, 5, 0, 0, 278, 279, 5, 38, 0, 0, 279, 290, 3, 0, 0, 6, 280, 281, 10, 4, 0, 0, 281, 282, 5, 40, 0, 0, 282, 290, 3, 0, 0, 5, 283, 284, 10, 3, 0, 0, 284, 285, 5, 41, 0, 0, 285, 290, 3, 0, 0, 4, 286, 287, 10, 41, 0, 0, 287, 288, 5, 14, 0, 0, 288, 290, 5, 70, 0, 0, 289, 237, 1, 0, 0, 0, 289, 240, 1, 0, 0, 0, 289, 243, 1, 0, 0, 0, 289, 246, 1, 0, 0, 0, 289, 249, 1, 0, 0, 0, 289, 255, 1, 0, 0, 0, 289, 260, 1, 0, 0, 0, 289, 265, 1, 0, 0, 0, 289, 268, 1, 0, 0, 0, 289, 271, 1, 0, 0, 0, 289, 274, 1, 0, 0, 0, 289, 277, 1, 0, 0, 0, 289, 280, 1, 0, 0, 0, 289, 283, 1, 0, 0, 0, 289, 286, 1, 0, 0, 0, 290, 293, 1, 0, 0, 0, 291, 289, 1, 0, 0, 0, 291, 292, 1, 0, 0, 0, 292, 1, 1, 0, 0, 0, 293, 291, 1, 0, 0, 0, 294, 295, 5, 26, 0, 0, 295, 296, 5, 28, 0, 0, 296, 297, 5, 66, 0, 0, 297, 3, 1, 0, 0, 0, 13, 9, 21, 43, 47, 61, 71, 222, 226, 228, 235, 251, 289, 291]