diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 6e9d6384cab4f..4b19b6409e46a 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -331,6 +331,29 @@ func TestExplain(t *testing.T) { tk.MustExec("drop global binding for SELECT * from t1 union SELECT * from t1") } +func TestBindSemiJoinRewrite(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t1") + tk.MustExec("drop table if exists t2") + tk.MustExec("create table t1(id int)") + tk.MustExec("create table t2(id int)") + require.True(t, tk.HasKeywordInOperatorInfo("select * from t1 where exists(select 1 from t2 where t1.id=t2.id)", "semi join")) + require.True(t, tk.NotHasKeywordInOperatorInfo("select * from t1 where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t2 where t1.id=t2.id)", "semi join")) + + tk.MustExec(` +create global binding for + select * from t1 where exists(select 1 from t2 where t1.id=t2.id) +using + select * from t1 where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t2 where t1.id=t2.id) +`) + + require.True(t, tk.NotHasKeywordInOperatorInfo("select * from t1 where exists(select 1 from t2 where t1.id=t2.id)", "semi join")) +} + // TestBindingSymbolList tests sql with "?, ?, ?, ?", fixes #13871 func TestBindingSymbolList(t *testing.T) { store, dom, clean := testkit.CreateMockStoreAndDomain(t) diff --git a/parser/hintparser.go b/parser/hintparser.go index 906f1a0259978..83fdee7af18a2 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -41,18 +41,18 @@ type yyhintXError struct { } const ( - yyhintDefault = 57418 + yyhintDefault = 57419 yyhintEOFCode = 57344 yyhintErrCode = 57345 hintAggToCop = 57378 hintBCJoin = 57391 hintBKA = 57355 hintBNL = 57357 - hintDupsWeedOut = 57414 - hintFalse = 57410 - hintFirstMatch = 57415 + hintDupsWeedOut = 57415 + hintFalse = 57411 + hintFirstMatch = 57416 hintForceIndex = 57402 - hintGB = 57413 + hintGB = 57414 hintHashAgg = 57380 hintHashJoin = 57359 hintIdentifier = 57347 @@ -70,10 +70,10 @@ const ( hintJoinSuffix = 57354 hintLeading = 57404 hintLimitToCop = 57401 - hintLooseScan = 57416 - hintMB = 57412 + hintLooseScan = 57417 + hintMB = 57413 hintMRR = 57366 - hintMaterialization = 57417 + hintMaterialization = 57418 hintMaxExecutionTime = 57374 hintMemoryQuota = 57385 hintMerge = 57362 @@ -89,16 +89,17 @@ const ( hintNoSkipScan = 57371 hintNoSwapJoinInputs = 57386 hintNthPlan = 57400 - hintOLAP = 57405 - hintOLTP = 57406 + hintOLAP = 57406 + hintOLTP = 57407 hintOrderedHashJoin = 57360 - hintPartition = 57407 + hintPartition = 57408 hintQBName = 57377 hintQueryType = 57387 hintReadConsistentReplica = 57388 hintReadFromStorage = 57389 hintResourceGroup = 57376 hintSMJoin = 57390 + hintSemiJoinRewrite = 57405 hintSemijoin = 57372 hintSetVar = 57375 hintSingleAtIdentifier = 57349 @@ -107,10 +108,10 @@ const ( hintStreamAgg = 57392 hintStringLit = 57350 hintSwapJoinInputs = 57393 - hintTiFlash = 57409 - hintTiKV = 57408 + hintTiFlash = 57410 + hintTiKV = 57409 hintTimeRange = 57398 - hintTrue = 57411 + hintTrue = 57412 hintUseCascades = 57399 hintUseIndex = 57395 hintUseIndexMerge = 57394 @@ -118,126 +119,127 @@ const ( hintUseToja = 57397 yyhintMaxDepth = 200 - yyhintTabOfs = -176 + yyhintTabOfs = -178 ) var ( yyhintXLAT = map[int]int{ - 41: 0, // ')' (132x) - 57378: 1, // hintAggToCop (124x) - 57391: 2, // hintBCJoin (124x) - 57355: 3, // hintBKA (124x) - 57357: 4, // hintBNL (124x) - 57402: 5, // hintForceIndex (124x) - 57380: 6, // hintHashAgg (124x) - 57359: 7, // hintHashJoin (124x) - 57381: 8, // hintIgnoreIndex (124x) - 57379: 9, // hintIgnorePlanCache (124x) - 57364: 10, // hintIndexMerge (124x) - 57382: 11, // hintInlHashJoin (124x) - 57383: 12, // hintInlJoin (124x) - 57384: 13, // hintInlMergeJoin (124x) - 57351: 14, // hintJoinFixedOrder (124x) - 57352: 15, // hintJoinOrder (124x) - 57353: 16, // hintJoinPrefix (124x) - 57354: 17, // hintJoinSuffix (124x) - 57404: 18, // hintLeading (124x) - 57401: 19, // hintLimitToCop (124x) - 57374: 20, // hintMaxExecutionTime (124x) - 57385: 21, // hintMemoryQuota (124x) - 57362: 22, // hintMerge (124x) - 57366: 23, // hintMRR (124x) - 57356: 24, // hintNoBKA (124x) - 57358: 25, // hintNoBNL (124x) - 57361: 26, // hintNoHashJoin (124x) - 57368: 27, // hintNoICP (124x) - 57365: 28, // hintNoIndexMerge (124x) - 57363: 29, // hintNoMerge (124x) - 57367: 30, // hintNoMRR (124x) - 57369: 31, // hintNoRangeOptimization (124x) - 57373: 32, // hintNoSemijoin (124x) - 57371: 33, // hintNoSkipScan (124x) - 57386: 34, // hintNoSwapJoinInputs (124x) - 57400: 35, // hintNthPlan (124x) - 57360: 36, // hintOrderedHashJoin (124x) - 57377: 37, // hintQBName (124x) - 57387: 38, // hintQueryType (124x) - 57388: 39, // hintReadConsistentReplica (124x) - 57389: 40, // hintReadFromStorage (124x) - 57376: 41, // hintResourceGroup (124x) - 57372: 42, // hintSemijoin (124x) - 57375: 43, // hintSetVar (124x) - 57370: 44, // hintSkipScan (124x) - 57390: 45, // hintSMJoin (124x) - 57403: 46, // hintStraightJoin (124x) - 57392: 47, // hintStreamAgg (124x) - 57393: 48, // hintSwapJoinInputs (124x) - 57398: 49, // hintTimeRange (124x) - 57399: 50, // hintUseCascades (124x) - 57395: 51, // hintUseIndex (124x) - 57394: 52, // hintUseIndexMerge (124x) - 57396: 53, // hintUsePlanCache (124x) - 57397: 54, // hintUseToja (124x) - 44: 55, // ',' (122x) - 57414: 56, // hintDupsWeedOut (102x) - 57415: 57, // hintFirstMatch (102x) - 57416: 58, // hintLooseScan (102x) - 57417: 59, // hintMaterialization (102x) - 57409: 60, // hintTiFlash (102x) - 57408: 61, // hintTiKV (102x) - 57410: 62, // hintFalse (101x) - 57405: 63, // hintOLAP (101x) - 57406: 64, // hintOLTP (101x) - 57411: 65, // hintTrue (101x) - 57413: 66, // hintGB (100x) - 57412: 67, // hintMB (100x) - 57347: 68, // hintIdentifier (99x) - 57349: 69, // hintSingleAtIdentifier (84x) - 93: 70, // ']' (78x) - 57407: 71, // hintPartition (72x) - 46: 72, // '.' (68x) - 61: 73, // '=' (68x) - 40: 74, // '(' (63x) - 57344: 75, // $end (24x) - 57438: 76, // QueryBlockOpt (17x) - 57430: 77, // Identifier (13x) - 57346: 78, // hintIntLit (8x) - 57350: 79, // hintStringLit (5x) - 57420: 80, // CommaOpt (4x) - 57426: 81, // HintTable (4x) - 57427: 82, // HintTableList (4x) - 91: 83, // '[' (3x) - 57419: 84, // BooleanHintName (2x) - 57421: 85, // HintIndexList (2x) - 57423: 86, // HintStorageType (2x) - 57424: 87, // HintStorageTypeAndTable (2x) - 57428: 88, // HintTableListOpt (2x) - 57433: 89, // JoinOrderOptimizerHintName (2x) - 57434: 90, // NullaryHintName (2x) - 57437: 91, // PartitionListOpt (2x) - 57440: 92, // StorageOptimizerHintOpt (2x) - 57441: 93, // SubqueryOptimizerHintName (2x) - 57444: 94, // SubqueryStrategy (2x) - 57445: 95, // SupportedIndexLevelOptimizerHintName (2x) - 57446: 96, // SupportedTableLevelOptimizerHintName (2x) - 57447: 97, // TableOptimizerHintOpt (2x) - 57449: 98, // UnsupportedIndexLevelOptimizerHintName (2x) - 57450: 99, // UnsupportedTableLevelOptimizerHintName (2x) - 57422: 100, // HintQueryType (1x) - 57425: 101, // HintStorageTypeAndTableList (1x) - 57429: 102, // HintTrueOrFalse (1x) - 57431: 103, // IndexNameList (1x) - 57432: 104, // IndexNameListOpt (1x) - 57435: 105, // OptimizerHintList (1x) - 57436: 106, // PartitionList (1x) - 57439: 107, // Start (1x) - 57442: 108, // SubqueryStrategies (1x) - 57443: 109, // SubqueryStrategiesOpt (1x) - 57448: 110, // UnitOfBytes (1x) - 57451: 111, // Value (1x) - 57418: 112, // $default (0x) - 57345: 113, // error (0x) - 57348: 114, // hintInvalid (0x) + 41: 0, // ')' (133x) + 57378: 1, // hintAggToCop (125x) + 57391: 2, // hintBCJoin (125x) + 57355: 3, // hintBKA (125x) + 57357: 4, // hintBNL (125x) + 57402: 5, // hintForceIndex (125x) + 57380: 6, // hintHashAgg (125x) + 57359: 7, // hintHashJoin (125x) + 57381: 8, // hintIgnoreIndex (125x) + 57379: 9, // hintIgnorePlanCache (125x) + 57364: 10, // hintIndexMerge (125x) + 57382: 11, // hintInlHashJoin (125x) + 57383: 12, // hintInlJoin (125x) + 57384: 13, // hintInlMergeJoin (125x) + 57351: 14, // hintJoinFixedOrder (125x) + 57352: 15, // hintJoinOrder (125x) + 57353: 16, // hintJoinPrefix (125x) + 57354: 17, // hintJoinSuffix (125x) + 57404: 18, // hintLeading (125x) + 57401: 19, // hintLimitToCop (125x) + 57374: 20, // hintMaxExecutionTime (125x) + 57385: 21, // hintMemoryQuota (125x) + 57362: 22, // hintMerge (125x) + 57366: 23, // hintMRR (125x) + 57356: 24, // hintNoBKA (125x) + 57358: 25, // hintNoBNL (125x) + 57361: 26, // hintNoHashJoin (125x) + 57368: 27, // hintNoICP (125x) + 57365: 28, // hintNoIndexMerge (125x) + 57363: 29, // hintNoMerge (125x) + 57367: 30, // hintNoMRR (125x) + 57369: 31, // hintNoRangeOptimization (125x) + 57373: 32, // hintNoSemijoin (125x) + 57371: 33, // hintNoSkipScan (125x) + 57386: 34, // hintNoSwapJoinInputs (125x) + 57400: 35, // hintNthPlan (125x) + 57360: 36, // hintOrderedHashJoin (125x) + 57377: 37, // hintQBName (125x) + 57387: 38, // hintQueryType (125x) + 57388: 39, // hintReadConsistentReplica (125x) + 57389: 40, // hintReadFromStorage (125x) + 57376: 41, // hintResourceGroup (125x) + 57372: 42, // hintSemijoin (125x) + 57405: 43, // hintSemiJoinRewrite (125x) + 57375: 44, // hintSetVar (125x) + 57370: 45, // hintSkipScan (125x) + 57390: 46, // hintSMJoin (125x) + 57403: 47, // hintStraightJoin (125x) + 57392: 48, // hintStreamAgg (125x) + 57393: 49, // hintSwapJoinInputs (125x) + 57398: 50, // hintTimeRange (125x) + 57399: 51, // hintUseCascades (125x) + 57395: 52, // hintUseIndex (125x) + 57394: 53, // hintUseIndexMerge (125x) + 57396: 54, // hintUsePlanCache (125x) + 57397: 55, // hintUseToja (125x) + 44: 56, // ',' (123x) + 57415: 57, // hintDupsWeedOut (103x) + 57416: 58, // hintFirstMatch (103x) + 57417: 59, // hintLooseScan (103x) + 57418: 60, // hintMaterialization (103x) + 57410: 61, // hintTiFlash (103x) + 57409: 62, // hintTiKV (103x) + 57411: 63, // hintFalse (102x) + 57406: 64, // hintOLAP (102x) + 57407: 65, // hintOLTP (102x) + 57412: 66, // hintTrue (102x) + 57414: 67, // hintGB (101x) + 57413: 68, // hintMB (101x) + 57347: 69, // hintIdentifier (100x) + 57349: 70, // hintSingleAtIdentifier (85x) + 93: 71, // ']' (79x) + 57408: 72, // hintPartition (73x) + 46: 73, // '.' (69x) + 61: 74, // '=' (69x) + 40: 75, // '(' (64x) + 57344: 76, // $end (24x) + 57439: 77, // QueryBlockOpt (17x) + 57431: 78, // Identifier (13x) + 57346: 79, // hintIntLit (8x) + 57350: 80, // hintStringLit (5x) + 57421: 81, // CommaOpt (4x) + 57427: 82, // HintTable (4x) + 57428: 83, // HintTableList (4x) + 91: 84, // '[' (3x) + 57420: 85, // BooleanHintName (2x) + 57422: 86, // HintIndexList (2x) + 57424: 87, // HintStorageType (2x) + 57425: 88, // HintStorageTypeAndTable (2x) + 57429: 89, // HintTableListOpt (2x) + 57434: 90, // JoinOrderOptimizerHintName (2x) + 57435: 91, // NullaryHintName (2x) + 57438: 92, // PartitionListOpt (2x) + 57441: 93, // StorageOptimizerHintOpt (2x) + 57442: 94, // SubqueryOptimizerHintName (2x) + 57445: 95, // SubqueryStrategy (2x) + 57446: 96, // SupportedIndexLevelOptimizerHintName (2x) + 57447: 97, // SupportedTableLevelOptimizerHintName (2x) + 57448: 98, // TableOptimizerHintOpt (2x) + 57450: 99, // UnsupportedIndexLevelOptimizerHintName (2x) + 57451: 100, // UnsupportedTableLevelOptimizerHintName (2x) + 57423: 101, // HintQueryType (1x) + 57426: 102, // HintStorageTypeAndTableList (1x) + 57430: 103, // HintTrueOrFalse (1x) + 57432: 104, // IndexNameList (1x) + 57433: 105, // IndexNameListOpt (1x) + 57436: 106, // OptimizerHintList (1x) + 57437: 107, // PartitionList (1x) + 57440: 108, // Start (1x) + 57443: 109, // SubqueryStrategies (1x) + 57444: 110, // SubqueryStrategiesOpt (1x) + 57449: 111, // UnitOfBytes (1x) + 57452: 112, // Value (1x) + 57419: 113, // $default (0x) + 57345: 114, // error (0x) + 57348: 115, // hintInvalid (0x) } yyhintSymNames = []string{ @@ -284,6 +286,7 @@ var ( "hintReadFromStorage", "hintResourceGroup", "hintSemijoin", + "hintSemiJoinRewrite", "hintSetVar", "hintSkipScan", "hintSMJoin", @@ -360,65 +363,82 @@ var ( yyhintReductions = []struct{ xsym, components int }{ {0, 1}, - {107, 1}, - {105, 1}, - {105, 3}, - {105, 1}, - {105, 3}, - {97, 4}, - {97, 4}, - {97, 4}, - {97, 4}, - {97, 4}, - {97, 4}, - {97, 5}, - {97, 5}, - {97, 5}, - {97, 6}, - {97, 4}, - {97, 4}, - {97, 6}, - {97, 6}, - {97, 5}, - {97, 4}, - {97, 5}, - {92, 5}, - {101, 1}, - {101, 3}, - {87, 4}, - {76, 0}, - {76, 1}, - {80, 0}, - {80, 1}, - {91, 0}, - {91, 4}, + {108, 1}, {106, 1}, {106, 3}, - {88, 1}, - {88, 1}, - {82, 2}, + {106, 1}, + {106, 3}, + {98, 4}, + {98, 4}, + {98, 4}, + {98, 4}, + {98, 4}, + {98, 4}, + {98, 5}, + {98, 5}, + {98, 5}, + {98, 6}, + {98, 4}, + {98, 4}, + {98, 6}, + {98, 6}, + {98, 5}, + {98, 4}, + {98, 5}, + {93, 5}, + {102, 1}, + {102, 3}, + {88, 4}, + {77, 0}, + {77, 1}, + {81, 0}, + {81, 1}, + {92, 0}, + {92, 4}, + {107, 1}, + {107, 3}, + {89, 1}, + {89, 1}, + {83, 2}, + {83, 3}, {82, 3}, - {81, 3}, - {81, 5}, - {85, 4}, - {104, 0}, + {82, 5}, + {86, 4}, + {105, 0}, + {105, 1}, {104, 1}, - {103, 1}, - {103, 3}, - {109, 0}, + {104, 3}, + {110, 0}, + {110, 1}, {109, 1}, - {108, 1}, - {108, 3}, - {111, 1}, + {109, 3}, + {112, 1}, + {112, 1}, + {112, 1}, {111, 1}, {111, 1}, - {110, 1}, - {110, 1}, - {102, 1}, - {102, 1}, - {89, 1}, - {89, 1}, - {89, 1}, + {103, 1}, + {103, 1}, + {90, 1}, + {90, 1}, + {90, 1}, + {100, 1}, + {100, 1}, + {100, 1}, + {100, 1}, + {100, 1}, + {100, 1}, + {100, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, + {97, 1}, {99, 1}, {99, 1}, {99, 1}, @@ -430,427 +450,415 @@ var ( {96, 1}, {96, 1}, {96, 1}, - {96, 1}, - {96, 1}, - {96, 1}, - {96, 1}, - {96, 1}, - {96, 1}, - {98, 1}, - {98, 1}, - {98, 1}, - {98, 1}, - {98, 1}, - {98, 1}, - {98, 1}, + {94, 1}, + {94, 1}, {95, 1}, {95, 1}, {95, 1}, {95, 1}, - {93, 1}, - {93, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {94, 1}, - {84, 1}, - {84, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {90, 1}, - {100, 1}, - {100, 1}, - {86, 1}, - {86, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, - {77, 1}, + {85, 1}, + {85, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {91, 1}, + {101, 1}, + {101, 1}, + {87, 1}, + {87, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, + {78, 1}, } yyhintXErrors = map[yyhintXError]string{} - yyhintParseTab = [259][]uint16{ + yyhintParseTab = [261][]uint16{ // 0 - {1: 237, 210, 202, 204, 229, 235, 216, 227, 241, 219, 212, 211, 215, 181, 199, 200, 201, 218, 238, 188, 193, 207, 220, 203, 205, 206, 222, 239, 208, 221, 223, 231, 225, 214, 189, 217, 192, 197, 240, 198, 191, 230, 190, 224, 209, 242, 236, 213, 194, 233, 226, 228, 234, 232, 84: 195, 89: 182, 196, 92: 180, 187, 95: 186, 184, 179, 185, 183, 105: 178, 107: 177}, - {75: 176}, - {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 332, 75: 175, 80: 432}, - {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 75: 174}, - {1: 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 75: 172}, + {1: 239, 212, 204, 206, 231, 237, 218, 229, 243, 221, 214, 213, 217, 183, 201, 202, 203, 220, 240, 190, 195, 209, 222, 205, 207, 208, 224, 241, 210, 223, 225, 233, 227, 216, 191, 219, 194, 199, 242, 200, 193, 232, 245, 192, 226, 211, 244, 238, 215, 196, 235, 228, 230, 236, 234, 85: 197, 90: 184, 198, 93: 182, 189, 96: 188, 186, 181, 187, 185, 106: 180, 108: 179}, + {76: 178}, + {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 336, 76: 177, 81: 436}, + {1: 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 76: 176}, + {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 76: 174}, // 5 - {74: 429}, - {74: 426}, - {74: 423}, - {74: 418}, - {74: 415}, + {75: 433}, + {75: 430}, + {75: 427}, + {75: 422}, + {75: 419}, // 10 - {74: 404}, - {74: 392}, - {74: 388}, - {74: 384}, - {74: 376}, + {75: 408}, + {75: 396}, + {75: 392}, + {75: 388}, + {75: 380}, // 15 - {74: 373}, - {74: 370}, - {74: 363}, - {74: 358}, - {74: 352}, + {75: 377}, + {75: 374}, + {75: 367}, + {75: 362}, + {75: 356}, // 20 - {74: 349}, - {74: 343}, - {74: 243}, - {74: 119}, - {74: 118}, + {75: 353}, + {75: 347}, + {75: 246}, + {75: 121}, + {75: 120}, // 25 - {74: 117}, - {74: 116}, - {74: 115}, - {74: 114}, - {74: 113}, + {75: 119}, + {75: 118}, + {75: 117}, + {75: 116}, + {75: 115}, // 30 - {74: 112}, - {74: 111}, - {74: 110}, - {74: 109}, - {74: 108}, + {75: 114}, + {75: 113}, + {75: 112}, + {75: 111}, + {75: 110}, // 35 - {74: 107}, - {74: 106}, - {74: 105}, - {74: 104}, - {74: 103}, + {75: 109}, + {75: 108}, + {75: 107}, + {75: 106}, + {75: 105}, // 40 - {74: 102}, - {74: 101}, - {74: 100}, - {74: 99}, - {74: 98}, + {75: 104}, + {75: 103}, + {75: 102}, + {75: 101}, + {75: 100}, // 45 - {74: 97}, - {74: 96}, - {74: 95}, - {74: 94}, - {74: 93}, + {75: 99}, + {75: 98}, + {75: 97}, + {75: 96}, + {75: 95}, // 50 - {74: 92}, - {74: 91}, - {74: 90}, - {74: 89}, - {74: 88}, + {75: 94}, + {75: 93}, + {75: 92}, + {75: 91}, + {75: 90}, // 55 - {74: 87}, - {74: 82}, - {74: 81}, - {74: 80}, - {74: 79}, + {75: 89}, + {75: 84}, + {75: 83}, + {75: 82}, + {75: 81}, // 60 - {74: 78}, - {74: 77}, - {74: 76}, - {74: 75}, - {74: 74}, + {75: 80}, + {75: 79}, + {75: 78}, + {75: 77}, + {75: 76}, // 65 - {74: 73}, - {74: 72}, - {60: 149, 149, 69: 245, 76: 244}, - {60: 250, 249, 86: 248, 247, 101: 246}, - {148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 70: 148, 148, 78: 148}, + {75: 75}, + {75: 74}, + {75: 73}, + {61: 151, 151, 70: 248, 77: 247}, + {61: 253, 252, 87: 251, 250, 102: 249}, // 70 - {340, 55: 341}, - {152, 55: 152}, - {83: 251}, - {83: 69}, - {83: 68}, + {150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 71: 150, 150, 79: 150}, + {344, 56: 345}, + {154, 56: 154}, + {84: 254}, + {84: 70}, // 75 - {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 253, 82: 252}, - {55: 338, 70: 337}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 255, 81: 254}, - {139, 55: 139, 70: 139}, - {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 149, 149, 324, 76: 323}, + {84: 69}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 256, 83: 255}, + {56: 342, 71: 341}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 258, 82: 257}, + {141, 56: 141, 71: 141}, // 80 - {67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}, - {66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66}, - {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, - {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 151, 151, 328, 77: 327}, + {68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68}, + {67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67}, + {66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66}, + {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, // 85 - {62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62}, - {61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61}, - {60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60}, - {59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59}, - {58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58}, + {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + {63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}, + {62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62}, + {61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61}, + {60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60}, // 90 - {57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57}, - {56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56}, - {55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55}, - {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}, - {53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53}, + {59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59}, + {58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58}, + {57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57}, + {56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56}, + {55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55}, // 95 - {52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52}, - {51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51}, - {50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, - {49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49}, - {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48}, + {54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54}, + {53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53}, + {52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52}, + {51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51}, + {50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50}, // 100 - {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47}, - {46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46}, - {45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45}, - {44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44}, - {43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43}, + {49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49}, + {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48}, + {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47}, + {46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46}, + {45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45}, // 105 - {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}, - {41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41}, - {40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}, - {39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39}, - {38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38}, + {44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44}, + {43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43}, + {42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42}, + {41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41}, + {40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}, // 110 - {37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37}, - {36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}, - {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, - {34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34}, - {33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33}, + {39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39}, + {38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38}, + {37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37}, + {36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36}, + {35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35}, // 115 - {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - {31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}, - {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, - {29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}, - {28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, + {34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34}, + {33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33}, + {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + {31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31}, + {30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // 120 - {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}, - {26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26}, - {25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}, - {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}, - {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}, + {29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29}, + {28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, + {27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}, + {26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26}, + {25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25}, // 125 - {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, - {21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}, - {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, - {19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}, - {18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18}, + {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24}, + {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23}, + {22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}, + {21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21}, + {20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20}, // 130 - {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}, - {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, - {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, - {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}, - {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}, + {19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}, + {18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18}, + {17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17}, + {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}, + {15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15}, // 135 - {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, - {11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, - {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, - {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, - {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, + {14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}, + {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}, + {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, + {11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}, + {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, // 140 - {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, - {6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}, - {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, - {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, - {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}, + {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, + {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}, + {6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}, + {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}, // 145 - {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 70: 145, 327, 91: 336}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 325}, - {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 149, 149, 76: 326}, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, + {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, + {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 71: 147, 331, 92: 340}, // 150 - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 70: 145, 327, 91: 328}, - {74: 329}, - {136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 70: 136}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 331, 106: 330}, - {333, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 332, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 80: 334}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 329}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 151, 151, 77: 330}, + {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 71: 147, 331, 92: 332}, + {75: 333}, + {138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 71: 138}, // 155 - {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143}, - {146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 56: 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 79: 146}, - {144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 70: 144}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 335}, - {142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 335, 107: 334}, + {337, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 336, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 81: 338}, + {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145}, + {148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 57: 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 80: 148}, + {146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 71: 146}, // 160 - {137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 70: 137}, - {150, 55: 150}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 255, 81: 339}, - {138, 55: 138, 70: 138}, - {1: 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 75: 153}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 339}, + {144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144}, + {139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 71: 139}, + {152, 56: 152}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 258, 82: 343}, // 165 - {60: 250, 249, 86: 248, 342}, - {151, 55: 151}, - {63: 149, 149, 69: 245, 76: 344}, - {63: 346, 347, 100: 345}, - {348}, + {140, 56: 140, 71: 140}, + {1: 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 76: 155}, + {61: 253, 252, 87: 251, 346}, + {153, 56: 153}, + {64: 151, 151, 70: 248, 77: 348}, // 170 + {64: 350, 351, 101: 349}, + {352}, + {72}, {71}, - {70}, - {1: 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 75: 154}, - {149, 69: 245, 76: 350}, - {351}, + {1: 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 76: 156}, // 175 - {1: 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 75: 155}, - {62: 149, 65: 149, 69: 245, 76: 353}, - {62: 356, 65: 355, 102: 354}, - {357}, - {121}, + {151, 70: 248, 77: 354}, + {355}, + {1: 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 76: 157}, + {63: 151, 66: 151, 70: 248, 77: 357}, + {63: 360, 66: 359, 103: 358}, // 180 - {120}, - {1: 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 75: 156}, - {79: 359}, - {55: 332, 79: 147, 360}, - {79: 361}, - // 185 - {362}, - {1: 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 75: 157}, - {69: 245, 76: 364, 78: 149}, - {78: 365}, - {66: 368, 367, 110: 366}, - // 190 - {369}, + {361}, {123}, {122}, - {1: 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 75: 158}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 371}, + {1: 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 76: 158}, + {80: 363}, + // 185 + {56: 336, 80: 149, 364}, + {80: 365}, + {366}, + {1: 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 76: 159}, + {70: 248, 77: 368, 79: 151}, + // 190 + {79: 369}, + {67: 372, 371, 111: 370}, + {373}, + {125}, + {124}, // 195 - {372}, - {1: 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 75: 159}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 374}, - {375}, - {1: 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 75: 160}, + {1: 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 76: 160}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 375}, + {376}, + {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 76: 161}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 378}, // 200 - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 377}, - {73: 378}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 381, 382, 380, 111: 379}, - {383}, - {126}, + {379}, + {1: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 76: 162}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 381}, + {74: 382}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 385, 386, 384, 112: 383}, // 205 - {125}, - {124}, - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 75: 161}, - {69: 245, 76: 385, 78: 149}, - {78: 386}, - // 210 {387}, - {1: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 75: 162}, - {69: 245, 76: 389, 78: 149}, - {78: 390}, + {128}, + {127}, + {126}, + {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 76: 163}, + // 210 + {70: 248, 77: 389, 79: 151}, + {79: 390}, {391}, + {1: 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 76: 164}, + {70: 248, 77: 393, 79: 151}, // 215 - {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 75: 163}, - {149, 56: 149, 149, 149, 149, 69: 245, 76: 393}, - {130, 56: 397, 398, 399, 400, 94: 396, 108: 395, 394}, - {403}, - {129, 55: 401}, + {79: 394}, + {395}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 76: 165}, + {151, 57: 151, 151, 151, 151, 70: 248, 77: 397}, + {132, 57: 401, 402, 403, 404, 95: 400, 109: 399, 398}, // 220 - {128, 55: 128}, - {86, 55: 86}, - {85, 55: 85}, - {84, 55: 84}, - {83, 55: 83}, + {407}, + {131, 56: 405}, + {130, 56: 130}, + {88, 56: 88}, + {87, 56: 87}, // 225 - {56: 397, 398, 399, 400, 94: 402}, - {127, 55: 127}, - {1: 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 75: 164}, - {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 406, 85: 405}, - {414}, + {86, 56: 86}, + {85, 56: 85}, + {57: 401, 402, 403, 404, 95: 406}, + {129, 56: 129}, + {1: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 76: 166}, // 230 - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 255, 81: 407}, - {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 332, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 80: 408}, - {134, 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 411, 103: 410, 409}, - {135}, - {133, 55: 412}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 410, 86: 409}, + {418}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 258, 82: 411}, + {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 336, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 81: 412}, + {136, 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 415, 104: 414, 413}, // 235 - {132, 55: 132}, - {1: 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 413}, - {131, 55: 131}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 75: 165}, - {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 406, 85: 416}, + {137}, + {135, 56: 416}, + {134, 56: 134}, + {1: 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 417}, + {133, 56: 133}, // 240 - {417}, - {1: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 75: 166}, - {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 421, 82: 420, 88: 419}, - {422}, - {141, 55: 338}, + {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 76: 167}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 410, 86: 420}, + {421}, + {1: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 76: 168}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 425, 83: 424, 89: 423}, // 245 - {140, 284, 298, 261, 263, 308, 287, 265, 288, 286, 270, 289, 290, 291, 257, 258, 259, 260, 310, 285, 280, 292, 268, 272, 262, 264, 267, 274, 271, 269, 273, 275, 279, 277, 293, 307, 266, 283, 294, 295, 296, 282, 278, 281, 276, 297, 309, 299, 300, 305, 306, 302, 301, 303, 304, 56: 319, 320, 321, 322, 314, 313, 315, 311, 312, 316, 318, 317, 256, 77: 255, 81: 254}, - {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 75: 167}, - {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 421, 82: 420, 88: 424}, - {425}, - {1: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 75: 168}, + {426}, + {143, 56: 342}, + {142, 287, 301, 264, 266, 311, 290, 268, 291, 289, 273, 292, 293, 294, 260, 261, 262, 263, 313, 288, 283, 295, 271, 275, 265, 267, 270, 277, 274, 272, 276, 278, 282, 280, 296, 310, 269, 286, 297, 298, 299, 285, 281, 314, 284, 279, 300, 312, 302, 303, 308, 309, 305, 304, 306, 307, 57: 323, 324, 325, 326, 318, 317, 319, 315, 316, 320, 322, 321, 259, 78: 258, 82: 257}, + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 76: 169}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 425, 83: 424, 89: 428}, // 250 - {1: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 56: 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 245, 76: 253, 82: 427}, - {428, 55: 338}, - {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 75: 169}, - {149, 69: 245, 76: 430}, - {431}, + {429}, + {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 76: 170}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 57: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 248, 77: 256, 83: 431}, + {432, 56: 342}, + {1: 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 76: 171}, // 255 - {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 75: 170}, - {1: 237, 210, 202, 204, 229, 235, 216, 227, 241, 219, 212, 211, 215, 181, 199, 200, 201, 218, 238, 188, 193, 207, 220, 203, 205, 206, 222, 239, 208, 221, 223, 231, 225, 214, 189, 217, 192, 197, 240, 198, 191, 230, 190, 224, 209, 242, 236, 213, 194, 233, 226, 228, 234, 232, 84: 195, 89: 182, 196, 92: 434, 187, 95: 186, 184, 433, 185, 183}, - {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 75: 173}, - {1: 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 75: 171}, + {151, 70: 248, 77: 434}, + {435}, + {1: 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 76: 172}, + {1: 239, 212, 204, 206, 231, 237, 218, 229, 243, 221, 214, 213, 217, 183, 201, 202, 203, 220, 240, 190, 195, 209, 222, 205, 207, 208, 224, 241, 210, 223, 225, 233, 227, 216, 191, 219, 194, 199, 242, 200, 193, 232, 245, 192, 226, 211, 244, 238, 215, 196, 235, 228, 230, 236, 234, 85: 197, 90: 184, 198, 93: 438, 189, 96: 188, 186, 437, 187, 185}, + {1: 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 76: 175}, + // 260 + {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 76: 173}, } ) @@ -890,7 +898,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) { } func yyhintParse(yylex yyhintLexer, parser *hintParser) int { - const yyError = 113 + const yyError = 114 yyEx, _ := yylex.(yyhintLexerEx) var yyn int diff --git a/parser/hintparser.y b/parser/hintparser.y index 0938acff9df22..76f986bce7262 100644 --- a/parser/hintparser.y +++ b/parser/hintparser.y @@ -108,6 +108,7 @@ import ( hintForceIndex "FORCE_INDEX" hintStraightJoin "STRAIGHT_JOIN" hintLeading "LEADING" + hintSemiJoinRewrite "SEMI_JOIN_REWRITE" /* Other keywords */ hintOLAP "OLAP" @@ -585,6 +586,7 @@ NullaryHintName: | "READ_CONSISTENT_REPLICA" | "IGNORE_PLAN_CACHE" | "STRAIGHT_JOIN" +| "SEMI_JOIN_REWRITE" HintQueryType: "OLAP" @@ -652,6 +654,7 @@ Identifier: | "FORCE_INDEX" | "STRAIGHT_JOIN" | "LEADING" +| "SEMI_JOIN_REWRITE" /* other keywords */ | "OLAP" | "OLTP" diff --git a/parser/hintparser_test.go b/parser/hintparser_test.go index 2c9156f579128..30d8d2c1ea803 100644 --- a/parser/hintparser_test.go +++ b/parser/hintparser_test.go @@ -261,7 +261,7 @@ func TestParseHint(t *testing.T) { }, }, { - input: "READ_FROM_STORAGE(@foo TIKV[a, b], TIFLASH[c, d]) HASH_AGG() READ_FROM_STORAGE(TIKV[e])", + input: "READ_FROM_STORAGE(@foo TIKV[a, b], TIFLASH[c, d]) HASH_AGG() SEMI_JOIN_REWRITE() READ_FROM_STORAGE(TIKV[e])", output: []*ast.TableOptimizerHint{ { HintName: model.NewCIStr("READ_FROM_STORAGE"), @@ -284,6 +284,9 @@ func TestParseHint(t *testing.T) { { HintName: model.NewCIStr("HASH_AGG"), }, + { + HintName: model.NewCIStr("SEMI_JOIN_REWRITE"), + }, { HintName: model.NewCIStr("READ_FROM_STORAGE"), HintData: model.NewCIStr("TIKV"), diff --git a/parser/misc.go b/parser/misc.go index 171eb81db3b8d..6c54150896578 100644 --- a/parser/misc.go +++ b/parser/misc.go @@ -942,6 +942,7 @@ var hintTokenMap = map[string]int{ "FORCE_INDEX": hintForceIndex, "STRAIGHT_JOIN": hintStraightJoin, "LEADING": hintLeading, + "SEMI_JOIN_REWRITE": hintSemiJoinRewrite, // TiDB hint aliases "TIDB_HJ": hintHashJoin, diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go index 67f97245075bb..9b27b112f0bda 100644 --- a/planner/core/expression_rewriter.go +++ b/planner/core/expression_rewriter.go @@ -315,7 +315,9 @@ func (er *expressionRewriter) constructBinaryOpFunction(l expression.Expression, } } -func (er *expressionRewriter) buildSubquery(ctx context.Context, subq *ast.SubqueryExpr) (LogicalPlan, error) { +// buildSubquery translates the subquery ast to plan. +// Currently, only the EXIST can apply the rewrite hint(rewrite the semi join to inner join with aggregation). +func (er *expressionRewriter) buildSubquery(ctx context.Context, subq *ast.SubqueryExpr, rewriteHintCanTakeEffect bool) (np LogicalPlan, hasSemiJoinRewriteHint bool, err error) { if er.schema != nil { outerSchema := er.schema.Clone() er.b.outerSchemas = append(er.b.outerSchemas, outerSchema) @@ -325,18 +327,25 @@ func (er *expressionRewriter) buildSubquery(ctx context.Context, subq *ast.Subqu er.b.outerNames = er.b.outerNames[0 : len(er.b.outerNames)-1] }() } + // Store the old value before we enter the subquery and reset they to default value. + oldRewriteHintCanTakeEffect := er.b.checkSemiJoinHint + er.b.checkSemiJoinHint = rewriteHintCanTakeEffect + oldHasHint := er.b.hasValidSemiJoinHint + er.b.hasValidSemiJoinHint = false outerWindowSpecs := er.b.windowSpecs defer func() { er.b.windowSpecs = outerWindowSpecs + er.b.checkSemiJoinHint = oldRewriteHintCanTakeEffect + er.b.hasValidSemiJoinHint = oldHasHint }() - np, err := er.b.buildResultSetNode(ctx, subq.Query) + np, err = er.b.buildResultSetNode(ctx, subq.Query) if err != nil { - return nil, err + return nil, false, err } // Pop the handle map generated by the subquery. er.b.handleHelper.popMap() - return np, nil + return np, er.b.hasValidSemiJoinHint, nil } // Enter implements Visitor interface. @@ -500,7 +509,7 @@ func (er *expressionRewriter) buildSemiApplyFromEqualSubq(np LogicalPlan, l, r e if er.err != nil { return } - er.p, er.err = er.b.buildSemiApply(er.p, np, []expression.Expression{condition}, er.asScalar, not) + er.p, er.err = er.b.buildSemiApply(er.p, np, []expression.Expression{condition}, er.asScalar, not, false) } func (er *expressionRewriter) handleCompareSubquery(ctx context.Context, v *ast.CompareSubqueryExpr) (ast.Node, bool) { @@ -516,7 +525,7 @@ func (er *expressionRewriter) handleCompareSubquery(ctx context.Context, v *ast. er.err = errors.Errorf("Unknown compare type %T", v.R) return v, true } - np, err := er.buildSubquery(ctx, subq) + np, _, err := er.buildSubquery(ctx, subq, false) if err != nil { er.err = err return v, true @@ -690,7 +699,7 @@ func (er *expressionRewriter) buildQuantifierPlan(plan4Agg *LogicalAggregation, // plan4Agg.buildProjectionIfNecessary() if !er.asScalar { // For Semi LogicalApply without aux column, the result is no matter false or null. So we can add it to join predicate. - er.p, er.err = er.b.buildSemiApply(er.p, plan4Agg, []expression.Expression{cond}, false, false) + er.p, er.err = er.b.buildSemiApply(er.p, plan4Agg, []expression.Expression{cond}, false, false, false) return } // If we treat the result as a scalar value, we will add a projection with a extra column to output true, false or null. @@ -810,14 +819,14 @@ func (er *expressionRewriter) handleExistSubquery(ctx context.Context, v *ast.Ex er.err = errors.Errorf("Unknown exists type %T", v.Sel) return v, true } - np, err := er.buildSubquery(ctx, subq) + np, hasRewriteHint, err := er.buildSubquery(ctx, subq, true) if err != nil { er.err = err return v, true } np = er.popExistsSubPlan(np) if len(ExtractCorrelatedCols4LogicalPlan(np)) > 0 { - er.p, er.err = er.b.buildSemiApply(er.p, np, nil, er.asScalar, v.Not) + er.p, er.err = er.b.buildSemiApply(er.p, np, nil, er.asScalar, v.Not, hasRewriteHint) if er.err != nil || !er.asScalar { return v, true } @@ -884,7 +893,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte er.err = errors.Errorf("Unknown compare type %T", v.Sel) return v, true } - np, err := er.buildSubquery(ctx, subq) + np, _, err := er.buildSubquery(ctx, subq, false) if err != nil { er.err = err return v, true @@ -968,7 +977,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte } er.p = join } else { - er.p, er.err = er.b.buildSemiApply(er.p, np, expression.SplitCNFItems(checkCondition), asScalar, v.Not) + er.p, er.err = er.b.buildSemiApply(er.p, np, expression.SplitCNFItems(checkCondition), asScalar, v.Not, false) if er.err != nil { return v, true } @@ -985,7 +994,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte func (er *expressionRewriter) handleScalarSubquery(ctx context.Context, v *ast.SubqueryExpr) (ast.Node, bool) { ci := er.b.prepareCTECheckForSubQuery() defer resetCTECheckForSubQuery(ci) - np, err := er.buildSubquery(ctx, v) + np, _, err := er.buildSubquery(ctx, v, false) if err != nil { er.err = err return v, true diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 92c2a3dbcfd80..81fe7209c7e78 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -117,6 +117,8 @@ const ( HintIgnorePlanCache = "ignore_plan_cache" // HintLimitToCop is a hint enforce pushing limit or topn to coprocessor. HintLimitToCop = "limit_to_cop" + // HintSemiJoinRewrite is a hint to force we rewrite the semi join operator as much as possible. + HintSemiJoinRewrite = "semi_join_rewrite" ) const ( @@ -3626,6 +3628,12 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev leadingJoinOrder = append(leadingJoinOrder, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...) } leadingHintCnt++ + case HintSemiJoinRewrite: + if !b.checkSemiJoinHint { + b.ctx.GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack("The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause.")) + continue + } + b.hasValidSemiJoinHint = true default: // ignore hints that not implemented } @@ -4866,10 +4874,10 @@ func (b *PlanBuilder) buildApplyWithJoinType(outerPlan, innerPlan LogicalPlan, t } // buildSemiApply builds apply plan with outerPlan and innerPlan, which apply semi-join for every row from outerPlan and the whole innerPlan. -func (b *PlanBuilder) buildSemiApply(outerPlan, innerPlan LogicalPlan, condition []expression.Expression, asScalar, not bool) (LogicalPlan, error) { +func (b *PlanBuilder) buildSemiApply(outerPlan, innerPlan LogicalPlan, condition []expression.Expression, asScalar, not, considerRewrite bool) (LogicalPlan, error) { b.optFlag = b.optFlag | flagPredicatePushDown | flagBuildKeyInfo | flagDecorrelate - join, err := b.buildSemiJoin(outerPlan, innerPlan, condition, asScalar, not) + join, err := b.buildSemiJoin(outerPlan, innerPlan, condition, asScalar, not, considerRewrite) if err != nil { return nil, err } @@ -4905,7 +4913,7 @@ func (b *PlanBuilder) buildMaxOneRow(p LogicalPlan) LogicalPlan { return maxOneRow } -func (b *PlanBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onCondition []expression.Expression, asScalar bool, not bool) (*LogicalJoin, error) { +func (b *PlanBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onCondition []expression.Expression, asScalar, not, forceRewrite bool) (*LogicalJoin, error) { joinPlan := LogicalJoin{}.Init(b.ctx, b.getSelectOffset()) for i, expr := range onCondition { onCondition[i] = expr.Decorrelate(outerPlan.Schema()) @@ -4959,6 +4967,10 @@ func (b *PlanBuilder) buildSemiJoin(outerPlan, innerPlan LogicalPlan, onConditio return nil, errors.New("Join hints are conflict, you can only specify one type of join") } } + if forceRewrite { + joinPlan.preferJoinType |= preferRewriteSemiJoin + b.optFlag |= flagSemiJoinRewrite + } return joinPlan, nil } diff --git a/planner/core/logical_plan_test.go b/planner/core/logical_plan_test.go index 0a73522baa9a3..7b616411b3e2c 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -506,7 +506,7 @@ func TestSubquery(t *testing.T) { p, _, err := BuildLogicalPlanForTest(ctx, s.ctx, stmt, s.is) require.NoError(t, err) if lp, ok := p.(LogicalPlan); ok { - p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain, lp) + p, err = logicalOptimize(context.TODO(), flagBuildKeyInfo|flagDecorrelate|flagPrunColumns|flagPrunColumnsAgain|flagSemiJoinRewrite, lp) require.NoError(t, err) } testdata.OnRecord(func() { diff --git a/planner/core/logical_plans.go b/planner/core/logical_plans.go index 48b4da2e96cd6..909f950798ce9 100644 --- a/planner/core/logical_plans.go +++ b/planner/core/logical_plans.go @@ -117,6 +117,7 @@ const ( preferHashJoin preferMergeJoin preferBCJoin + preferRewriteSemiJoin preferHashAgg preferStreamAgg ) diff --git a/planner/core/optimizer.go b/planner/core/optimizer.go index 20d4fd598e701..24c95d7ad60a8 100644 --- a/planner/core/optimizer.go +++ b/planner/core/optimizer.go @@ -58,6 +58,7 @@ const ( flagStabilizeResults flagBuildKeyInfo flagDecorrelate + flagSemiJoinRewrite flagEliminateAgg flagEliminateProjection flagMaxMinEliminate @@ -78,6 +79,7 @@ var optRuleList = []logicalOptRule{ &resultReorder{}, &buildKeySolver{}, &decorrelateSolver{}, + &semiJoinRewriter{}, &aggregationEliminator{}, &projectionEliminator{}, &maxMinEliminator{}, diff --git a/planner/core/physical_plan_test.go b/planner/core/physical_plan_test.go index fe5c5cba7da00..ec9c71d6fa245 100644 --- a/planner/core/physical_plan_test.go +++ b/planner/core/physical_plan_test.go @@ -911,6 +911,57 @@ func TestAggregationHints(t *testing.T) { } } +func TestSemiJoinRewriteHints(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t(a int, b int, c int)") + + sessionVars := tk.Session().GetSessionVars() + sessionVars.SetHashAggFinalConcurrency(1) + sessionVars.SetHashAggPartialConcurrency(1) + + var input []string + var output []struct { + SQL string + Plan []string + Warning string + } + planSuiteData := core.GetPlanSuiteData() + planSuiteData.GetTestCases(t, &input, &output) + ctx := context.Background() + p := parser.New() + is := infoschema.MockInfoSchema([]*model.TableInfo{core.MockSignedTable(), core.MockUnsignedTable()}) + for i, test := range input { + comment := fmt.Sprintf("case: %v sql: %v", i, test) + tk.Session().GetSessionVars().StmtCtx.SetWarnings(nil) + + stmt, err := p.ParseOneStmt(test, "", "") + require.NoError(t, err, comment) + + _, _, err = planner.Optimize(ctx, tk.Session(), stmt, is) + require.NoError(t, err) + warnings := tk.Session().GetSessionVars().StmtCtx.GetWarnings() + + testdata.OnRecord(func() { + output[i].SQL = test + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief'" + test).Rows()) + if len(warnings) > 0 { + output[i].Warning = warnings[0].Err.Error() + } + }) + tk.MustQuery("explain format = 'brief'" + test).Check(testkit.Rows(output[i].Plan...)) + if output[i].Warning == "" { + require.Len(t, warnings, 0) + } else { + require.Len(t, warnings, 1, fmt.Sprintf("%v", warnings)) + require.Equal(t, stmtctx.WarnLevelWarning, warnings[0].Level) + require.Equal(t, output[i].Warning, warnings[0].Err.Error()) + } + } +} + func TestExplainJoinHints(t *testing.T) { store, clean := testkit.CreateMockStore(t) defer clean() diff --git a/planner/core/physical_plan_trace_test.go b/planner/core/physical_plan_trace_test.go index 9988fb6cacfa9..30cb5d6d1a976 100644 --- a/planner/core/physical_plan_trace_test.go +++ b/planner/core/physical_plan_trace_test.go @@ -83,9 +83,7 @@ func TestPhysicalOptimizeWithTraceEnabled(t *testing.T) { domain.GetDomain(sctx).MockInfoCacheAndLoadInfoSchema(dom.InfoSchema()) plan, err := builder.Build(context.TODO(), stmt) require.NoError(t, err) - flag := uint64(0) - flag = flag | 1<<3 | 1<<8 - _, _, err = core.DoOptimize(context.TODO(), sctx, flag, plan.(core.LogicalPlan)) + _, _, err = core.DoOptimize(context.TODO(), sctx, builder.GetOptFlag(), plan.(core.LogicalPlan)) require.NoError(t, err) otrace := sctx.GetSessionVars().StmtCtx.OptimizeTracer.Physical require.NotNil(t, otrace) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 4f574a6010b63..9b1a1fbe0206b 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -501,6 +501,15 @@ type PlanBuilder struct { allocIDForCTEStorage int buildingRecursivePartForCTE bool buildingCTE bool + + // checkSemiJoinHint checks whether the SEMI_JOIN_REWRITE hint is possible to be applied on the current SELECT stmt. + // We need this variable for the hint since the hint is set in subquery, but we check its availability in its outer scope. + // e.g. select * from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t1 where t.a=t1.a) + // Whether the hint can be applied or not is checked after the subquery is fully built. + checkSemiJoinHint bool + // hasValidSemijoinHint would tell the outer APPLY/JOIN operator that there's valid hint to be checked later + // if there's SEMI_JOIN_REWRITE hint and we find checkSemiJoinHint is true. + hasValidSemiJoinHint bool } type handleColHelper struct { diff --git a/planner/core/rule_build_key_info.go b/planner/core/rule_build_key_info.go index 22ec84d150bc4..361a821c8f2cd 100644 --- a/planner/core/rule_build_key_info.go +++ b/planner/core/rule_build_key_info.go @@ -48,6 +48,10 @@ func (la *LogicalAggregation) BuildKeyInfo(selfSchema *expression.Schema, childS return } la.logicalSchemaProducer.BuildKeyInfo(selfSchema, childSchema) + la.buildSelfKeyInfo(selfSchema) +} + +func (la *LogicalAggregation) buildSelfKeyInfo(selfSchema *expression.Schema) { groupByCols := la.GetGroupByCols() if len(groupByCols) == len(la.GroupByItems) && len(la.GroupByItems) > 0 { indices := selfSchema.ColumnsIndices(groupByCols) diff --git a/planner/core/rule_semi_join_rewrite.go b/planner/core/rule_semi_join_rewrite.go new file mode 100644 index 0000000000000..0bce68183b59e --- /dev/null +++ b/planner/core/rule_semi_join_rewrite.go @@ -0,0 +1,115 @@ +// Copyright 2022 PingCAP, Inc. +// +// 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. + +package core + +import ( + "context" + + "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/expression/aggregation" + "github.com/pingcap/tidb/parser/ast" +) + +type semiJoinRewriter struct { +} + +func (smj *semiJoinRewriter) optimize(_ context.Context, p LogicalPlan, opt *logicalOptimizeOp) (LogicalPlan, error) { + return smj.recursivePlan(p) +} + +func (smj *semiJoinRewriter) name() string { + return "semi_join_rewrite" +} + +func (smj *semiJoinRewriter) recursivePlan(p LogicalPlan) (LogicalPlan, error) { + newChildren := make([]LogicalPlan, 0, len(p.Children())) + for _, child := range p.Children() { + newChild, err := smj.recursivePlan(child) + if err != nil { + return nil, err + } + newChildren = append(newChildren, newChild) + } + p.SetChildren(newChildren...) + join, ok := p.(*LogicalJoin) + // If it's not a join, or not a (outer) semi join. We just return it since no optimization is needed. + // Actually the check of the preferRewriteSemiJoin is a superset of checking the join type. We remain them for a better understanding. + if !ok || !(join.JoinType == SemiJoin || join.JoinType == LeftOuterSemiJoin) || (join.preferJoinType&preferRewriteSemiJoin == 0) { + return p, nil + } + + if join.JoinType == LeftOuterSemiJoin { + p.SCtx().GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack("SEMI_JOIN_REWRITE() is inapplicable for LeftOuterSemiJoin.")) + return p, nil + } + + // If we have jumped the above if condition. We can make sure that the current join is a non-correlated one. + + // If there's left condition or other condition, we cannot rewrite + if len(join.LeftConditions) > 0 || len(join.OtherConditions) > 0 { + p.SCtx().GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack("SEMI_JOIN_REWRITE() is inapplicable for SemiJoin with left conditions or other conditions.")) + return p, nil + } + + innerChild := join.Children()[1] + + // If there's right conditions: + // - If it's semi join, then right condition should be pushed. + // - If it's outer semi join, then it still should be pushed since the outer join should not remain any cond of the inner side. + // But the aggregation we added may block the predicate push down since we've not maintained the functional dependency to pass the equiv class to guide the push down. + // So we create a selection before we build the aggregation. + if len(join.RightConditions) > 0 { + sel := LogicalSelection{Conditions: make([]expression.Expression, len(join.RightConditions))}.Init(p.SCtx(), innerChild.SelectBlockOffset()) + copy(sel.Conditions, join.RightConditions) + sel.SetChildren(innerChild) + innerChild = sel + } + + subAgg := LogicalAggregation{ + AggFuncs: make([]*aggregation.AggFuncDesc, 0, len(join.EqualConditions)), + GroupByItems: make([]expression.Expression, 0, len(join.EqualConditions)), + }.Init(p.SCtx(), p.Children()[1].SelectBlockOffset()) + + aggOutputCols := make([]*expression.Column, 0, len(join.EqualConditions)) + for i := range join.EqualConditions { + innerCol := join.EqualConditions[i].GetArgs()[1].(*expression.Column) + firstRow, err := aggregation.NewAggFuncDesc(join.SCtx(), ast.AggFuncFirstRow, []expression.Expression{innerCol}, false) + if err != nil { + return nil, err + } + subAgg.AggFuncs = append(subAgg.AggFuncs, firstRow) + subAgg.GroupByItems = append(subAgg.GroupByItems, innerCol) + aggOutputCols = append(aggOutputCols, innerCol) + } + subAgg.SetChildren(innerChild) + subAgg.SetSchema(expression.NewSchema(aggOutputCols...)) + subAgg.buildSelfKeyInfo(subAgg.Schema()) + + innerJoin := LogicalJoin{ + JoinType: InnerJoin, + EqualConditions: make([]*expression.ScalarFunction, 0, len(join.EqualConditions)), + }.Init(p.SCtx(), p.SelectBlockOffset()) + innerJoin.SetChildren(join.Children()[0], subAgg) + innerJoin.SetSchema(expression.MergeSchema(join.Children()[0].Schema(), subAgg.schema)) + innerJoin.AttachOnConds(expression.ScalarFuncs2Exprs(join.EqualConditions)) + + proj := LogicalProjection{ + Exprs: expression.Column2Exprs(join.Children()[0].Schema().Columns), + }.Init(p.SCtx(), p.SelectBlockOffset()) + proj.SetChildren(innerJoin) + proj.SetSchema(join.Children()[0].Schema()) + + return proj, nil +} diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index dc2b7b07239e1..d729efb623635 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -285,7 +285,9 @@ "cases": [ // Query with WHERE or ON should have the same plan, i.e, the Apply has been decorrelated. "explain format = 'brief' select * from t where exists (select 1 from t t1 join t t2 where t1.a = t2.a and t1.a = t.a)", - "explain format = 'brief' select * from t where exists (select 1 from t t1 join t t2 on t1.a = t2.a and t1.a = t.a)" + "explain format = 'brief' select * from t where exists (select 1 from t t1 join t t2 on t1.a = t2.a and t1.a = t.a)", + "explain format = 'brief' select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 join t t2 where t1.a = t2.a and t1.a = t.a)", + "explain format = 'brief' select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 join t t2 on t1.a = t2.a and t1.a = t.a)" ] }, { @@ -509,6 +511,8 @@ "explain format = 'brief' select count(*) from fact_t right join d1_t on fact_t.d1_k = d1_t.d1_k and d1_t.value > 10 and fact_t.col1 > d1_t.value", "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k)", "explain format = 'brief' select count(*) from fact_t where exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "explain format = 'brief' select count(*) from fact_t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from d1_t where d1_k = fact_t.d1_k)", + "explain format = 'brief' select count(*) from fact_t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", "explain format = 'brief' select count(*) from fact_t join d1_t on fact_t.d1_k > d1_t.d1_k", diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 22e3d3d4f582d..fe0f0d0a6586a 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -1535,6 +1535,34 @@ "└─TableReader(Probe) 10000.00 root data:TableFullScan", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ] + }, + { + "SQL": "explain format = 'brief' select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 join t t2 where t1.a = t2.a and t1.a = t.a)", + "Plan": [ + "HashJoin 10000.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 8000.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─HashJoin 12500.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ] + }, + { + "SQL": "explain format = 'brief' select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 join t t2 on t1.a = t2.a and t1.a = t.a)", + "Plan": [ + "HashJoin 10000.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 8000.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─HashJoin 12500.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ] } ] }, @@ -3019,6 +3047,40 @@ " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" ] }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from d1_t where d1_k = fact_t.d1_k)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 8.00 root data:ExchangeSender", + " └─ExchangeSender 8.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 8.00 mpp[tiflash] inner join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)]", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Projection 2.00 mpp[tiflash] test.d1_t.d1_k", + " │ └─HashAgg 2.00 mpp[tiflash] group by:test.d1_t.d1_k, funcs:firstrow(test.d1_t.d1_k)->test.d1_t.d1_k", + " │ └─ExchangeReceiver 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: HashPartition, Hash Cols: [name: test.d1_t.d1_k, collate: binary]", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, + { + "SQL": "explain format = 'brief' select count(*) from fact_t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from d1_t where d1_k = fact_t.d1_k and value > fact_t.col1)", + "Plan": [ + "StreamAgg 1.00 root funcs:count(1)->Column#12", + "└─TableReader 6.40 root data:ExchangeSender", + " └─ExchangeSender 6.40 mpp[tiflash] ExchangeType: PassThrough", + " └─HashJoin 6.40 mpp[tiflash] semi join, equal:[eq(test.fact_t.d1_k, test.d1_t.d1_k)], other cond:gt(test.d1_t.value, test.fact_t.col1)", + " ├─ExchangeReceiver(Build) 2.00 mpp[tiflash] ", + " │ └─ExchangeSender 2.00 mpp[tiflash] ExchangeType: Broadcast", + " │ └─Selection 2.00 mpp[tiflash] not(isnull(test.d1_t.d1_k)), not(isnull(test.d1_t.value))", + " │ └─TableFullScan 2.00 mpp[tiflash] table:d1_t keep order:false", + " └─Selection(Probe) 8.00 mpp[tiflash] not(isnull(test.fact_t.col1)), not(isnull(test.fact_t.d1_k))", + " └─TableFullScan 8.00 mpp[tiflash] table:fact_t keep order:false" + ] + }, { "SQL": "explain format = 'brief' select count(*) from fact_t where not exists (select 1 from d1_t where d1_k = fact_t.d1_k)", "Plan": [ diff --git a/planner/core/testdata/plan_suite_in.json b/planner/core/testdata/plan_suite_in.json index ce4c38cbc695d..627621aa1bfe6 100644 --- a/planner/core/testdata/plan_suite_in.json +++ b/planner/core/testdata/plan_suite_in.json @@ -783,5 +783,16 @@ "select * from employee e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.deptid = e2.d", "select * from (select deptid+1 d, count(empid) a from employee group by d) e1 join (select deptid+1 d, count(empid) a from employee group by d) e2 on e1.d = e2.d" ] + }, + { + "name": "TestSemiJoinRewriteHints", + "cases": [ + "select /*+ SEMI_JOIN_REWRITE() */ * from t", + "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)", + "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)", + "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ t.b from t t1 where t1.a=t.a)", + "select exists(select /*+ SEMI_JOIN_REWRITE() */ * from t t1 where t1.a=t.a) from t", + "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a > t.a)" + ] } ] diff --git a/planner/core/testdata/plan_suite_out.json b/planner/core/testdata/plan_suite_out.json index 43c97667fd49d..49b92cb6e9afa 100644 --- a/planner/core/testdata/plan_suite_out.json +++ b/planner/core/testdata/plan_suite_out.json @@ -3078,5 +3078,86 @@ ] } ] + }, + { + "Name": "TestSemiJoinRewriteHints", + "Cases": [ + { + "SQL": "select /*+ SEMI_JOIN_REWRITE() */ * from t", + "Plan": [ + "TableReader 10000.00 root data:TableFullScan", + "└─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause." + }, + { + "SQL": "select * from t where a > (select /*+ SEMI_JOIN_REWRITE() */ min(b) from t t1 where t1.c = t.c)", + "Plan": [ + "HashJoin 7992.00 root inner join, equal:[eq(test.t.c, test.t.c)], other cond:gt(test.t.a, Column#9)", + "├─Selection(Build) 6393.60 root not(isnull(Column#9))", + "│ └─HashAgg 7992.00 root group by:test.t.c, funcs:min(Column#10)->Column#9, funcs:firstrow(test.t.c)->test.t.c", + "│ └─TableReader 7992.00 root data:HashAgg", + "│ └─HashAgg 7992.00 cop[tikv] group by:test.t.c, funcs:min(test.t.b)->Column#10", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.c))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9980.01 root data:Selection", + " └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.c))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]The SEMI_JOIN_REWRITE hint is not used correctly, maybe it's not in a subquery or the subquery is not EXISTS clause." + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a=t.a)", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 7992.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "" + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ t.b from t t1 where t1.a=t.a)", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, test.t.a)]", + "├─HashAgg(Build) 7992.00 root group by:test.t.a, funcs:firstrow(test.t.a)->test.t.a", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "" + }, + { + "SQL": "select exists(select /*+ SEMI_JOIN_REWRITE() */ * from t t1 where t1.a=t.a) from t", + "Plan": [ + "HashJoin 10000.00 root left outer semi join, equal:[eq(test.t.a, test.t.a)]", + "├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for LeftOuterSemiJoin." + }, + { + "SQL": "select * from t where exists (select /*+ SEMI_JOIN_REWRITE() */ 1 from t t1 where t1.a > t.a)", + "Plan": [ + "HashJoin 7992.00 root CARTESIAN semi join, other cond:gt(test.t.a, test.t.a)", + "├─TableReader(Build) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warning": "[planner:1815]SEMI_JOIN_REWRITE() is inapplicable for SemiJoin with left conditions or other conditions." + } + ] } ] diff --git a/planner/core/testdata/plan_suite_unexported_in.json b/planner/core/testdata/plan_suite_unexported_in.json index 0e68e3cd27deb..7c934c7be798f 100644 --- a/planner/core/testdata/plan_suite_unexported_in.json +++ b/planner/core/testdata/plan_suite_unexported_in.json @@ -137,6 +137,17 @@ "select t1.b from t t1 where t1.b = (select max(t2.a) from t t2 where t1.b=t2.b order by t1.a)", "select t1.b from t t1 where t1.b in (select t2.b from t t2 where t2.a = t1.a order by t2.a)", "select t1.b from t t1 where exists(select t2.b from t t2 where t2.a = t1.a order by t2.a)", + "select t1.b from t t1 where exists(select /*+ SEMI_JOIN_REWRITE() */ t2.b from t t2 where t2.a = t1.a order by t2.a)", + "select a from t where exists(select 1 from t as x where x.a < t.a)", + "select a from t where exists(select 1 from t as x where x.a = t.a and t.a < 1 and x.a < 1)", + "select a from t where exists(select 1 from t as x where x.a = t.a and x.a < 1) and a < 1", + "select a from t where exists(select 1 from t as x where x.a = t.a) and exists(select 1 from t as x where x.a = t.a)", + "select a from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a < t.a)", + "select a from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a and t.a < 1 and x.a < 1)", + "select a from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a and x.a < 1) and a < 1", + "select a from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a) and exists(select 1 from t as x where x.a = t.a)", + "select a from t where exists(select 1 from t as x where x.a = t.a) and exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a)", + "select a from t where exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a) and exists(select /*+ SEMI_JOIN_REWRITE() */ 1 from t as x where x.a = t.a)", // `Sort` will not be eliminated, if it is not the top level operator. "select t1.b from t t1 where t1.b = (select t2.b from t t2 where t2.a = t1.a order by t2.a limit 1)", "select (select 1 from t t1 where t1.a = t2.a) from t t2", diff --git a/planner/core/testdata/plan_suite_unexported_out.json b/planner/core/testdata/plan_suite_unexported_out.json index 562fcacf94547..ce05997328fde 100644 --- a/planner/core/testdata/plan_suite_unexported_out.json +++ b/planner/core/testdata/plan_suite_unexported_out.json @@ -124,6 +124,17 @@ "Join{DataScan(t1)->DataScan(t2)->Aggr(max(test.t.a),firstrow(test.t.b))}(test.t.b,test.t.b)->Projection->Sel([eq(test.t.b, Column#25)])->Projection", "Join{DataScan(t1)->DataScan(t2)}(test.t.a,test.t.a)(test.t.b,test.t.b)->Projection", "Join{DataScan(t1)->DataScan(t2)}(test.t.a,test.t.a)->Projection", + "Join{DataScan(t1)->DataScan(t2)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->Projection", + "Join{DataScan(t)->DataScan(x)}->Projection", + "Join{DataScan(t)->DataScan(x)}(test.t.a,test.t.a)->Projection", + "Join{DataScan(t)->DataScan(x)}(test.t.a,test.t.a)->Sel([lt(test.t.a, 1)])->Projection", + "Join{Join{DataScan(t)->DataScan(x)}(test.t.a,test.t.a)->DataScan(x)}(test.t.a,test.t.a)->Projection", + "Join{DataScan(t)->DataScan(x)}->Projection", + "Join{DataScan(t)->DataScan(x)}(test.t.a,test.t.a)->Projection", + "Join{DataScan(t)->DataScan(x)->Sel([lt(test.t.a, 1)])->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->Sel([lt(test.t.a, 1)])->Projection", + "Join{Join{DataScan(t)->DataScan(x)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->DataScan(x)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->Projection", + "Join{Join{DataScan(t)->DataScan(x)}(test.t.a,test.t.a)->DataScan(x)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->Projection", + "Join{Join{DataScan(t)->DataScan(x)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->DataScan(x)->Aggr(firstrow(test.t.a))}(test.t.a,test.t.a)->Projection->Projection", "Apply{DataScan(t1)->DataScan(t2)->Sel([eq(test.t.a, test.t.a)])->Projection->Sort->Limit}->Projection->Sel([eq(test.t.b, test.t.b)])->Projection", "Apply{DataScan(t2)->DataScan(t1)->Sel([eq(test.t.a, test.t.a)])->Projection}->Projection", "Join{DataScan(t2)->DataScan(t1)->Aggr(firstrow(test.t.c),count(1))}(test.t.c,test.t.c)->Projection->Aggr(count(1))->Projection" diff --git a/testkit/testkit.go b/testkit/testkit.go index 912b5292dad10..4b47dd61f4b96 100644 --- a/testkit/testkit.go +++ b/testkit/testkit.go @@ -186,6 +186,28 @@ func (tk *TestKit) HasPlan(sql string, plan string, args ...interface{}) bool { return false } +// HasKeywordInOperatorInfo checks if the result execution plan contains specific keyword in the operator info. +func (tk *TestKit) HasKeywordInOperatorInfo(sql string, keyword string, args ...interface{}) bool { + rs := tk.MustQuery("explain "+sql, args...) + for i := range rs.rows { + if strings.Contains(rs.rows[i][4], keyword) { + return true + } + } + return false +} + +// NotHasKeywordInOperatorInfo checks if the result execution plan doesn't contain specific keyword in the operator info. +func (tk *TestKit) NotHasKeywordInOperatorInfo(sql string, keyword string, args ...interface{}) bool { + rs := tk.MustQuery("explain "+sql, args...) + for i := range rs.rows { + if strings.Contains(rs.rows[i][4], keyword) { + return false + } + } + return true +} + // HasPlan4ExplainFor checks if the result execution plan contains specific plan. func (tk *TestKit) HasPlan4ExplainFor(result *Result, plan string) bool { for i := range result.rows {