diff --git a/pkg/pb/plan/plan.pb.go b/pkg/pb/plan/plan.pb.go index d501a6a6a4634..5a4e8e3945bb3 100644 --- a/pkg/pb/plan/plan.pb.go +++ b/pkg/pb/plan/plan.pb.go @@ -6000,6 +6000,8 @@ type UpdateCtx struct { InsertPkColIdx int32 `protobuf:"varint,11,opt,name=insert_pk_col_idx,json=insertPkColIdx,proto3" json:"insert_pk_col_idx,omitempty"` CountDeleteAffectRows bool `protobuf:"varint,12,opt,name=count_delete_affect_rows,json=countDeleteAffectRows,proto3" json:"count_delete_affect_rows,omitempty"` IgnoreAffectedRows bool `protobuf:"varint,13,opt,name=ignore_affected_rows,json=ignoreAffectedRows,proto3" json:"ignore_affected_rows,omitempty"` + DedupByTargetRowId bool `protobuf:"varint,14,opt,name=dedup_by_target_row_id,json=dedupByTargetRowId,proto3" json:"dedup_by_target_row_id,omitempty"` + TargetUpdateCtxIdx int32 `protobuf:"varint,15,opt,name=target_update_ctx_idx,json=targetUpdateCtxIdx,proto3" json:"target_update_ctx_idx,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -6101,6 +6103,20 @@ func (m *UpdateCtx) GetIgnoreAffectedRows() bool { return false } +func (m *UpdateCtx) GetDedupByTargetRowId() bool { + if m != nil { + return m.DedupByTargetRowId + } + return false +} + +func (m *UpdateCtx) GetTargetUpdateCtxIdx() int32 { + if m != nil { + return m.TargetUpdateCtxIdx + } + return 0 +} + type InsertCtx struct { Ref *ObjectRef `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` AddAffectedRows bool `protobuf:"varint,2,opt,name=add_affected_rows,json=addAffectedRows,proto3" json:"add_affected_rows,omitempty"` @@ -14650,919 +14666,921 @@ func init() { func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } var fileDescriptor_2d655ab2f7683c23 = []byte{ - // 14579 bytes of a gzipped FileDescriptorProto + // 14620 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x6d, 0x8c, 0x1b, 0xd9, 0xb6, 0x28, 0xd4, 0x6e, 0xdb, 0x6d, 0x7b, 0xf9, 0xa3, 0xab, 0x77, 0x3a, 0x89, 0x93, 0xc9, 0x24, 0x9d, 0x4a, 0x26, 0x93, 0xc9, 0xcc, 0x64, 0x66, 0x92, 0xf9, 0xc8, 0x9c, 0x7b, 0xee, 0x9b, 0xe3, 0xb6, 0xdd, 0xdd, 0x9e, 0xb8, 0xed, 0x3e, 0x65, 0x77, 0x32, 0x73, 0x1e, 0x57, 0xa5, 0x6a, 0x57, 0xd9, 0x5d, 0xd3, 0xe5, 0x2a, 0x4f, 0x55, 0x39, 0xdd, 0x7d, 0xa4, 0x27, 0x8e, 0xf8, 0x71, 0x1f, - 0x0f, 0xf8, 0x81, 0x84, 0x80, 0x5f, 0x4f, 0xba, 0x20, 0x21, 0x24, 0x04, 0x42, 0xa0, 0x2b, 0x2e, - 0x4f, 0x48, 0xc0, 0x15, 0x7f, 0x1e, 0xe2, 0x43, 0xc0, 0x13, 0x20, 0x40, 0x7a, 0xc0, 0xe5, 0x2f, - 0x4f, 0x20, 0x81, 0x84, 0xc4, 0x1f, 0xd0, 0x5a, 0x7b, 0xef, 0xfa, 0xb0, 0x9d, 0xc9, 0xcc, 0x9c, - 0x73, 0xa5, 0xf7, 0xa7, 0xdb, 0x7b, 0xad, 0xb5, 0xbf, 0xd7, 0x5e, 0x7b, 0xed, 0xb5, 0xd7, 0x5e, - 0x05, 0x30, 0x73, 0x0c, 0xf7, 0xf1, 0xcc, 0xf7, 0x42, 0x8f, 0xe5, 0xf0, 0xf7, 0xcd, 0x0f, 0x27, - 0x76, 0x78, 0x3a, 0x3f, 0x79, 0x3c, 0xf2, 0xa6, 0x1f, 0x4d, 0xbc, 0x89, 0xf7, 0x11, 0x21, 0x4f, - 0xe6, 0x63, 0x4a, 0x51, 0x82, 0x7e, 0xf1, 0x4c, 0x37, 0xc1, 0xf1, 0x46, 0x67, 0xe2, 0xf7, 0x66, - 0x68, 0x4f, 0xad, 0x20, 0x34, 0xa6, 0x33, 0x0e, 0x50, 0xff, 0x22, 0x03, 0xb9, 0xe1, 0xe5, 0xcc, - 0x62, 0x35, 0x58, 0xb7, 0xcd, 0x7a, 0x66, 0x27, 0xf3, 0x30, 0xaf, 0xad, 0xdb, 0x26, 0xdb, 0x81, - 0xb2, 0xeb, 0x85, 0xbd, 0xb9, 0xe3, 0x18, 0x27, 0x8e, 0x55, 0x5f, 0xdf, 0xc9, 0x3c, 0x2c, 0x6a, - 0x49, 0x10, 0x7b, 0x0b, 0x4a, 0xc6, 0x3c, 0xf4, 0x74, 0xdb, 0x1d, 0xf9, 0xf5, 0x2c, 0xe1, 0x8b, - 0x08, 0xe8, 0xb8, 0x23, 0x9f, 0x6d, 0x43, 0xfe, 0xdc, 0x36, 0xc3, 0xd3, 0x7a, 0x8e, 0x4a, 0xe4, - 0x09, 0x84, 0x06, 0x23, 0xc3, 0xb1, 0xea, 0x79, 0x0e, 0xa5, 0x04, 0x42, 0x43, 0xaa, 0x64, 0x63, - 0x27, 0xf3, 0xb0, 0xa4, 0xf1, 0x04, 0xbb, 0x0d, 0x60, 0xb9, 0xf3, 0xe9, 0x2b, 0xc3, 0x99, 0x5b, - 0x41, 0xbd, 0x40, 0xa8, 0x04, 0x44, 0xfd, 0x0a, 0x4a, 0xd3, 0x60, 0x72, 0x60, 0x19, 0xa6, 0xe5, - 0xb3, 0xeb, 0x50, 0x98, 0x06, 0x13, 0x3d, 0x34, 0x26, 0xa2, 0x0b, 0x1b, 0xd3, 0x60, 0x32, 0x34, - 0x26, 0xec, 0x06, 0x14, 0x09, 0x71, 0x39, 0xe3, 0x7d, 0xc8, 0x6b, 0x48, 0x88, 0x3d, 0x56, 0xff, - 0xce, 0x06, 0x14, 0xba, 0x76, 0x68, 0xf9, 0x86, 0xc3, 0xae, 0xc1, 0x86, 0x1d, 0xb8, 0x73, 0xc7, - 0xa1, 0xec, 0x45, 0x4d, 0xa4, 0xd8, 0x35, 0xc8, 0xdb, 0xcf, 0x5e, 0x19, 0x0e, 0xcf, 0x7b, 0xb0, - 0xa6, 0xf1, 0x24, 0xab, 0xc3, 0x86, 0xfd, 0xc9, 0xe7, 0x88, 0xc8, 0x0a, 0x84, 0x48, 0x13, 0xe6, - 0xe9, 0x13, 0xc4, 0xe4, 0x22, 0x0c, 0xa5, 0x09, 0xf3, 0xf9, 0xa7, 0x88, 0xc1, 0xde, 0x67, 0x09, - 0x43, 0x69, 0xac, 0x65, 0x4e, 0xb5, 0xe0, 0x00, 0x54, 0xb1, 0x96, 0xb9, 0xac, 0x65, 0xce, 0x6b, - 0x29, 0x08, 0x84, 0x48, 0x13, 0x86, 0xd7, 0x52, 0x8c, 0x30, 0x51, 0x2d, 0x73, 0x5e, 0x4b, 0x69, - 0x27, 0xf3, 0x30, 0x47, 0x18, 0x5e, 0xcb, 0x36, 0xe4, 0x4c, 0x84, 0xc3, 0x4e, 0xe6, 0x61, 0xe6, - 0x60, 0x4d, 0xa3, 0x14, 0x42, 0x03, 0x84, 0x96, 0x71, 0x80, 0x11, 0x1a, 0x08, 0xe8, 0x09, 0x42, - 0x2b, 0x38, 0x1a, 0x08, 0x3d, 0x11, 0xd0, 0x31, 0x42, 0xab, 0x3b, 0x99, 0x87, 0xeb, 0x08, 0xc5, - 0x14, 0xbb, 0x09, 0x05, 0xd3, 0x08, 0x2d, 0x44, 0xd4, 0x44, 0x97, 0x25, 0x00, 0x71, 0xc8, 0x71, - 0x88, 0xdb, 0x14, 0x9d, 0x96, 0x00, 0xa6, 0x42, 0x19, 0xc9, 0x24, 0x5e, 0x11, 0xf8, 0x24, 0x90, - 0x7d, 0x06, 0x15, 0xd3, 0x1a, 0xd9, 0x53, 0xc3, 0xe1, 0x7d, 0xda, 0xda, 0xc9, 0x3c, 0x2c, 0x3f, - 0xd9, 0x7c, 0x4c, 0x6b, 0x22, 0xc2, 0x1c, 0xac, 0x69, 0x29, 0x32, 0xf6, 0x0c, 0xaa, 0x22, 0xfd, - 0xc9, 0x13, 0x1a, 0x58, 0x46, 0xf9, 0x94, 0x54, 0xbe, 0x4f, 0x9e, 0x3c, 0x3b, 0x58, 0xd3, 0xd2, - 0x84, 0xec, 0x3e, 0x54, 0xa2, 0x25, 0x82, 0x19, 0xaf, 0x88, 0x56, 0xa5, 0xa0, 0xd8, 0xad, 0xef, - 0x02, 0xcf, 0x45, 0x82, 0x6d, 0x31, 0x6e, 0x12, 0xc0, 0x76, 0x00, 0x4c, 0x6b, 0x6c, 0xcc, 0x9d, - 0x10, 0xd1, 0x57, 0xc5, 0x00, 0x26, 0x60, 0xec, 0x36, 0x94, 0xe6, 0x33, 0xec, 0xe5, 0x0b, 0xc3, - 0xa9, 0x5f, 0x13, 0x04, 0x31, 0x08, 0x4b, 0x47, 0x3e, 0x47, 0xec, 0x75, 0x31, 0xbb, 0x12, 0x80, - 0xd3, 0xfb, 0xca, 0x1a, 0x21, 0xaa, 0x2e, 0x2a, 0x16, 0x69, 0x5c, 0x45, 0x76, 0xb0, 0x6b, 0xbb, - 0xf5, 0x1b, 0xc4, 0xc1, 0x3c, 0xc1, 0x6e, 0x41, 0x36, 0xf0, 0x47, 0xf5, 0x9b, 0xd4, 0x7f, 0xe0, - 0xfd, 0x6f, 0x5f, 0xcc, 0x7c, 0x0d, 0xc1, 0xbb, 0x05, 0xc8, 0xd3, 0x6a, 0x52, 0x6f, 0x41, 0xf1, - 0xc8, 0xf0, 0x8d, 0xa9, 0x66, 0x8d, 0x99, 0x02, 0xd9, 0x99, 0x17, 0x88, 0x75, 0x84, 0x3f, 0xd5, - 0x2e, 0x6c, 0xbc, 0x30, 0x7c, 0xc4, 0x31, 0xc8, 0xb9, 0xc6, 0xd4, 0x22, 0x64, 0x49, 0xa3, 0xdf, - 0xb8, 0x76, 0x82, 0xcb, 0x20, 0xb4, 0xa6, 0x42, 0x48, 0x88, 0x14, 0xc2, 0x27, 0x8e, 0x77, 0x22, - 0xd6, 0x48, 0x51, 0x13, 0x29, 0xf5, 0x9f, 0xca, 0xc0, 0x46, 0xd3, 0x73, 0xb0, 0xb8, 0xeb, 0x50, - 0xf0, 0x2d, 0x47, 0x8f, 0xab, 0xdb, 0xf0, 0x2d, 0xe7, 0xc8, 0x0b, 0x10, 0x31, 0xf2, 0x38, 0x82, - 0xaf, 0xda, 0x8d, 0x91, 0x47, 0x08, 0xd9, 0x80, 0x6c, 0xa2, 0x01, 0x37, 0xa0, 0x18, 0x9e, 0x38, - 0x3a, 0xc1, 0x73, 0x04, 0x2f, 0x84, 0x27, 0x4e, 0x0f, 0x51, 0xd7, 0xa1, 0x60, 0x9e, 0x70, 0x4c, - 0x9e, 0x30, 0x1b, 0xe6, 0x09, 0x22, 0xd4, 0x2f, 0xa1, 0xa4, 0x19, 0xe7, 0xa2, 0x19, 0x57, 0x61, - 0x03, 0x0b, 0x10, 0xf2, 0x2f, 0xa7, 0xe5, 0xc3, 0x13, 0xa7, 0x63, 0x22, 0x18, 0x1b, 0x61, 0x9b, - 0xd4, 0x86, 0x9c, 0x96, 0x1f, 0x79, 0x4e, 0xc7, 0x54, 0x87, 0x00, 0x4d, 0xcf, 0xf7, 0x7f, 0x76, - 0x17, 0xb6, 0x21, 0x6f, 0x5a, 0xb3, 0xf0, 0x94, 0x8b, 0x0e, 0x8d, 0x27, 0xd4, 0x47, 0x50, 0xc4, - 0x79, 0xe9, 0xda, 0x41, 0xc8, 0x6e, 0x43, 0xce, 0xb1, 0x83, 0xb0, 0x9e, 0xd9, 0xc9, 0x2e, 0xcc, - 0x1a, 0xc1, 0xd5, 0x1d, 0x28, 0x1e, 0x1a, 0x17, 0x2f, 0x70, 0xe6, 0xb0, 0x34, 0x9a, 0x42, 0x31, - 0x25, 0x62, 0x3e, 0x2b, 0x00, 0x43, 0xc3, 0x9f, 0x58, 0x21, 0x49, 0xba, 0xff, 0x2b, 0x03, 0xe5, - 0xc1, 0xfc, 0xe4, 0xfb, 0xb9, 0xe5, 0x5f, 0x62, 0x9b, 0x1f, 0x42, 0x36, 0xbc, 0x9c, 0x51, 0x8e, - 0xda, 0x93, 0x6b, 0xbc, 0xf8, 0x04, 0xfe, 0x31, 0x66, 0xd2, 0x90, 0x04, 0x3b, 0xe1, 0x7a, 0xa6, - 0x25, 0xc7, 0x20, 0xaf, 0x6d, 0x60, 0xb2, 0x63, 0xe2, 0x76, 0xe1, 0xcd, 0xc4, 0x2c, 0xac, 0x7b, - 0x33, 0xb6, 0x03, 0xf9, 0xd1, 0xa9, 0xed, 0x98, 0x34, 0x01, 0xe9, 0x36, 0x73, 0x04, 0xce, 0x92, - 0xef, 0x9d, 0xeb, 0x81, 0xfd, 0x5b, 0x29, 0xfe, 0x0b, 0xbe, 0x77, 0x3e, 0xb0, 0x7f, 0x6b, 0xa9, - 0x43, 0xb1, 0x07, 0x01, 0x6c, 0x0c, 0x9a, 0x8d, 0x6e, 0x43, 0x53, 0xd6, 0xf0, 0x77, 0xfb, 0x9b, - 0xce, 0x60, 0x38, 0x50, 0x32, 0xac, 0x06, 0xd0, 0xeb, 0x0f, 0x75, 0x91, 0x5e, 0x67, 0x1b, 0xb0, - 0xde, 0xe9, 0x29, 0x59, 0xa4, 0x41, 0x78, 0xa7, 0xa7, 0xe4, 0x58, 0x01, 0xb2, 0x8d, 0xde, 0xb7, - 0x4a, 0x9e, 0x7e, 0x74, 0xbb, 0xca, 0x86, 0xfa, 0xff, 0xae, 0x43, 0xa9, 0x7f, 0xf2, 0x9d, 0x35, - 0x0a, 0xb1, 0xcf, 0xc8, 0xa5, 0x96, 0xff, 0xca, 0xf2, 0xa9, 0xdb, 0x59, 0x4d, 0xa4, 0xb0, 0x23, - 0xe6, 0x09, 0x75, 0x2e, 0xab, 0xad, 0x9b, 0x27, 0x44, 0x37, 0x3a, 0xb5, 0xa6, 0x06, 0x75, 0x0e, - 0xe9, 0x28, 0x85, 0xab, 0xc2, 0x3b, 0xf9, 0x8e, 0xba, 0x97, 0xd5, 0xf0, 0x27, 0xbb, 0x03, 0x65, - 0x5e, 0x46, 0x92, 0xbf, 0x80, 0x83, 0x16, 0x99, 0x6f, 0x23, 0xc9, 0x7c, 0x94, 0x93, 0x4a, 0xe5, - 0x48, 0xb1, 0xb7, 0x71, 0x50, 0x4f, 0x70, 0xb4, 0x77, 0xf2, 0x1d, 0xc7, 0x16, 0x39, 0x47, 0x7b, - 0x27, 0xdf, 0x11, 0xea, 0x7d, 0xd8, 0x0a, 0xe6, 0x27, 0xc1, 0xc8, 0xb7, 0x67, 0xa1, 0xed, 0xb9, - 0x9c, 0xa6, 0x44, 0x34, 0x4a, 0x12, 0x41, 0xc4, 0x0f, 0xa1, 0x38, 0x9b, 0x9f, 0xe8, 0xb6, 0x3b, - 0xf6, 0x48, 0xec, 0x97, 0x9f, 0x54, 0xf9, 0xc4, 0x1c, 0xcd, 0x4f, 0x3a, 0xee, 0xd8, 0xd3, 0x0a, - 0x33, 0xfe, 0x83, 0xa9, 0x50, 0x75, 0xbd, 0x50, 0x47, 0x55, 0x41, 0x9f, 0x5a, 0xa1, 0x41, 0xfb, - 0x01, 0xdf, 0xf0, 0xbb, 0xde, 0xe8, 0xec, 0xd0, 0x0a, 0x0d, 0xf6, 0x08, 0x8a, 0x81, 0x6b, 0xcc, - 0x82, 0x53, 0x2f, 0xa4, 0x8d, 0xa1, 0xfc, 0xa4, 0x26, 0x78, 0x47, 0x40, 0xb5, 0x08, 0xaf, 0x3e, - 0x80, 0x82, 0xa8, 0x03, 0xf5, 0x84, 0xd0, 0x72, 0x0d, 0x37, 0xd4, 0x23, 0x05, 0xa3, 0xc8, 0x01, - 0x1d, 0x53, 0xfd, 0xf3, 0x0c, 0x28, 0x83, 0x44, 0xb3, 0xa9, 0xa2, 0x55, 0x52, 0xe6, 0x6d, 0x00, - 0x63, 0x34, 0xf2, 0xe6, 0xbc, 0x18, 0xce, 0x8c, 0x25, 0x01, 0xe9, 0x98, 0xc9, 0xb1, 0xce, 0xa6, - 0xc6, 0xfa, 0x2e, 0x54, 0x64, 0xbe, 0x84, 0x80, 0x28, 0x0b, 0x98, 0x1c, 0xed, 0x60, 0x9e, 0x92, - 0x12, 0x85, 0x60, 0xce, 0x73, 0x5f, 0x83, 0x0d, 0xd2, 0x46, 0x02, 0x39, 0x83, 0x3c, 0xa5, 0xfe, - 0xf7, 0x19, 0xa8, 0x76, 0x5c, 0xd3, 0xba, 0x18, 0x8c, 0x0c, 0x57, 0x0e, 0xa0, 0x1d, 0xe8, 0x36, - 0xc2, 0xf4, 0x60, 0x64, 0xb8, 0x42, 0x91, 0x28, 0xdb, 0x41, 0x44, 0x87, 0x7d, 0xe0, 0x04, 0x54, - 0xd5, 0x3a, 0x95, 0x58, 0x22, 0x08, 0x55, 0xf6, 0x00, 0x36, 0x4f, 0x2c, 0xc7, 0x73, 0x27, 0x7a, - 0xe8, 0xe9, 0x5c, 0x23, 0xe2, 0x7d, 0xa9, 0x72, 0xf0, 0xd0, 0x1b, 0x92, 0x66, 0xb4, 0x0d, 0xf9, - 0x99, 0xe1, 0x87, 0x41, 0x3d, 0xb7, 0x93, 0xc5, 0x25, 0x4f, 0x09, 0x1c, 0x66, 0x3b, 0xd0, 0xe7, - 0xae, 0xfd, 0xfd, 0x9c, 0x77, 0xa3, 0xa8, 0x15, 0xed, 0xe0, 0x98, 0xd2, 0xec, 0x21, 0x28, 0xbc, - 0x66, 0x2a, 0x36, 0xc9, 0x93, 0x35, 0x82, 0x53, 0xc1, 0x24, 0x18, 0xff, 0xf7, 0x75, 0x28, 0xee, - 0xcd, 0xdd, 0x11, 0x4e, 0x06, 0xbb, 0x07, 0xb9, 0xf1, 0xdc, 0x1d, 0x51, 0x5f, 0xa2, 0x6d, 0x37, - 0x5a, 0x53, 0x1a, 0x21, 0x51, 0x5a, 0x19, 0xfe, 0x04, 0xa5, 0xdc, 0x92, 0xb4, 0x42, 0x38, 0xcd, - 0xdc, 0x64, 0xa2, 0x8f, 0x3c, 0x77, 0x6c, 0x4f, 0xa8, 0x47, 0x15, 0xad, 0x64, 0x4c, 0x26, 0x4d, - 0x02, 0xb0, 0x06, 0x6c, 0xc6, 0x68, 0xae, 0xa8, 0xe5, 0x48, 0x30, 0xdd, 0xe0, 0x25, 0x35, 0x26, - 0x13, 0xdf, 0x9a, 0x18, 0xa1, 0xc5, 0xe9, 0x49, 0x36, 0x55, 0xa3, 0xec, 0x24, 0xdf, 0xfe, 0xfd, - 0x0c, 0x6f, 0xf3, 0x9e, 0x63, 0x4c, 0x58, 0x11, 0x72, 0xbd, 0x7e, 0xaf, 0xad, 0xac, 0xb1, 0x0a, - 0x14, 0x3b, 0xbd, 0x61, 0x5b, 0xeb, 0x35, 0xba, 0x4a, 0x86, 0x84, 0xcb, 0xb0, 0xb1, 0xdb, 0x6d, - 0x2b, 0xeb, 0x88, 0x79, 0xd1, 0xef, 0x36, 0x86, 0x9d, 0x6e, 0x5b, 0xc9, 0x71, 0x8c, 0xd6, 0x69, - 0x0e, 0x95, 0x22, 0x53, 0xa0, 0x72, 0xa4, 0xf5, 0x5b, 0xc7, 0xcd, 0xb6, 0xde, 0x3b, 0xee, 0x76, - 0x15, 0x85, 0x5d, 0x81, 0xcd, 0x08, 0xd2, 0xe7, 0xc0, 0x1d, 0xcc, 0xf2, 0xa2, 0xa1, 0x35, 0xb4, - 0x7d, 0xe5, 0x57, 0xac, 0x08, 0xd9, 0xc6, 0xfe, 0xbe, 0xf2, 0x3b, 0x94, 0x53, 0xa5, 0x97, 0x9d, - 0x9e, 0xfe, 0xa2, 0xd1, 0x3d, 0x6e, 0x2b, 0xbf, 0x5b, 0x97, 0xe9, 0xbe, 0xd6, 0x6a, 0x6b, 0xca, - 0xef, 0x72, 0x6c, 0x0b, 0x2a, 0xbf, 0xe9, 0xf7, 0xda, 0x87, 0x8d, 0xa3, 0x23, 0x6a, 0xc8, 0xef, - 0x8a, 0xea, 0x3f, 0xca, 0x41, 0x0e, 0xc7, 0x8a, 0xa9, 0xb1, 0x4c, 0x8e, 0x06, 0x11, 0x3b, 0xb7, - 0x9b, 0xfb, 0xfb, 0xff, 0xf0, 0xce, 0x1a, 0x97, 0xc6, 0x77, 0x21, 0xeb, 0xd8, 0x21, 0x31, 0x4e, - 0xb4, 0x92, 0x85, 0x06, 0x7b, 0xb0, 0xa6, 0x21, 0x8e, 0xdd, 0x86, 0x0c, 0x17, 0xcb, 0xd1, 0xe2, - 0x94, 0xfb, 0xfa, 0xc1, 0x9a, 0x96, 0x99, 0xb1, 0x5b, 0x90, 0x79, 0x25, 0x64, 0x74, 0x85, 0xe3, - 0xf9, 0xce, 0x8e, 0xd8, 0x57, 0x6c, 0x07, 0xb2, 0x23, 0x8f, 0xeb, 0xa7, 0x11, 0x9e, 0xef, 0x73, - 0x58, 0xfe, 0xc8, 0x73, 0xd8, 0x3d, 0xc8, 0xfa, 0xc6, 0x39, 0xf1, 0x4e, 0xc4, 0x10, 0xd1, 0x46, - 0x8a, 0x44, 0xbe, 0x71, 0x8e, 0x8d, 0x18, 0x93, 0x54, 0x8b, 0x1a, 0x21, 0x39, 0x0a, 0xab, 0x19, - 0xb3, 0x1d, 0xc8, 0x9c, 0x93, 0x5c, 0x8b, 0x54, 0xb2, 0x97, 0xb6, 0x6b, 0x7a, 0xe7, 0x83, 0x99, - 0x35, 0x42, 0x8a, 0x73, 0xf6, 0x0e, 0x64, 0x83, 0xf9, 0x09, 0xc9, 0xb5, 0xf2, 0x93, 0xad, 0xa5, - 0x1d, 0x0a, 0x2b, 0x0a, 0xe6, 0x27, 0xec, 0x01, 0xe4, 0x46, 0x9e, 0xef, 0x0b, 0xd9, 0xa6, 0xc8, - 0x06, 0xcb, 0xcd, 0x19, 0x55, 0x54, 0xc4, 0x63, 0x85, 0x21, 0x49, 0xb4, 0x88, 0x28, 0xde, 0x1d, - 0xb1, 0xc2, 0x90, 0xdd, 0x17, 0x5b, 0x6e, 0x4a, 0xae, 0xc9, 0x0d, 0x19, 0xcb, 0x41, 0x2c, 0x4e, - 0xd2, 0xd4, 0xb8, 0x20, 0xfd, 0x37, 0x22, 0x92, 0x3b, 0x31, 0xb6, 0x69, 0x6a, 0x5c, 0xb0, 0xfb, - 0x90, 0x7d, 0x65, 0x8d, 0x48, 0x15, 0x8e, 0x6a, 0x13, 0x93, 0xf4, 0x82, 0xba, 0x87, 0x68, 0x5a, - 0x59, 0x9e, 0x63, 0x92, 0x56, 0x1c, 0xcd, 0xe5, 0x9e, 0xe7, 0x98, 0x2f, 0x68, 0x2e, 0x09, 0x89, - 0x0a, 0x88, 0x31, 0xbf, 0x40, 0x79, 0xa7, 0x70, 0x55, 0xc1, 0x98, 0x5f, 0x74, 0x4c, 0xdc, 0x8a, - 0x5c, 0xf3, 0x15, 0xe9, 0xc2, 0x19, 0x0d, 0x7f, 0xe2, 0x61, 0x2d, 0xb0, 0x1c, 0x6b, 0x14, 0xda, - 0xaf, 0xec, 0xf0, 0x92, 0xb4, 0xdd, 0x8c, 0x96, 0x04, 0xed, 0x6e, 0x40, 0xce, 0xba, 0x98, 0xf9, - 0xea, 0x01, 0x14, 0x44, 0x2d, 0x4b, 0x27, 0xbe, 0x1b, 0x50, 0xb4, 0x03, 0x5c, 0x87, 0x41, 0x28, - 0x34, 0xb9, 0x82, 0x1d, 0x34, 0x31, 0x89, 0x02, 0xd9, 0x34, 0x42, 0x43, 0x2c, 0x5e, 0xfa, 0xad, - 0x3e, 0x01, 0x88, 0xbb, 0x85, 0x6d, 0x72, 0x2c, 0x57, 0x2a, 0x8d, 0x8e, 0xe5, 0x46, 0x79, 0xd6, - 0x13, 0x79, 0x6e, 0x40, 0x29, 0xd2, 0xd3, 0x59, 0x05, 0x32, 0x86, 0xd8, 0x8c, 0x33, 0x86, 0xfa, - 0x10, 0xd5, 0x66, 0xa9, 0x89, 0xa7, 0x71, 0x98, 0x92, 0x5b, 0x74, 0xe6, 0x44, 0xfd, 0x25, 0x54, - 0x34, 0x2b, 0x98, 0x3b, 0x61, 0xd3, 0x73, 0x5a, 0xd6, 0x98, 0x7d, 0x00, 0x10, 0xa5, 0x03, 0xa1, - 0x33, 0xc5, 0xbc, 0xdb, 0xb2, 0xc6, 0x5a, 0x02, 0xaf, 0xfe, 0xaf, 0x39, 0xd2, 0x3e, 0x5b, 0x5c, - 0xed, 0x13, 0xfa, 0x5d, 0x26, 0xa1, 0xdf, 0x45, 0xbb, 0xcf, 0x7a, 0x5a, 0xc7, 0x3d, 0xb5, 0x4d, - 0xd3, 0x72, 0xa5, 0x2e, 0xcb, 0x53, 0x38, 0xd9, 0x86, 0x33, 0x11, 0x02, 0x8b, 0xc9, 0x4a, 0xa7, - 0x33, 0xdf, 0x0a, 0x02, 0xae, 0x45, 0x19, 0xce, 0x44, 0xae, 0xed, 0xfc, 0x0f, 0xad, 0xed, 0x1b, - 0x50, 0xc4, 0x0d, 0x98, 0xce, 0xa0, 0x1b, 0x7c, 0xf4, 0xc5, 0x61, 0x9b, 0xbd, 0x0b, 0x05, 0x71, - 0x7a, 0x10, 0x8b, 0x4a, 0xb0, 0x4b, 0x8b, 0x03, 0x35, 0x89, 0x65, 0x75, 0x54, 0x39, 0xa7, 0x53, - 0xcb, 0x0d, 0xa5, 0xd6, 0x20, 0x92, 0xec, 0x7d, 0x28, 0x79, 0xae, 0xce, 0x8f, 0x18, 0x62, 0x55, - 0x09, 0xf6, 0xed, 0xbb, 0xc7, 0x04, 0xd5, 0x8a, 0x9e, 0xf8, 0x85, 0x4d, 0x71, 0xbc, 0x73, 0x7d, - 0x64, 0xf8, 0x26, 0xad, 0xac, 0xa2, 0x56, 0x70, 0xbc, 0xf3, 0xa6, 0xe1, 0x9b, 0x5c, 0x8b, 0xfa, - 0xde, 0x9d, 0x4f, 0x69, 0x35, 0x55, 0x35, 0x91, 0x62, 0xb7, 0xa0, 0x34, 0x72, 0xe6, 0x41, 0x68, - 0xf9, 0xbb, 0x97, 0xfc, 0xd0, 0xa8, 0xc5, 0x00, 0x6c, 0xd7, 0xcc, 0xb7, 0xa7, 0x86, 0x7f, 0x49, - 0x4b, 0xa7, 0xa8, 0xc9, 0x24, 0x6d, 0x65, 0x67, 0xb6, 0x79, 0xc1, 0x4f, 0x8e, 0x1a, 0x4f, 0x20, - 0xfd, 0x29, 0x9d, 0xeb, 0x03, 0x5a, 0x1f, 0x45, 0x4d, 0x26, 0x69, 0x1e, 0xe8, 0x27, 0xad, 0x88, - 0x92, 0x26, 0x52, 0xa9, 0x23, 0xc0, 0xd6, 0x6b, 0x8f, 0x00, 0x6c, 0x51, 0x0b, 0xf3, 0x7c, 0x7b, - 0x62, 0x0b, 0x1d, 0xea, 0x0a, 0xd7, 0xc2, 0x38, 0x88, 0x08, 0xbe, 0x80, 0xea, 0xc4, 0x72, 0x2d, - 0xdf, 0x08, 0x2d, 0x53, 0x47, 0xb9, 0xb8, 0x4d, 0x03, 0x27, 0xa6, 0x79, 0x5f, 0xa2, 0x50, 0xd6, - 0x54, 0x26, 0x89, 0x94, 0xfa, 0x3d, 0x14, 0xc4, 0xdc, 0xe0, 0xe6, 0x88, 0xeb, 0x2e, 0x2d, 0xd7, - 0xf9, 0xe6, 0x88, 0x70, 0x76, 0x0f, 0xaa, 0xa2, 0x11, 0x41, 0xe8, 0xdb, 0xee, 0x44, 0x70, 0x5d, - 0x85, 0x03, 0x07, 0x04, 0x43, 0x1d, 0x06, 0xf9, 0x42, 0x37, 0x4e, 0x6c, 0x07, 0xd7, 0x77, 0x56, - 0xe8, 0x66, 0x73, 0xc7, 0x69, 0x70, 0x90, 0xda, 0x87, 0xa2, 0x9c, 0xc9, 0x3f, 0x48, 0x9d, 0xea, - 0x0c, 0x2a, 0xc9, 0x1e, 0xfe, 0x61, 0x3a, 0xc2, 0x75, 0x94, 0x20, 0xf4, 0x7c, 0xcb, 0x94, 0x26, - 0x23, 0x3b, 0x18, 0x50, 0x5a, 0xfd, 0xd3, 0x0c, 0x94, 0x49, 0x57, 0xea, 0x93, 0x26, 0xc8, 0x3e, - 0x00, 0x36, 0xf2, 0x2d, 0x23, 0xb4, 0x74, 0xeb, 0x22, 0xf4, 0x0d, 0xa1, 0x11, 0x71, 0xb5, 0x4a, - 0xe1, 0x98, 0x36, 0x22, 0xb8, 0x52, 0x74, 0x07, 0xca, 0x33, 0xc3, 0x0f, 0xa4, 0x36, 0xce, 0x6b, - 0x07, 0x0e, 0x12, 0xba, 0xb0, 0xe2, 0x4e, 0x7c, 0x63, 0xaa, 0x87, 0xde, 0x99, 0xe5, 0xf2, 0x73, - 0x08, 0x3f, 0x81, 0xd5, 0x08, 0x3e, 0x44, 0x30, 0x1d, 0x47, 0xfe, 0xc7, 0x0c, 0x54, 0x8f, 0x38, - 0x83, 0x3e, 0xb7, 0x2e, 0x5b, 0xfc, 0xd8, 0x3b, 0x92, 0xc2, 0x25, 0xa7, 0xd1, 0x6f, 0x76, 0x1b, - 0xca, 0xb3, 0x33, 0xeb, 0x52, 0x4f, 0x1d, 0x11, 0x4b, 0x08, 0x6a, 0x92, 0x18, 0x79, 0x0f, 0x36, - 0x3c, 0xea, 0x88, 0xd8, 0x8e, 0xc5, 0x2e, 0x96, 0xe8, 0xa1, 0x26, 0x08, 0x50, 0x77, 0x8c, 0x8a, - 0x4a, 0x2a, 0xa9, 0xa2, 0x30, 0x6a, 0xfe, 0x36, 0xe4, 0x11, 0x15, 0xd4, 0xf3, 0x5c, 0xe9, 0xa3, - 0x04, 0xfb, 0x18, 0xaa, 0x23, 0x6f, 0x3a, 0xd3, 0x65, 0x76, 0xb1, 0x31, 0xa7, 0xc5, 0x5f, 0x19, - 0x49, 0x8e, 0x78, 0x59, 0xea, 0x5f, 0x66, 0xa1, 0x48, 0x6d, 0x10, 0x12, 0xd0, 0x36, 0x2f, 0xa4, - 0x04, 0x2c, 0x69, 0x79, 0xdb, 0xc4, 0x0d, 0xe6, 0x0d, 0x7a, 0x6a, 0xa4, 0x7f, 0x66, 0x93, 0xfa, - 0xe7, 0x35, 0xd8, 0x10, 0xca, 0x67, 0x8e, 0x8b, 0xc8, 0xf9, 0xeb, 0x55, 0xcf, 0xfc, 0x2a, 0xd5, - 0x13, 0xa7, 0x90, 0xd3, 0x58, 0x17, 0xb8, 0x15, 0x73, 0x29, 0x08, 0x04, 0x6a, 0x23, 0x24, 0x29, - 0xdf, 0x0a, 0x69, 0xf9, 0x56, 0x87, 0xc2, 0x2b, 0x3b, 0xb0, 0x91, 0x41, 0x8a, 0x5c, 0x62, 0x88, - 0x64, 0x62, 0x1a, 0x4a, 0x6f, 0x9a, 0x86, 0xa8, 0xdb, 0x86, 0x33, 0xe1, 0xe7, 0x25, 0xd9, 0xed, - 0x86, 0x33, 0xf1, 0xd8, 0x27, 0x70, 0x35, 0x46, 0x8b, 0xde, 0x90, 0xba, 0x4a, 0xa6, 0x33, 0x8d, - 0x45, 0x94, 0xd4, 0x23, 0x3a, 0xd0, 0x3e, 0x82, 0xad, 0x44, 0x96, 0x19, 0x6a, 0x62, 0x01, 0x89, - 0xc7, 0x92, 0xb6, 0x19, 0x91, 0x93, 0x82, 0x16, 0xb0, 0xf7, 0x70, 0x9c, 0x46, 0xce, 0xdc, 0xe4, - 0xc2, 0x66, 0x3e, 0x75, 0x83, 0x7a, 0x95, 0x06, 0x78, 0x53, 0xc2, 0x9b, 0x1c, 0xac, 0xfe, 0xa7, - 0xeb, 0x50, 0xdd, 0xf3, 0x7c, 0xcb, 0x9e, 0xb8, 0x31, 0x83, 0x2e, 0x9d, 0x98, 0x24, 0xd3, 0xae, - 0x27, 0x98, 0xf6, 0x0e, 0x94, 0xc7, 0x3c, 0xa3, 0x1e, 0x9e, 0x70, 0xc3, 0x4c, 0x4e, 0x03, 0x01, - 0x1a, 0x9e, 0x38, 0x28, 0x6a, 0x24, 0x01, 0x65, 0xce, 0x51, 0x66, 0x99, 0x09, 0x77, 0x50, 0xf6, - 0x0b, 0xda, 0x4b, 0x4c, 0xcb, 0xb1, 0x42, 0x3e, 0x93, 0xb5, 0x27, 0x6f, 0x4b, 0xfd, 0x25, 0xd1, - 0xa6, 0xc7, 0x9a, 0x35, 0x6e, 0x90, 0xd2, 0x87, 0x5b, 0x4b, 0x8b, 0xc8, 0x45, 0x5e, 0xb1, 0x0f, - 0x6d, 0xfc, 0xc8, 0xbc, 0x5c, 0xac, 0xa9, 0x43, 0x28, 0x45, 0x60, 0xd4, 0xe0, 0xb5, 0xb6, 0xd0, - 0xda, 0xd7, 0x58, 0x19, 0x0a, 0xcd, 0xc6, 0xa0, 0xd9, 0x68, 0xb5, 0x95, 0x0c, 0xa2, 0x06, 0xed, - 0x21, 0xd7, 0xd4, 0xd7, 0xd9, 0x26, 0x94, 0x31, 0xd5, 0x6a, 0xef, 0x35, 0x8e, 0xbb, 0x43, 0x25, - 0xcb, 0xaa, 0x50, 0xea, 0xf5, 0xf5, 0x46, 0x73, 0xd8, 0xe9, 0xf7, 0x94, 0x9c, 0xaa, 0x43, 0xb1, - 0x79, 0x6a, 0x8d, 0xce, 0x5e, 0x37, 0x8a, 0x64, 0xd8, 0xb0, 0x46, 0x67, 0x42, 0xeb, 0x5e, 0x30, - 0x6c, 0x58, 0xa3, 0x33, 0x64, 0x1b, 0x29, 0xf9, 0xbe, 0x77, 0xc4, 0x89, 0xad, 0x24, 0xc4, 0xde, - 0xf7, 0x8e, 0xda, 0x86, 0xd2, 0x91, 0xe1, 0x87, 0x36, 0x35, 0xfb, 0x19, 0x54, 0xa3, 0x44, 0xcb, - 0x1a, 0x4b, 0x75, 0x85, 0x45, 0xaa, 0x7a, 0x84, 0xd2, 0xd2, 0x84, 0xea, 0x07, 0x50, 0x49, 0x02, - 0xd8, 0x2d, 0xc8, 0x9a, 0xd6, 0x78, 0x85, 0x38, 0x46, 0xb0, 0xfa, 0x02, 0x2a, 0x4d, 0xb9, 0xfd, - 0xbe, 0xae, 0x67, 0x4f, 0xa0, 0x46, 0xb2, 0x63, 0x74, 0x22, 0x85, 0xc7, 0xfa, 0x0a, 0xe1, 0x51, - 0x41, 0x9a, 0xe6, 0x89, 0x90, 0x1e, 0x9f, 0x41, 0xf9, 0xc8, 0xf7, 0x66, 0x96, 0x1f, 0x52, 0xb1, - 0x0a, 0x64, 0xcf, 0xac, 0x4b, 0x51, 0x2a, 0xfe, 0x8c, 0xcd, 0x51, 0xeb, 0x49, 0x73, 0xd4, 0x13, - 0x28, 0xca, 0x6c, 0x3f, 0x3a, 0xcf, 0x57, 0x28, 0x84, 0x29, 0x8f, 0x6d, 0x05, 0x58, 0xd9, 0x63, - 0x80, 0x59, 0x04, 0x10, 0x03, 0x27, 0xcf, 0x38, 0xa2, 0x70, 0x2d, 0x41, 0xa1, 0xbe, 0x0d, 0x85, - 0x17, 0xb6, 0x75, 0x2e, 0xba, 0xff, 0xca, 0xb6, 0xce, 0x65, 0xf7, 0xf1, 0xb7, 0xfa, 0xff, 0x94, - 0xa0, 0x48, 0x2b, 0xb5, 0xf5, 0x7a, 0x0b, 0xe0, 0x4f, 0x51, 0x05, 0x77, 0xc4, 0x72, 0xcb, 0xad, - 0x50, 0x40, 0xf9, 0xe2, 0x7b, 0x1b, 0x20, 0x21, 0x35, 0xb8, 0x0c, 0x2c, 0x85, 0x91, 0xb0, 0x40, - 0x1d, 0x8a, 0x76, 0x35, 0x64, 0x23, 0x7e, 0x38, 0x8f, 0x01, 0xec, 0x31, 0xd7, 0x70, 0xe8, 0x38, - 0xce, 0xb5, 0xc0, 0x2b, 0xf2, 0x24, 0x73, 0xe2, 0x58, 0xf2, 0x7c, 0x45, 0x6a, 0x0f, 0x26, 0x48, - 0x22, 0x5a, 0x7e, 0x80, 0x82, 0x8f, 0xae, 0x08, 0x34, 0x99, 0x64, 0xef, 0x42, 0x0e, 0xb7, 0x0b, - 0x71, 0x1e, 0xba, 0x22, 0x47, 0x30, 0xb1, 0xdf, 0x69, 0x44, 0xc0, 0x1e, 0x42, 0x81, 0x84, 0x94, - 0x85, 0x32, 0x2b, 0x31, 0xda, 0x72, 0xfb, 0xd0, 0x24, 0x9a, 0xbd, 0x07, 0xf9, 0xf1, 0x99, 0x75, - 0xc9, 0x05, 0x56, 0x54, 0x66, 0x6a, 0x49, 0x6b, 0x9c, 0x82, 0xdd, 0x87, 0x9a, 0x6f, 0x8d, 0x75, - 0xb2, 0x09, 0xa2, 0x0c, 0x0a, 0xea, 0x35, 0x12, 0x31, 0x15, 0xdf, 0x1a, 0x37, 0x11, 0x38, 0x3c, - 0x71, 0x02, 0xf6, 0x00, 0x36, 0x68, 0x71, 0xa1, 0x02, 0x98, 0xa8, 0x59, 0xae, 0x54, 0x4d, 0x60, - 0xd9, 0x27, 0x00, 0x42, 0xcd, 0xd4, 0x4f, 0x2e, 0xc9, 0x96, 0x1e, 0x2d, 0xa6, 0x24, 0xff, 0x27, - 0x95, 0xd1, 0x77, 0x21, 0x8f, 0x4c, 0x12, 0xd4, 0xaf, 0x53, 0xc9, 0x5b, 0x69, 0x0e, 0xa2, 0x96, - 0x12, 0x9e, 0x3d, 0x84, 0x22, 0x32, 0x0a, 0xad, 0xea, 0x7a, 0x52, 0xef, 0x16, 0x5c, 0x85, 0x7b, - 0x8c, 0x75, 0x3e, 0xf8, 0xde, 0x61, 0x8f, 0x20, 0x67, 0xe2, 0x62, 0xbe, 0x41, 0x25, 0x5e, 0x4b, - 0xcc, 0x0b, 0xca, 0xb2, 0x96, 0x35, 0xa6, 0xa3, 0x00, 0xd1, 0xb0, 0x03, 0xa8, 0x21, 0x1b, 0x3d, - 0x21, 0xb5, 0x01, 0x87, 0xaf, 0x7e, 0x93, 0x72, 0xdd, 0x5d, 0xc8, 0xd5, 0x13, 0x44, 0x34, 0xd8, - 0x6d, 0x37, 0xf4, 0x2f, 0xb5, 0xaa, 0x9b, 0x84, 0xb1, 0x9b, 0x78, 0x5e, 0xeb, 0x7a, 0xa3, 0x33, - 0xcb, 0xac, 0xbf, 0x25, 0x75, 0x29, 0x9e, 0x66, 0x5f, 0x42, 0x95, 0x18, 0x0b, 0x93, 0x58, 0x79, - 0xfd, 0x16, 0xc9, 0xda, 0x24, 0xcb, 0x48, 0x94, 0x96, 0xa6, 0xc4, 0x1d, 0xc0, 0x0e, 0xf4, 0xd0, - 0x9a, 0xce, 0x3c, 0x1f, 0x35, 0xf6, 0xb7, 0xa5, 0x1d, 0x6b, 0x28, 0x41, 0xb8, 0xa5, 0x47, 0x37, - 0x7f, 0xba, 0x37, 0x1e, 0x07, 0x56, 0x58, 0xbf, 0x4d, 0xeb, 0xa6, 0x26, 0x2f, 0x00, 0xfb, 0x04, - 0xa5, 0x2d, 0x35, 0xd0, 0xcd, 0x4b, 0xd7, 0x98, 0xda, 0xa3, 0xfa, 0x1d, 0x7e, 0x30, 0xb0, 0x83, - 0x16, 0x07, 0x24, 0x75, 0xf3, 0x9d, 0x94, 0x6e, 0x7e, 0x05, 0xf2, 0xe6, 0x09, 0x2e, 0xc7, 0xbb, - 0x54, 0x6c, 0xce, 0x3c, 0xe9, 0x98, 0xec, 0x43, 0x28, 0xcd, 0xa4, 0x08, 0xac, 0xab, 0x49, 0x0b, - 0x44, 0x24, 0x19, 0xb5, 0x98, 0x02, 0x0f, 0xc5, 0x7b, 0x96, 0x11, 0xce, 0x7d, 0x6b, 0xcf, 0x31, - 0x26, 0xf5, 0x7b, 0x54, 0x52, 0x12, 0x84, 0xad, 0x73, 0xbc, 0x89, 0x3d, 0x32, 0x68, 0xe5, 0xdf, - 0xe7, 0x1a, 0x9c, 0x80, 0x74, 0xcc, 0x58, 0xa5, 0x35, 0x84, 0x5a, 0xf6, 0x4e, 0x52, 0xa5, 0x35, - 0x1c, 0x69, 0xb4, 0x8b, 0xc7, 0xc2, 0x9a, 0x79, 0xa3, 0xd3, 0xfa, 0x03, 0x5a, 0x6f, 0x55, 0x39, - 0x14, 0x6d, 0x04, 0xde, 0xdc, 0xa7, 0x33, 0x01, 0x8d, 0xf0, 0x67, 0x0b, 0x82, 0x2c, 0xb5, 0x0c, - 0x13, 0x12, 0xef, 0x60, 0x2d, 0x29, 0xcf, 0x76, 0xf3, 0x24, 0xf1, 0x6f, 0xfe, 0x0a, 0xd8, 0x32, - 0x6f, 0xbc, 0x49, 0xaa, 0xe6, 0x85, 0x54, 0xfd, 0xc5, 0xfa, 0xb3, 0x8c, 0xfa, 0xdf, 0x65, 0xa0, - 0x9a, 0x92, 0x1a, 0x2b, 0xb7, 0x07, 0xae, 0xe5, 0x19, 0x53, 0x71, 0x80, 0xe7, 0x09, 0xa9, 0xc1, - 0xdb, 0xee, 0x44, 0x58, 0x27, 0xb9, 0x06, 0x4f, 0x69, 0xf6, 0x15, 0x5c, 0x19, 0xcf, 0x1d, 0x27, - 0xb4, 0x2e, 0x42, 0x3d, 0xf0, 0xe6, 0xfe, 0xc8, 0xd2, 0x7d, 0x6b, 0x2c, 0xcc, 0x4d, 0x4b, 0xd6, - 0xc3, 0x2d, 0x49, 0x3b, 0x20, 0x52, 0xcd, 0x1a, 0xb3, 0x3f, 0x06, 0x16, 0x15, 0xc0, 0x15, 0x27, - 0xcc, 0x9f, 0x5f, 0x9d, 0x5f, 0x91, 0xa4, 0x34, 0x0c, 0x9a, 0x35, 0x56, 0xff, 0xcb, 0x2c, 0x54, - 0x0e, 0x8c, 0xe0, 0xf4, 0xd0, 0x98, 0x0d, 0x42, 0x23, 0x0c, 0x90, 0x97, 0x4f, 0x8d, 0xe0, 0x74, - 0x6a, 0xcc, 0xb8, 0xbe, 0x9f, 0xe1, 0x86, 0x11, 0x01, 0x43, 0x65, 0x1f, 0x57, 0x11, 0x26, 0xfb, - 0xee, 0xd1, 0x73, 0x61, 0xf5, 0x88, 0xd2, 0x28, 0x43, 0x83, 0xd3, 0xf9, 0x78, 0x1c, 0x75, 0x55, - 0x26, 0xd9, 0x7d, 0xa8, 0x8a, 0x9f, 0xa4, 0xec, 0x5f, 0x88, 0x6b, 0xee, 0x34, 0x90, 0x3d, 0x85, - 0xb2, 0x00, 0x0c, 0xa5, 0xc4, 0xaf, 0x45, 0xd6, 0xac, 0x18, 0xa1, 0x25, 0xa9, 0xd8, 0xaf, 0xe1, - 0x6a, 0x22, 0xb9, 0xe7, 0xf9, 0x87, 0x73, 0x27, 0xb4, 0x9b, 0x3d, 0xa1, 0x2e, 0xbd, 0xb5, 0x94, - 0x3d, 0x26, 0xd1, 0x56, 0xe7, 0x4c, 0xb7, 0xf6, 0xd0, 0x76, 0x69, 0x03, 0xc9, 0x6a, 0x69, 0xe0, - 0x02, 0x95, 0x71, 0x41, 0xfb, 0x46, 0x9a, 0xca, 0xb8, 0x40, 0xc9, 0x22, 0x00, 0x87, 0x56, 0x78, - 0xea, 0x99, 0xa4, 0x56, 0x47, 0x92, 0x65, 0x90, 0x44, 0x69, 0x69, 0x4a, 0x1c, 0x4e, 0x3c, 0xb2, - 0x8e, 0xdc, 0x90, 0x94, 0xeb, 0xac, 0x26, 0x93, 0xb8, 0xa7, 0xfa, 0x86, 0x3b, 0xb1, 0x82, 0x7a, - 0x79, 0x27, 0xfb, 0x30, 0xa3, 0x89, 0x94, 0xfa, 0xaf, 0xad, 0x43, 0x9e, 0xcf, 0xe4, 0x5b, 0x50, - 0x3a, 0xa1, 0xcb, 0x09, 0x77, 0x3e, 0x95, 0x97, 0x08, 0x04, 0xe8, 0xcd, 0xa7, 0x5c, 0xd3, 0x15, - 0x56, 0xab, 0x8c, 0x46, 0xbf, 0xb1, 0x48, 0x6f, 0x1e, 0x62, 0x5d, 0x59, 0x82, 0x8a, 0x14, 0x36, - 0xc2, 0xf7, 0xce, 0x89, 0x1b, 0x72, 0x84, 0x90, 0x49, 0xba, 0xa7, 0xa0, 0xed, 0x19, 0x33, 0xe5, - 0x09, 0x57, 0x24, 0x40, 0xd3, 0x0d, 0x17, 0x2d, 0x6c, 0x1b, 0x4b, 0x16, 0x36, 0x76, 0x1b, 0x50, - 0x8f, 0x1e, 0x59, 0x7d, 0xd7, 0x6a, 0xf6, 0x68, 0x84, 0x8b, 0x5a, 0x02, 0x82, 0x2b, 0xd4, 0xf4, - 0x66, 0x34, 0xa8, 0x79, 0x0d, 0x7f, 0xb2, 0xcf, 0x23, 0xee, 0xa4, 0x3e, 0x8a, 0x03, 0x8a, 0xd8, - 0xbe, 0x92, 0x7c, 0xac, 0xa5, 0xe8, 0xb0, 0x24, 0xdc, 0x93, 0xf8, 0x01, 0x05, 0x7f, 0xaa, 0x6d, - 0x00, 0xcd, 0x3b, 0x0f, 0xac, 0x90, 0x4c, 0xc9, 0xd7, 0xa9, 0x8b, 0xa9, 0x2b, 0x49, 0xef, 0xfc, - 0xc8, 0x0b, 0xa2, 0x33, 0xfc, 0xfa, 0xea, 0x33, 0xbc, 0xfa, 0x11, 0x14, 0x50, 0x61, 0x31, 0x42, - 0x83, 0xdd, 0x17, 0xd6, 0x3b, 0xae, 0x66, 0x09, 0x33, 0x66, 0x5c, 0x87, 0xb0, 0xe7, 0x75, 0x65, - 0xbd, 0x94, 0xe7, 0x6e, 0xe2, 0x94, 0x1c, 0x6d, 0x96, 0xa2, 0x40, 0xa1, 0x02, 0xbd, 0x05, 0x25, - 0x6c, 0x1a, 0xdd, 0xbd, 0x08, 0xc1, 0x54, 0xf4, 0xbd, 0xf3, 0x26, 0xa6, 0xd5, 0xff, 0x29, 0x03, - 0xe5, 0xbe, 0x6f, 0xe2, 0x2e, 0x3d, 0x98, 0x59, 0xa3, 0x37, 0x9a, 0x1c, 0x50, 0x61, 0xf2, 0x1c, - 0xc7, 0xa0, 0xfd, 0x40, 0x9c, 0x52, 0x23, 0x00, 0xfb, 0x04, 0x72, 0x63, 0x94, 0xfb, 0xd9, 0xe4, - 0x29, 0x23, 0x51, 0xbc, 0xfc, 0x8d, 0x3b, 0x81, 0x46, 0xa4, 0xea, 0xdf, 0x8c, 0xea, 0xa7, 0xed, - 0x21, 0x79, 0x7f, 0xb0, 0x46, 0xf7, 0x8a, 0x83, 0xa6, 0x92, 0x61, 0x45, 0xc8, 0xb5, 0xda, 0x83, - 0x26, 0x3f, 0x5b, 0xe0, 0x29, 0x63, 0xa0, 0xef, 0x75, 0xb4, 0xc1, 0x50, 0xc9, 0xd1, 0x45, 0x25, - 0x01, 0xba, 0x8d, 0xc1, 0x50, 0x29, 0x32, 0x80, 0x8d, 0xe3, 0x5e, 0xe7, 0xd7, 0xc7, 0x6d, 0x45, - 0x51, 0xff, 0x41, 0x06, 0x20, 0x36, 0x73, 0xb3, 0xf7, 0xa1, 0x7c, 0x4e, 0x29, 0x3d, 0x71, 0xc3, - 0x92, 0xec, 0x23, 0x70, 0x34, 0x29, 0x73, 0x1f, 0x42, 0x25, 0xda, 0xd7, 0x50, 0xd1, 0x59, 0xbe, - 0x6a, 0x29, 0x47, 0xf8, 0xdd, 0x4b, 0xf6, 0x01, 0x14, 0x3d, 0xec, 0x07, 0x92, 0x66, 0x93, 0x5a, - 0x4e, 0xa2, 0xfb, 0x5a, 0xc1, 0xe3, 0x09, 0x54, 0x88, 0xc6, 0xbe, 0xb4, 0x3a, 0x44, 0xa4, 0x7b, - 0x08, 0x6a, 0x3a, 0xc6, 0x3c, 0xb0, 0x34, 0x8e, 0x8f, 0x76, 0x89, 0x7c, 0xbc, 0x4b, 0xa8, 0xbf, - 0x81, 0xda, 0xc0, 0x98, 0xce, 0xf8, 0x5e, 0x42, 0x1d, 0x63, 0x90, 0x43, 0x9e, 0x10, 0xac, 0x47, - 0xbf, 0x71, 0xd1, 0x1d, 0x59, 0xfe, 0xc8, 0x72, 0xe5, 0x1a, 0x95, 0x49, 0x14, 0xbf, 0xc7, 0xb8, - 0x9b, 0x68, 0xde, 0xb9, 0xdc, 0x4e, 0x64, 0x5a, 0xfd, 0x37, 0x33, 0x50, 0x4e, 0x34, 0x83, 0x7d, - 0x04, 0x39, 0xd2, 0x9c, 0x33, 0x49, 0x41, 0x98, 0x20, 0xe0, 0xbf, 0xb9, 0xae, 0x85, 0x84, 0xec, - 0x01, 0xe4, 0x83, 0xd0, 0xf0, 0xe5, 0x8d, 0x89, 0x92, 0xc8, 0xb1, 0xeb, 0xcd, 0x5d, 0x53, 0xe3, - 0x68, 0xa6, 0x42, 0xd6, 0x72, 0x4d, 0x61, 0xa7, 0x59, 0xa6, 0x42, 0xa4, 0xba, 0x03, 0xa5, 0xa8, - 0x78, 0x64, 0x01, 0xad, 0xff, 0x72, 0xa0, 0xac, 0xb1, 0x12, 0xe4, 0xb5, 0x46, 0x6f, 0xbf, 0xad, - 0x64, 0xd4, 0x3f, 0xcf, 0x00, 0xc4, 0xb9, 0xd8, 0xe3, 0x54, 0x6b, 0x6f, 0x2e, 0x96, 0xfa, 0x98, - 0xfe, 0x26, 0x1a, 0x7b, 0x0b, 0x4a, 0x73, 0x97, 0x80, 0x96, 0x29, 0x76, 0xa2, 0x18, 0x80, 0xc7, - 0x3d, 0xe9, 0x6d, 0xb4, 0x70, 0xdc, 0x7b, 0x65, 0x38, 0xea, 0x2f, 0xa0, 0x14, 0x15, 0x87, 0x07, - 0xdc, 0xbd, 0x7e, 0xb7, 0xdb, 0x7f, 0xd9, 0xe9, 0xed, 0x2b, 0x6b, 0x98, 0x3c, 0xd2, 0xda, 0xcd, - 0x76, 0x0b, 0x93, 0x19, 0xe4, 0xd9, 0xe6, 0xb1, 0xa6, 0xb5, 0x7b, 0x43, 0x5d, 0xeb, 0xbf, 0x54, - 0xd6, 0xd5, 0xbf, 0x9d, 0x81, 0x6a, 0xdf, 0x31, 0x9b, 0x9e, 0xd3, 0x34, 0x66, 0xa8, 0x1a, 0xb1, - 0xaf, 0x60, 0xeb, 0x64, 0x8e, 0xea, 0xf9, 0xcc, 0x31, 0x46, 0xd6, 0xa9, 0xe7, 0x98, 0x96, 0x5c, - 0x84, 0xa9, 0x3b, 0x21, 0x61, 0xbe, 0x56, 0x88, 0xf8, 0x28, 0xa6, 0x65, 0x9f, 0x41, 0x65, 0xe6, - 0x7b, 0x27, 0x96, 0x50, 0x02, 0x96, 0xce, 0x95, 0x71, 0xde, 0x32, 0xd1, 0x71, 0x05, 0x40, 0xfd, - 0xb7, 0xd7, 0xa1, 0xd2, 0xb2, 0xcc, 0xf9, 0xec, 0x6b, 0xcf, 0x76, 0x9b, 0xe1, 0x05, 0xfb, 0x14, - 0x2a, 0x9e, 0x43, 0xd6, 0x10, 0x3d, 0xe1, 0x0f, 0xb1, 0xaa, 0x1c, 0xf0, 0xa8, 0x07, 0xe4, 0x3d, - 0xf1, 0x21, 0x5c, 0xe1, 0x06, 0x06, 0x61, 0x9a, 0xbb, 0xe0, 0x99, 0x71, 0xcd, 0xe4, 0x35, 0x85, - 0xa3, 0xf8, 0x06, 0x4d, 0xe4, 0x7f, 0x04, 0xdb, 0x09, 0x72, 0x14, 0x2c, 0x9c, 0x3e, 0xbb, 0xb4, - 0xc6, 0xb6, 0xa2, 0xbc, 0x91, 0xa7, 0xc6, 0xd7, 0xb0, 0x2d, 0x5b, 0x38, 0xe2, 0xa3, 0xc7, 0x33, - 0xe7, 0x92, 0xe7, 0xa0, 0xd4, 0xe8, 0x8a, 0x06, 0x6f, 0x79, 0x49, 0x20, 0x95, 0xf5, 0x09, 0x5c, - 0x35, 0xb1, 0xf7, 0x3a, 0x1f, 0xfc, 0x33, 0xcb, 0x9a, 0xe9, 0x8e, 0x11, 0x84, 0xe2, 0x32, 0x97, - 0x11, 0x72, 0x17, 0x71, 0xcf, 0x2d, 0x6b, 0xd6, 0x35, 0x82, 0x50, 0xfd, 0xaf, 0xb3, 0x50, 0xe2, - 0xd6, 0x11, 0x1c, 0xae, 0x87, 0x50, 0xf0, 0x4e, 0xbe, 0x23, 0x95, 0xe9, 0x35, 0x17, 0xb6, 0x1b, - 0xde, 0xc9, 0x77, 0xa8, 0x67, 0xbd, 0x2f, 0xb7, 0x3a, 0xd3, 0x1a, 0x8b, 0xd9, 0xa9, 0xa5, 0xcf, - 0x1f, 0x62, 0xeb, 0xc3, 0xb3, 0xf1, 0x53, 0x28, 0xdb, 0x6e, 0x60, 0xf9, 0x21, 0xb7, 0x08, 0x15, - 0x5e, 0x3f, 0x09, 0x9c, 0x8c, 0x8c, 0x44, 0x4f, 0xa1, 0xcc, 0x2d, 0x44, 0x3c, 0x53, 0xf1, 0xf5, - 0x99, 0x38, 0x19, 0x65, 0xfa, 0x12, 0x6a, 0xb1, 0x98, 0xa3, 0x7c, 0xa5, 0xd7, 0xe6, 0xab, 0x46, - 0x94, 0x94, 0xf5, 0x09, 0x5c, 0x0b, 0xce, 0xec, 0x99, 0x2e, 0x5a, 0xea, 0xb9, 0x74, 0x93, 0xa2, - 0xcf, 0xce, 0xc4, 0x0d, 0x06, 0x43, 0x6c, 0x87, 0x90, 0x7d, 0xb7, 0x37, 0x77, 0x9c, 0xa3, 0x33, - 0xf6, 0x1e, 0x6c, 0x09, 0xf2, 0xd9, 0x99, 0xe4, 0x15, 0x3a, 0x15, 0xe7, 0xb5, 0x1a, 0x47, 0x1c, - 0x9d, 0x09, 0x4d, 0xee, 0x0b, 0xa8, 0x73, 0x1f, 0x02, 0xd1, 0x29, 0x63, 0x3c, 0xb6, 0x46, 0xa1, - 0x8e, 0xaa, 0x83, 0xb8, 0xee, 0xb8, 0x4a, 0x78, 0x6e, 0xe6, 0x6a, 0x10, 0x96, 0x24, 0xdf, 0xc7, - 0xb0, 0x6d, 0x4f, 0x5c, 0xcf, 0x97, 0x59, 0x2c, 0x93, 0x67, 0xe2, 0xf7, 0x20, 0x8c, 0xe3, 0x1a, - 0x02, 0x85, 0x39, 0xd4, 0x7f, 0x27, 0x03, 0x25, 0xde, 0x50, 0x9c, 0xd3, 0xbb, 0x90, 0xfd, 0x81, - 0xf9, 0x44, 0x1c, 0x7b, 0x04, 0x5b, 0x86, 0x69, 0x2e, 0x94, 0xcf, 0x05, 0xc8, 0xa6, 0x61, 0x9a, - 0xc9, 0xc2, 0xc9, 0x18, 0x1b, 0xe8, 0xf2, 0xc8, 0x1c, 0xfb, 0x18, 0x14, 0xb5, 0x9a, 0x1d, 0x88, - 0x13, 0x33, 0xb7, 0xa7, 0xa7, 0x58, 0x24, 0xf7, 0xc3, 0x2c, 0xa2, 0x32, 0x00, 0xcd, 0x22, 0x69, - 0xd1, 0x0c, 0x2f, 0xbe, 0xce, 0x15, 0x33, 0x0a, 0xa8, 0xff, 0x59, 0x19, 0xca, 0x0d, 0xd7, 0x70, - 0x2e, 0x7f, 0x6b, 0x91, 0x83, 0x04, 0x59, 0x57, 0x67, 0x73, 0x31, 0x68, 0xfc, 0x6e, 0xaf, 0x44, - 0x10, 0x6a, 0xd9, 0x1d, 0x28, 0x7b, 0xf3, 0x30, 0xc2, 0xf3, 0xdb, 0x3e, 0xe0, 0x20, 0x22, 0x88, - 0xf2, 0x47, 0x96, 0x7b, 0x99, 0x9f, 0xf4, 0xf8, 0x38, 0x7f, 0xa4, 0xdb, 0x45, 0xf9, 0x89, 0xe0, - 0x1e, 0x54, 0x43, 0x7b, 0x6a, 0xd1, 0x05, 0xe7, 0x7c, 0x6a, 0x99, 0xdc, 0x0b, 0x93, 0x3b, 0xf6, - 0x35, 0x05, 0x0c, 0x4b, 0x99, 0x5a, 0x53, 0xcf, 0xbf, 0xe4, 0xa5, 0x6c, 0xf0, 0x52, 0x38, 0x88, - 0x4a, 0xf9, 0x00, 0xd8, 0xb9, 0x61, 0x87, 0x7a, 0xba, 0x28, 0xae, 0x4f, 0x2b, 0x88, 0x19, 0x26, - 0x8b, 0xbb, 0x06, 0x1b, 0xa6, 0x1d, 0x9c, 0x75, 0xfa, 0x42, 0x97, 0x16, 0x29, 0xec, 0x4b, 0x30, - 0x32, 0x70, 0x2b, 0x0f, 0x2d, 0xae, 0xf7, 0x65, 0xb5, 0x12, 0x42, 0x76, 0x11, 0x80, 0x5b, 0x81, - 0x6b, 0x85, 0xe7, 0x9e, 0x8f, 0x39, 0xb9, 0xaa, 0x1c, 0x03, 0x70, 0xcb, 0x44, 0x52, 0xac, 0x88, - 0xb8, 0x35, 0xab, 0x45, 0x69, 0x54, 0x42, 0x39, 0xe7, 0x12, 0xb6, 0xc2, 0x9b, 0x1f, 0x43, 0xd8, - 0x7d, 0xa8, 0x51, 0xf3, 0x49, 0x95, 0xc6, 0x3e, 0x10, 0x23, 0x66, 0xb5, 0x0a, 0x42, 0xc9, 0x04, - 0x80, 0x54, 0x5f, 0xc2, 0x8d, 0x54, 0xff, 0x74, 0xc3, 0xf7, 0x8d, 0x4b, 0x7d, 0x6a, 0x7c, 0xe7, - 0xf9, 0x64, 0xae, 0xc9, 0x6a, 0xd7, 0x92, 0xc3, 0xd6, 0x40, 0xf4, 0x21, 0x62, 0x5f, 0x9b, 0xd5, - 0x76, 0x3d, 0x9f, 0x6c, 0x39, 0x2b, 0xb3, 0x22, 0x96, 0x0c, 0x0f, 0x34, 0xc1, 0xa4, 0xd7, 0x07, - 0xdc, 0x21, 0x54, 0x2b, 0x13, 0x6c, 0x97, 0x40, 0xa8, 0xd9, 0x06, 0x4f, 0xb9, 0x84, 0xdd, 0x12, - 0xde, 0x59, 0x4f, 0x49, 0x76, 0x72, 0xc4, 0xa9, 0x65, 0x98, 0x74, 0xc9, 0x47, 0x88, 0x03, 0xcb, - 0xa0, 0x2b, 0xf4, 0xe0, 0xa9, 0x3e, 0x9b, 0x87, 0xdc, 0x93, 0x53, 0xcb, 0x07, 0x4f, 0x8f, 0xe6, - 0xa1, 0x00, 0x4f, 0xac, 0x90, 0xee, 0xf4, 0x08, 0xbc, 0x6f, 0x85, 0xa8, 0x9e, 0x06, 0x4f, 0xa5, - 0x69, 0xfb, 0xaa, 0x18, 0xdb, 0xa7, 0xc2, 0x76, 0xad, 0x42, 0x35, 0x42, 0xea, 0xd3, 0x39, 0x77, - 0xdd, 0xcc, 0x6a, 0x65, 0x49, 0x70, 0x38, 0x77, 0x70, 0x62, 0x47, 0xc6, 0xe8, 0x14, 0xcf, 0xbd, - 0x86, 0x49, 0xde, 0x9b, 0x59, 0xad, 0x44, 0x10, 0x0d, 0x5b, 0xf3, 0x16, 0xf0, 0x84, 0x7e, 0x6a, - 0x87, 0x64, 0x53, 0xca, 0x6a, 0x45, 0x02, 0x1c, 0xd8, 0x21, 0xae, 0x63, 0x8e, 0x14, 0x1c, 0x48, - 0x45, 0xdc, 0x20, 0xa2, 0x4d, 0x42, 0x1c, 0x12, 0x9c, 0x0a, 0x7a, 0x08, 0x4a, 0x8a, 0x16, 0xcb, - 0xbb, 0x49, 0xa4, 0xb5, 0x04, 0x29, 0x96, 0xfa, 0x00, 0x78, 0x66, 0x1d, 0x59, 0x8f, 0x97, 0xf9, - 0x16, 0x3f, 0xd7, 0x11, 0xb8, 0x65, 0x07, 0x67, 0x54, 0xe2, 0x7d, 0xa8, 0x25, 0xe8, 0xb0, 0xbc, - 0x5b, 0x9c, 0x33, 0x22, 0xb2, 0x54, 0x1b, 0x7d, 0x6b, 0xea, 0x85, 0xa2, 0x9b, 0x6f, 0x27, 0xda, - 0xa8, 0x11, 0x3c, 0xdd, 0x46, 0x41, 0x8b, 0x65, 0xde, 0x4e, 0xb4, 0x91, 0x93, 0x62, 0xa9, 0x77, - 0xa1, 0x72, 0xee, 0xdb, 0x61, 0x68, 0xb9, 0x7c, 0xf1, 0xdf, 0xe1, 0x03, 0x2b, 0x60, 0xb4, 0xfa, - 0xef, 0x42, 0x85, 0x8f, 0xbc, 0x90, 0x6f, 0x3b, 0x9c, 0x44, 0xc0, 0xa4, 0x80, 0x10, 0xa3, 0x31, - 0xb5, 0x5d, 0x32, 0x1c, 0x65, 0xb5, 0x12, 0x87, 0xe0, 0xf1, 0x36, 0x81, 0x36, 0x2e, 0xc8, 0x7c, - 0x14, 0xa3, 0x8d, 0x0b, 0x5a, 0x92, 0x33, 0xdb, 0x71, 0xf8, 0xc2, 0xbf, 0x27, 0x96, 0x24, 0x42, - 0x68, 0xdd, 0x47, 0x68, 0xaa, 0xfd, 0x7e, 0x02, 0x4d, 0x75, 0x23, 0xe3, 0x10, 0x1a, 0xab, 0x7e, - 0x47, 0x30, 0x0e, 0x02, 0xb0, 0xe6, 0x18, 0x69, 0x5c, 0x90, 0x71, 0x28, 0x42, 0x1a, 0x17, 0x42, - 0x6e, 0x61, 0xa9, 0x94, 0xf7, 0xdd, 0x48, 0x6e, 0x21, 0x08, 0x73, 0x27, 0x09, 0x8c, 0x8b, 0xfa, - 0xc3, 0x34, 0x81, 0x71, 0x41, 0x67, 0x2a, 0xcb, 0x30, 0x79, 0xc3, 0xdf, 0xe3, 0xc5, 0x23, 0x80, - 0xda, 0xbd, 0x03, 0x95, 0xe0, 0xa9, 0x1e, 0xe3, 0x1f, 0xf1, 0xec, 0xc1, 0x53, 0x4d, 0x52, 0xdc, - 0x87, 0x5a, 0xc4, 0x1a, 0x9c, 0xe6, 0x7d, 0x3e, 0xf1, 0xa6, 0x60, 0x0d, 0xba, 0x13, 0xfd, 0x5d, - 0x06, 0x6e, 0xf6, 0xc9, 0xee, 0x45, 0xe2, 0xff, 0xd0, 0x0a, 0x02, 0x63, 0x62, 0xed, 0x79, 0xfe, - 0xde, 0xfc, 0xb7, 0xbf, 0xbd, 0x64, 0x0f, 0x61, 0xf3, 0xc8, 0xf0, 0x2d, 0x37, 0x8c, 0x6e, 0xf3, - 0x84, 0x2d, 0x69, 0x11, 0xcc, 0x9e, 0x81, 0xc2, 0x41, 0xdc, 0x33, 0xad, 0x29, 0x6f, 0xa8, 0x16, - 0x4d, 0xe6, 0x4b, 0x54, 0x78, 0x3c, 0x2c, 0xb5, 0xec, 0x20, 0xd4, 0x0c, 0x77, 0x82, 0x32, 0x4a, - 0x71, 0xbc, 0x73, 0x3c, 0xe3, 0xa0, 0xe2, 0xab, 0x27, 0x54, 0x6d, 0xb1, 0x4b, 0xc6, 0xfa, 0x75, - 0x8d, 0x08, 0x63, 0x05, 0xf9, 0x4b, 0x50, 0xe6, 0xb3, 0x59, 0x3a, 0xeb, 0xfa, 0x6b, 0xb2, 0x12, - 0x61, 0x9c, 0xf5, 0x7d, 0x28, 0x27, 0x6a, 0x5d, 0xa1, 0x8e, 0x43, 0x5c, 0x17, 0x12, 0x27, 0xea, - 0x59, 0xe1, 0x19, 0x0b, 0x71, 0xe9, 0xea, 0x3f, 0xb7, 0x0e, 0x8a, 0x30, 0x64, 0x19, 0xa6, 0xe5, - 0xd3, 0xa5, 0x60, 0xea, 0x20, 0x97, 0x79, 0xe3, 0x41, 0x6e, 0x07, 0xf2, 0x8e, 0x3d, 0x8d, 0x1c, - 0xc4, 0x52, 0x57, 0x55, 0x84, 0xc0, 0xb9, 0xf6, 0x7c, 0x7b, 0x42, 0x47, 0xce, 0xa4, 0xb3, 0x24, - 0x99, 0x34, 0xf1, 0x04, 0x47, 0x53, 0xf4, 0x18, 0xc0, 0xb4, 0x83, 0x50, 0x27, 0x23, 0x4c, 0xda, - 0x7a, 0x17, 0x8d, 0xbf, 0x56, 0x32, 0xa3, 0xa9, 0x78, 0x08, 0x4a, 0x42, 0x6d, 0x73, 0x23, 0xfb, - 0x49, 0x5e, 0x8b, 0xd5, 0xb9, 0xa6, 0xdb, 0x74, 0xc3, 0x25, 0x4a, 0x54, 0xb8, 0x36, 0x96, 0x28, - 0x3b, 0xe6, 0x85, 0xfa, 0xf7, 0xde, 0x81, 0x5c, 0xcf, 0x33, 0x2d, 0xf6, 0x31, 0x94, 0xc8, 0x03, - 0x39, 0x31, 0xc1, 0x42, 0xad, 0x46, 0x34, 0xfd, 0xa1, 0x99, 0x2a, 0xba, 0xe2, 0xd7, 0xeb, 0x7d, - 0x96, 0xef, 0xd2, 0x71, 0x90, 0xee, 0xad, 0xb1, 0x4b, 0x65, 0x61, 0xb2, 0x22, 0x0b, 0x0b, 0xc7, - 0xe0, 0xde, 0x4a, 0x37, 0x13, 0xbe, 0xe5, 0x92, 0x0e, 0x9f, 0xd7, 0xa2, 0x34, 0x1d, 0xc2, 0x7d, - 0x0f, 0x55, 0x2f, 0xbe, 0x03, 0xe5, 0x57, 0x1c, 0xc2, 0x39, 0x9e, 0xb6, 0xa4, 0x8f, 0xa1, 0xf4, - 0x9d, 0x67, 0xbb, 0xbc, 0xe1, 0x1b, 0x4b, 0x0d, 0xc7, 0x33, 0x0e, 0x6f, 0xf8, 0x77, 0xe2, 0x17, - 0xbb, 0x07, 0x05, 0xcf, 0xe5, 0x65, 0x17, 0x96, 0xca, 0xde, 0xf0, 0xdc, 0x2e, 0x77, 0x41, 0xab, - 0xda, 0x81, 0xee, 0xdb, 0x93, 0xd3, 0x50, 0xc7, 0x9c, 0xe2, 0xbe, 0xbb, 0x6c, 0x07, 0x1a, 0xc2, - 0xb0, 0x58, 0x64, 0xbc, 0xb1, 0xed, 0xa0, 0x86, 0x47, 0x85, 0x95, 0x96, 0x0a, 0x03, 0x8e, 0xa6, - 0x02, 0xdf, 0x81, 0xe2, 0xc4, 0xf7, 0xf0, 0xd8, 0x71, 0x59, 0x87, 0x25, 0xca, 0x02, 0xe1, 0x76, - 0x2f, 0x51, 0x7d, 0xa2, 0x9f, 0xb6, 0x3b, 0xd1, 0xc9, 0xae, 0x52, 0xde, 0xc9, 0x3e, 0x2c, 0x6a, - 0x15, 0x09, 0x24, 0x8b, 0xc9, 0x3b, 0x50, 0x34, 0x26, 0x13, 0x5d, 0x78, 0xd2, 0x2d, 0x95, 0x65, - 0x4c, 0x26, 0x54, 0xe5, 0x63, 0xa8, 0x9e, 0xdb, 0xae, 0x1e, 0xcc, 0xac, 0x11, 0xa7, 0xad, 0x2e, - 0x0f, 0xe5, 0xb9, 0xed, 0x22, 0x77, 0x13, 0x7d, 0x72, 0x19, 0xd4, 0x7e, 0xfc, 0x32, 0xd8, 0x7c, - 0xdd, 0x32, 0x50, 0x61, 0x43, 0xdc, 0x5a, 0x28, 0x4b, 0x24, 0x02, 0xc3, 0x3e, 0x81, 0xb2, 0x6f, - 0xb8, 0x67, 0xba, 0x70, 0x1e, 0xf8, 0x36, 0x69, 0x1b, 0xd0, 0x0c, 0xf7, 0x4c, 0xf8, 0x0e, 0x80, - 0x1f, 0xfd, 0x4e, 0xab, 0xcc, 0x5b, 0x6f, 0x38, 0x55, 0x25, 0x0e, 0x6b, 0xec, 0x87, 0x0f, 0x6b, - 0x9f, 0xd1, 0xa9, 0xc8, 0x72, 0x43, 0x5d, 0x66, 0xb8, 0xb2, 0x3a, 0x43, 0x85, 0x93, 0xf5, 0x79, - 0x36, 0xec, 0x00, 0xd9, 0xe6, 0x74, 0x32, 0xe4, 0x6d, 0xa7, 0x3a, 0x10, 0x19, 0xed, 0x34, 0xf0, - 0x63, 0x03, 0x5e, 0x03, 0x36, 0x63, 0x07, 0x66, 0xee, 0x35, 0x7e, 0x35, 0x79, 0x3b, 0x91, 0xf2, - 0x78, 0x96, 0xe7, 0x30, 0x3b, 0xe5, 0x06, 0x7d, 0x0f, 0xaa, 0xdc, 0x5b, 0x87, 0x8f, 0x5b, 0x40, - 0x4a, 0x52, 0x49, 0xab, 0x10, 0x90, 0x8f, 0x53, 0x40, 0x02, 0x46, 0x1c, 0x0e, 0xc3, 0x0b, 0xd2, - 0x92, 0x62, 0x01, 0xc3, 0x4f, 0x83, 0xe1, 0x85, 0x56, 0x32, 0xe5, 0x4f, 0xdc, 0xfc, 0x4f, 0x6c, - 0xd7, 0x44, 0xd6, 0x0b, 0x8d, 0x49, 0x50, 0xaf, 0xd3, 0xca, 0x2c, 0x0b, 0xd8, 0xd0, 0x98, 0x04, - 0xec, 0x53, 0xa8, 0x18, 0xfc, 0xb0, 0xc1, 0xdb, 0x7d, 0x23, 0x69, 0xcb, 0x4a, 0x1c, 0x43, 0xb4, - 0xb2, 0x91, 0x38, 0x93, 0x7c, 0x01, 0x4c, 0x5e, 0xaa, 0x26, 0x4e, 0xfe, 0x37, 0x97, 0xb8, 0x71, - 0x53, 0xdc, 0xaa, 0x46, 0xe7, 0xfe, 0x3b, 0x50, 0x16, 0x17, 0x1c, 0x41, 0x68, 0xcd, 0xea, 0x6f, - 0x51, 0x83, 0x80, 0x83, 0x06, 0xa1, 0x35, 0x63, 0x5f, 0x40, 0x35, 0x7d, 0xca, 0xba, 0xb5, 0xe2, - 0x6e, 0x92, 0xd8, 0x42, 0xab, 0x8c, 0x92, 0xe7, 0xae, 0x7b, 0xdc, 0x11, 0x9f, 0x34, 0x24, 0xca, - 0xc8, 0xef, 0xdf, 0x2a, 0xae, 0x17, 0x36, 0x25, 0x0c, 0x07, 0x50, 0x1e, 0xc9, 0xc3, 0x0b, 0x52, - 0xaa, 0xa2, 0x01, 0x8c, 0x8e, 0x8e, 0x78, 0x38, 0x92, 0xa7, 0xc8, 0x16, 0x30, 0x79, 0x9d, 0x82, - 0x9b, 0x0b, 0xf7, 0x44, 0x21, 0x1d, 0x2a, 0xba, 0xae, 0x5c, 0xdc, 0x7b, 0x34, 0xee, 0xb5, 0x93, - 0xdc, 0x8d, 0x9e, 0x41, 0x6d, 0xe6, 0x5b, 0x7a, 0xa2, 0x66, 0x35, 0xd9, 0xa9, 0x23, 0xdf, 0x8a, - 0x2b, 0xaf, 0xcc, 0x12, 0x29, 0xf6, 0x15, 0x6c, 0x25, 0x72, 0xce, 0xcf, 0x28, 0xf3, 0x3d, 0xca, - 0xbc, 0xbd, 0x90, 0xf9, 0xf8, 0x0c, 0xb3, 0xd7, 0x66, 0xa9, 0x34, 0xdb, 0x86, 0x7c, 0x27, 0x68, - 0xbb, 0x26, 0xe9, 0x56, 0x45, 0x8d, 0x27, 0xd8, 0x53, 0xa8, 0xf0, 0x83, 0x0c, 0x39, 0xf3, 0x06, - 0xf5, 0x07, 0x49, 0x63, 0x35, 0x9d, 0x66, 0x08, 0xa1, 0x95, 0x9d, 0xe8, 0x77, 0xc0, 0x3e, 0x87, - 0x2d, 0x7e, 0x93, 0x90, 0x14, 0x91, 0xef, 0x2e, 0x4f, 0x39, 0x11, 0xed, 0xc5, 0x72, 0x52, 0x83, - 0x1b, 0xfe, 0xdc, 0xa5, 0xc3, 0x8d, 0xc8, 0xc9, 0x6d, 0x5c, 0x94, 0xff, 0x21, 0xe5, 0xbf, 0x2e, - 0x56, 0x17, 0x27, 0xe3, 0x79, 0x49, 0x36, 0x5d, 0xf3, 0x93, 0xa0, 0x23, 0xcc, 0xf7, 0x9a, 0x32, - 0xb9, 0xed, 0x87, 0xca, 0x7c, 0xef, 0xa7, 0x94, 0x49, 0x76, 0x21, 0x2a, 0x93, 0x41, 0x6e, 0x3e, - 0xb7, 0x4d, 0xd2, 0xf4, 0x2a, 0x1a, 0xfd, 0x66, 0xef, 0x40, 0xcd, 0xb7, 0x46, 0x73, 0x3f, 0xb0, - 0x5f, 0x59, 0x7a, 0x60, 0xbb, 0x67, 0xa4, 0xe3, 0x15, 0xb5, 0x6a, 0x04, 0x1d, 0xd8, 0xee, 0x19, - 0x8a, 0x0c, 0xeb, 0x22, 0xb4, 0x7c, 0x97, 0xbf, 0x60, 0xf8, 0x20, 0x29, 0x32, 0xda, 0x84, 0xc0, - 0x75, 0xae, 0x81, 0x15, 0xfd, 0x5e, 0x98, 0xd9, 0x80, 0xcf, 0xec, 0xe3, 0x1f, 0x35, 0xb3, 0x03, - 0x9a, 0xd9, 0x07, 0x50, 0xb4, 0xdd, 0xd0, 0xf2, 0x5f, 0x19, 0x4e, 0xfd, 0xa3, 0x25, 0x69, 0x1c, - 0xe1, 0xd8, 0x7d, 0x28, 0x04, 0x8e, 0x8d, 0xeb, 0xbd, 0xfe, 0xf1, 0x12, 0x99, 0x44, 0xb1, 0x87, - 0x50, 0x8a, 0x1e, 0xea, 0xd5, 0x3f, 0x59, 0xa2, 0x8b, 0x91, 0xec, 0x36, 0xe4, 0xce, 0x91, 0xa1, - 0x9e, 0x2c, 0x5f, 0x2e, 0x20, 0x1c, 0xb7, 0xef, 0x31, 0xea, 0xec, 0xb4, 0x7d, 0x3f, 0x5d, 0xda, - 0xbe, 0xf7, 0x6c, 0xc7, 0xe1, 0xdb, 0xf7, 0x58, 0xfc, 0xc2, 0xcd, 0x8f, 0x72, 0x60, 0x4f, 0x3e, - 0x5d, 0xde, 0xfc, 0x10, 0xf7, 0x82, 0x9e, 0x34, 0x96, 0x03, 0xb2, 0x98, 0x73, 0xc3, 0xff, 0x67, - 0xc9, 0xb1, 0x4a, 0x9b, 0xd2, 0x35, 0x08, 0xa2, 0x34, 0x1e, 0x40, 0xc4, 0x7d, 0x01, 0x2a, 0x4d, - 0x9f, 0xf3, 0xf7, 0x2f, 0x1c, 0xd2, 0x31, 0x2f, 0xd8, 0xc7, 0x50, 0x95, 0x8e, 0x52, 0x58, 0x5d, - 0x50, 0xff, 0x62, 0xa9, 0x05, 0x69, 0x02, 0xd6, 0x82, 0xca, 0x18, 0x75, 0xf7, 0x29, 0x57, 0xe5, - 0xeb, 0xcf, 0xa8, 0x21, 0x3b, 0x72, 0x63, 0x7d, 0x9d, 0xaa, 0xaf, 0xa5, 0x72, 0xb1, 0xc7, 0xc0, - 0xec, 0x31, 0x9f, 0xcf, 0x3d, 0xdf, 0x9b, 0x72, 0x75, 0xbd, 0xfe, 0xa5, 0xb0, 0x6e, 0x2d, 0x61, - 0xe8, 0xfa, 0xd0, 0x72, 0x4d, 0x7d, 0x1a, 0x08, 0x35, 0xe1, 0x17, 0xd4, 0x4e, 0x21, 0xbc, 0xa2, - 0x07, 0xbd, 0xd2, 0x3c, 0x8c, 0xb4, 0x87, 0x01, 0xd7, 0x1a, 0xbe, 0x04, 0x64, 0xd7, 0x57, 0x71, - 0xd6, 0x3f, 0xfa, 0xc1, 0xac, 0x48, 0x2b, 0xb3, 0x3e, 0x83, 0x1a, 0x37, 0xad, 0x92, 0x46, 0x86, - 0x2c, 0xfa, 0xcb, 0xa4, 0xe4, 0x4a, 0x1a, 0x9d, 0xb5, 0x8a, 0x99, 0x34, 0x41, 0x7f, 0x01, 0x9b, - 0xd2, 0x3a, 0x1c, 0x0a, 0x43, 0xf2, 0x1f, 0x27, 0xab, 0x8d, 0xac, 0xaf, 0x5a, 0x75, 0x2e, 0x7f, - 0x52, 0x95, 0x4f, 0xa1, 0x4a, 0xbb, 0x68, 0xf4, 0x62, 0xea, 0x6f, 0xac, 0x7c, 0x31, 0x55, 0x41, - 0x22, 0x99, 0x42, 0xe1, 0x1f, 0xaf, 0xd3, 0x51, 0x68, 0xd5, 0xbf, 0xe2, 0xc2, 0x3f, 0x02, 0x36, - 0x43, 0x8b, 0x3d, 0x05, 0x30, 0x66, 0x33, 0xe7, 0x92, 0xb3, 0xe6, 0xaf, 0x88, 0x35, 0xb7, 0x13, - 0xac, 0xd9, 0x40, 0x24, 0xf1, 0x66, 0xc9, 0x90, 0x3f, 0xd9, 0x13, 0xa8, 0xcc, 0xbc, 0x20, 0xd4, - 0xcd, 0xa9, 0x43, 0xfd, 0x6f, 0x24, 0xd7, 0xf6, 0x91, 0x17, 0x84, 0xad, 0xa9, 0x83, 0xbd, 0x80, - 0x59, 0xf4, 0x9b, 0x75, 0xe1, 0x8a, 0xe7, 0xea, 0xe6, 0x7c, 0xe6, 0xd8, 0x23, 0x1c, 0x01, 0x83, - 0x9c, 0x05, 0xea, 0xbb, 0x54, 0xe3, 0xad, 0x44, 0x8d, 0x7d, 0xb7, 0x25, 0x89, 0x84, 0xd7, 0xde, - 0x96, 0xb7, 0x08, 0xa2, 0x73, 0x26, 0xcd, 0x41, 0xe4, 0xe5, 0xda, 0xe4, 0xaa, 0x01, 0x41, 0xa5, - 0x9b, 0xeb, 0x33, 0xd8, 0x8c, 0xa9, 0xb0, 0x83, 0x41, 0xbd, 0x95, 0xe4, 0xe4, 0x84, 0xdb, 0x7c, - 0x55, 0x66, 0x44, 0x58, 0x40, 0x63, 0xe7, 0x39, 0xce, 0x7c, 0x26, 0x44, 0x69, 0xbd, 0x2d, 0xc6, - 0x8e, 0x80, 0x5c, 0x4a, 0x26, 0x8e, 0xe2, 0xd6, 0xb4, 0xbe, 0x97, 0x3c, 0x8a, 0x5b, 0x53, 0x54, - 0x33, 0x84, 0x23, 0xdf, 0x2b, 0xdb, 0x3a, 0x0f, 0xea, 0xfb, 0xe4, 0x7d, 0x29, 0x9c, 0xc4, 0x5f, - 0x20, 0x08, 0xf7, 0x7d, 0xd3, 0xf6, 0xf1, 0x08, 0x40, 0xfe, 0x64, 0x07, 0xdc, 0xcb, 0x98, 0x83, - 0x90, 0x82, 0x35, 0xa1, 0x4e, 0xe2, 0x5c, 0xac, 0xd5, 0xd4, 0xad, 0x5d, 0x67, 0x69, 0x49, 0x5e, - 0x45, 0x5a, 0x7e, 0x29, 0x78, 0x94, 0xb8, 0xbf, 0xfb, 0x15, 0xbc, 0xbd, 0xba, 0x10, 0xf9, 0xa0, - 0xf4, 0x6b, 0xd2, 0x37, 0x6e, 0xac, 0xc8, 0xdd, 0xe4, 0x6f, 0x4c, 0x7f, 0x01, 0xd5, 0x89, 0x41, - 0x23, 0xe1, 0xe8, 0x53, 0xcf, 0xb4, 0xea, 0xcf, 0x93, 0x6f, 0x3d, 0x69, 0xd2, 0xf6, 0x0d, 0x1c, - 0x14, 0xe7, 0xd0, 0x33, 0x2d, 0xad, 0x3c, 0x89, 0x13, 0xec, 0x19, 0xd4, 0x63, 0x26, 0x9c, 0xbb, - 0x58, 0x2f, 0x9e, 0xf5, 0x6c, 0x77, 0x14, 0xd6, 0xbb, 0x34, 0xa6, 0xd7, 0x22, 0xfc, 0x31, 0xa2, - 0x5b, 0x02, 0xcb, 0x9a, 0xa0, 0x90, 0x70, 0x10, 0xbb, 0x58, 0x60, 0x9b, 0x56, 0xfd, 0x30, 0xf9, - 0x96, 0x8b, 0x8b, 0x4e, 0x24, 0xa1, 0xfd, 0x6a, 0x60, 0x9b, 0x96, 0x56, 0x1b, 0xa7, 0xd2, 0xea, - 0xbf, 0x97, 0x87, 0xa2, 0x3c, 0xd5, 0xb1, 0x32, 0x14, 0x8e, 0x7b, 0xcf, 0x7b, 0xfd, 0x97, 0x3d, - 0xfe, 0x24, 0xb4, 0x31, 0x18, 0xb4, 0xb5, 0xa1, 0x62, 0xb2, 0x1a, 0x00, 0x3d, 0xb3, 0xd2, 0x07, - 0xcd, 0x46, 0x8f, 0x3f, 0x11, 0xa5, 0xc7, 0x5d, 0x3c, 0xbd, 0xce, 0xb6, 0xa0, 0xba, 0x77, 0xdc, - 0x23, 0x27, 0x4f, 0x0e, 0xca, 0x22, 0xa8, 0xfd, 0x0d, 0xbf, 0xce, 0xe5, 0xa0, 0x1c, 0x82, 0x0e, - 0x1b, 0xc3, 0xb6, 0xd6, 0x91, 0xa0, 0x3c, 0xbb, 0x0a, 0x5b, 0x11, 0x95, 0x2c, 0x41, 0x29, 0x60, - 0x43, 0x8e, 0xb4, 0xfe, 0xd7, 0xed, 0xe6, 0x50, 0x01, 0xba, 0x0a, 0xde, 0xdf, 0x57, 0xca, 0xac, - 0x02, 0xc5, 0x56, 0x67, 0x30, 0xec, 0xf4, 0x9a, 0x43, 0xa5, 0x82, 0xed, 0xdb, 0xeb, 0x74, 0x87, - 0x6d, 0x4d, 0xa9, 0xb2, 0x22, 0xe4, 0xbe, 0xee, 0x77, 0x7a, 0x4a, 0x8d, 0x5e, 0x97, 0x35, 0x0e, - 0x8f, 0xba, 0x6d, 0x65, 0x13, 0xa1, 0x83, 0xbe, 0x36, 0x54, 0x14, 0x84, 0xbe, 0xec, 0xf4, 0x5a, - 0xfd, 0x97, 0xca, 0x16, 0x2b, 0x41, 0xfe, 0xb8, 0x87, 0xd5, 0x30, 0x56, 0x85, 0x12, 0xfd, 0xd4, - 0x1b, 0xdd, 0xae, 0x72, 0x25, 0x71, 0x7f, 0xbc, 0x8d, 0x28, 0xba, 0x8d, 0x1e, 0x60, 0x1b, 0xae, - 0x62, 0xd3, 0xa3, 0x24, 0x51, 0x5f, 0xc3, 0x72, 0x0e, 0x3b, 0xbd, 0xe3, 0x81, 0x72, 0x1d, 0x89, - 0xe9, 0x27, 0x61, 0xea, 0x58, 0x4e, 0xa7, 0x47, 0x23, 0x77, 0x1b, 0x7f, 0xb7, 0xda, 0xdd, 0xf6, - 0xb0, 0xad, 0xdc, 0xc1, 0x5e, 0x75, 0xfb, 0xcd, 0xe7, 0x7a, 0xff, 0x48, 0xb9, 0x8b, 0x43, 0x78, - 0xa4, 0xb5, 0x75, 0x41, 0x78, 0x8f, 0x29, 0x50, 0xd9, 0x3b, 0xfe, 0xcd, 0x6f, 0xbe, 0xd5, 0x45, - 0xa7, 0xde, 0xc1, 0x3a, 0x63, 0x0a, 0xfd, 0xf8, 0xb9, 0xf2, 0x60, 0x01, 0x34, 0x78, 0xae, 0xbc, - 0x8b, 0x83, 0x22, 0x07, 0x55, 0x79, 0x88, 0x04, 0x5a, 0xbb, 0x79, 0xac, 0x0d, 0x3a, 0x2f, 0xda, - 0x7a, 0x73, 0xd8, 0x56, 0xde, 0xa3, 0x51, 0xe8, 0xf4, 0x9e, 0x2b, 0x8f, 0xb0, 0x99, 0xf8, 0x8b, - 0x8f, 0xfd, 0xfb, 0x8c, 0x41, 0x2d, 0xa6, 0x25, 0xd8, 0x07, 0x48, 0xb2, 0xab, 0xf5, 0x1b, 0xad, - 0x66, 0x63, 0x30, 0x54, 0x3e, 0xc4, 0x3e, 0x0e, 0x8e, 0xba, 0x9d, 0xa1, 0xf2, 0x18, 0x3b, 0xb2, - 0xdf, 0x18, 0x1e, 0xb4, 0x35, 0xe5, 0x23, 0xb6, 0x09, 0xe5, 0x61, 0xe7, 0xb0, 0xad, 0x8b, 0x31, - 0x7d, 0x82, 0x75, 0xec, 0x75, 0xba, 0x5d, 0xe5, 0x29, 0xdd, 0x7f, 0x36, 0xb4, 0x61, 0x87, 0x26, - 0xf2, 0x53, 0x2c, 0xa0, 0x71, 0x74, 0xd4, 0xfd, 0x56, 0xf9, 0x0c, 0x3b, 0x78, 0x78, 0xdc, 0x1d, - 0x76, 0xf4, 0xe3, 0xa3, 0x56, 0x63, 0xd8, 0x56, 0x3e, 0xa7, 0x59, 0xee, 0x0f, 0x86, 0xad, 0xc3, - 0xae, 0xf2, 0x05, 0x95, 0x49, 0x2c, 0xd5, 0xec, 0xf6, 0x7b, 0x6d, 0xe5, 0x99, 0x9a, 0x2b, 0x6e, - 0x28, 0x1b, 0x6a, 0xae, 0xb8, 0xa3, 0xec, 0xa8, 0xb9, 0xa2, 0xaa, 0xa8, 0x8f, 0xca, 0x83, 0xfe, - 0xb1, 0xd6, 0xe4, 0x6d, 0x55, 0xff, 0x16, 0x14, 0xe5, 0xa1, 0x1e, 0x6b, 0xe9, 0xf4, 0x7a, 0x6d, - 0x4d, 0x59, 0xc3, 0x96, 0x74, 0xdb, 0x7b, 0x43, 0x25, 0x43, 0x77, 0xc5, 0x9d, 0xfd, 0x83, 0xa1, - 0xb2, 0x8e, 0x3f, 0xfb, 0xc7, 0x38, 0xa8, 0x59, 0x1a, 0x8d, 0xf6, 0x61, 0x47, 0xc9, 0xe1, 0xaf, - 0x46, 0x6f, 0xd8, 0x51, 0xf2, 0xc4, 0x33, 0x9d, 0xde, 0x7e, 0xb7, 0xad, 0x6c, 0x20, 0xf4, 0xb0, - 0xa1, 0x3d, 0x57, 0x0a, 0xbc, 0xd0, 0x56, 0xfb, 0x1b, 0xa5, 0xc8, 0x36, 0x60, 0xbd, 0xfb, 0x44, - 0x29, 0x21, 0xa8, 0xd5, 0x6e, 0x1d, 0x1f, 0x29, 0xa0, 0x3e, 0x84, 0x42, 0x63, 0x32, 0xa1, 0x15, - 0x8c, 0x9d, 0x3f, 0xee, 0x76, 0xf9, 0x92, 0xd9, 0xed, 0x0f, 0x87, 0xfd, 0x43, 0x25, 0x83, 0x5c, - 0x3b, 0xec, 0x1f, 0x29, 0xeb, 0x6a, 0x07, 0x8a, 0x52, 0x7d, 0x49, 0xbc, 0x96, 0x2c, 0x42, 0xee, - 0x48, 0x6b, 0xbf, 0xe0, 0x0e, 0x0e, 0xbd, 0xf6, 0x37, 0xd8, 0x4c, 0xfc, 0x85, 0x05, 0x65, 0xb1, - 0x22, 0xfe, 0xac, 0x91, 0x9e, 0x4b, 0x76, 0x3b, 0xbd, 0x76, 0x43, 0x53, 0xf2, 0xea, 0x33, 0x28, - 0x27, 0xe4, 0x08, 0x4e, 0xf6, 0x7e, 0xe3, 0x08, 0x19, 0xa6, 0xab, 0x8b, 0x62, 0xaf, 0x01, 0x8b, - 0x40, 0xf1, 0x3c, 0x64, 0xd4, 0xcf, 0x60, 0x6b, 0x69, 0xdb, 0xa0, 0x86, 0x37, 0x3a, 0xa2, 0xe1, - 0x9d, 0xfd, 0x5e, 0x5f, 0x6b, 0xf3, 0x97, 0x9b, 0x62, 0x86, 0xd6, 0xd5, 0xf7, 0xa1, 0x14, 0xed, - 0x6f, 0xc8, 0xb1, 0x4d, 0xad, 0x3f, 0x18, 0xf0, 0x09, 0x5d, 0xc3, 0x34, 0x8d, 0x2a, 0x4f, 0x67, - 0x54, 0x1b, 0x6a, 0x69, 0x61, 0xc3, 0x76, 0xe0, 0x16, 0xe7, 0xe9, 0xdd, 0xe3, 0x4e, 0xb7, 0xa5, - 0x0f, 0x3a, 0xad, 0xb6, 0x7e, 0xdc, 0x1b, 0x1c, 0xb5, 0x9b, 0x9d, 0xbd, 0x4e, 0xbb, 0xa5, 0xac, - 0xb1, 0x9b, 0x70, 0x6d, 0x89, 0x82, 0x3f, 0x1b, 0xcd, 0xb0, 0x1b, 0x70, 0x75, 0x09, 0x47, 0x9c, - 0xbc, 0xfe, 0x75, 0xae, 0x78, 0x47, 0xd9, 0xf9, 0x3a, 0x57, 0xbc, 0xaf, 0xbc, 0xa3, 0x0e, 0x60, - 0x4b, 0xee, 0xe8, 0xf4, 0x40, 0x85, 0x8e, 0x9a, 0xdb, 0x90, 0xef, 0x5a, 0xaf, 0x2c, 0x47, 0xbe, - 0xb4, 0xa0, 0x04, 0x42, 0xfb, 0x27, 0xdf, 0x75, 0xa2, 0x08, 0x03, 0x94, 0x40, 0x15, 0xbe, 0x97, - 0x08, 0x72, 0x40, 0xef, 0x72, 0xff, 0xc5, 0x0c, 0x14, 0x23, 0x3d, 0xe1, 0x3e, 0xac, 0x0f, 0x07, - 0xe2, 0x52, 0x70, 0xfb, 0x71, 0x1c, 0xd3, 0x65, 0x28, 0x7f, 0x69, 0xeb, 0xc3, 0x01, 0xfb, 0x00, - 0x36, 0xf8, 0x3b, 0x6b, 0x61, 0x10, 0xdc, 0x4e, 0xeb, 0x1e, 0x43, 0xc2, 0x69, 0x82, 0x86, 0x7d, - 0x06, 0xa5, 0xa8, 0xb5, 0xc2, 0x42, 0x76, 0x3d, 0x9d, 0x21, 0x42, 0x6b, 0x31, 0xa5, 0xda, 0x85, - 0x5a, 0xba, 0x40, 0x76, 0x1b, 0x80, 0x17, 0x99, 0x30, 0x03, 0x27, 0x20, 0xec, 0x26, 0xc8, 0xe7, - 0xdf, 0x2d, 0x6a, 0x58, 0x35, 0x7a, 0x0e, 0xde, 0x52, 0xff, 0x34, 0x07, 0x10, 0x9f, 0x34, 0x70, - 0x20, 0x22, 0xbb, 0x5f, 0x5e, 0xf8, 0x49, 0xbc, 0x05, 0x25, 0xc7, 0x33, 0xcc, 0x64, 0x48, 0x97, - 0x22, 0x02, 0x88, 0x23, 0x92, 0x0f, 0x15, 0x4b, 0xdc, 0x49, 0x89, 0x5d, 0x83, 0x8d, 0xb1, 0xe7, - 0x4f, 0x8d, 0x50, 0x3c, 0xab, 0x11, 0x29, 0x54, 0x18, 0xf8, 0xf5, 0x2b, 0x9e, 0xb7, 0x5c, 0x7a, - 0x59, 0x83, 0x73, 0x50, 0x11, 0xc0, 0x2e, 0xc2, 0x70, 0xc3, 0xb7, 0xdc, 0x91, 0xe3, 0x05, 0x96, - 0x89, 0x5b, 0xf8, 0x06, 0x1d, 0xaa, 0x40, 0x82, 0x76, 0x2f, 0x79, 0x6f, 0xfd, 0xa9, 0xed, 0x1a, - 0xa1, 0xb8, 0x08, 0xa4, 0xde, 0x4a, 0x08, 0x36, 0xf7, 0xbb, 0xc0, 0x13, 0x66, 0x40, 0xfe, 0x2a, - 0xaf, 0x88, 0x00, 0x6a, 0xee, 0xdb, 0x00, 0x56, 0x30, 0x32, 0x66, 0xbc, 0xf0, 0x12, 0x7f, 0x1a, - 0x2d, 0x20, 0xbb, 0x97, 0xac, 0x0b, 0xb5, 0xe1, 0x09, 0x2a, 0x38, 0x5e, 0xcb, 0x08, 0x8d, 0xa6, - 0xe7, 0x08, 0x03, 0xdd, 0xfd, 0xc5, 0x23, 0xd9, 0xe3, 0x34, 0x19, 0x77, 0x17, 0x5e, 0xc8, 0xcb, - 0x3e, 0x85, 0x8a, 0x3d, 0xb2, 0x4e, 0x2c, 0x7f, 0xc2, 0x8f, 0x77, 0xe5, 0xd4, 0x7b, 0x18, 0x8e, - 0xa1, 0xf3, 0x5d, 0xd9, 0x8e, 0x13, 0xa8, 0x38, 0x4e, 0x3d, 0x77, 0xe2, 0x99, 0x27, 0x3c, 0x57, - 0x25, 0x69, 0x6c, 0x38, 0x44, 0x0c, 0xcf, 0x23, 0x88, 0x30, 0x71, 0xb3, 0x01, 0x57, 0x56, 0x34, - 0xe8, 0x27, 0xf9, 0xa8, 0xfe, 0xe7, 0xeb, 0x50, 0x4e, 0xb4, 0x89, 0x6e, 0x6f, 0x8c, 0x19, 0x59, - 0x1f, 0x23, 0x27, 0xfd, 0x92, 0x80, 0xf0, 0x17, 0x4b, 0x23, 0x23, 0x34, 0x1c, 0x6f, 0x92, 0x78, - 0x8b, 0x25, 0x20, 0x1d, 0x93, 0x2e, 0x54, 0x8d, 0xa9, 0x15, 0xcc, 0x8c, 0x91, 0x5c, 0x55, 0x31, - 0x20, 0x8e, 0x3f, 0x94, 0x4b, 0xc6, 0x1f, 0x52, 0xf8, 0xcd, 0x3b, 0x77, 0x76, 0xa2, 0x8b, 0xf6, - 0x3b, 0x50, 0x96, 0xda, 0x3c, 0xd6, 0x22, 0x2e, 0x87, 0x25, 0xa8, 0x63, 0xb2, 0x07, 0x10, 0xc7, - 0x57, 0xd2, 0x8d, 0x40, 0xf7, 0xc6, 0xd2, 0xd3, 0x32, 0x02, 0x37, 0x82, 0xfe, 0x38, 0xba, 0xb1, - 0x21, 0xcd, 0x4c, 0xf0, 0x04, 0x02, 0x48, 0x86, 0x3e, 0x86, 0x2b, 0xc2, 0x8c, 0x6c, 0x99, 0xfa, - 0xd8, 0xb6, 0x1c, 0x53, 0xb7, 0x4d, 0xee, 0x09, 0x91, 0xd7, 0xb6, 0x22, 0xd4, 0x1e, 0x62, 0x3a, - 0x26, 0xe9, 0xbd, 0xc2, 0x76, 0x60, 0xda, 0x13, 0x2b, 0x08, 0x85, 0x5f, 0x60, 0x85, 0x03, 0x5b, - 0x04, 0x53, 0xff, 0x51, 0x0e, 0x4a, 0xd1, 0x64, 0xbd, 0x69, 0x30, 0xef, 0x41, 0x75, 0xe4, 0xb9, - 0xae, 0x45, 0x32, 0x39, 0x1e, 0xcf, 0x4a, 0x0c, 0x24, 0x67, 0x6c, 0x96, 0x20, 0x92, 0x4f, 0x0d, - 0xf8, 0x83, 0xa2, 0xad, 0x18, 0xf3, 0x42, 0x3c, 0x3a, 0xb8, 0x09, 0x45, 0x5c, 0x8c, 0x27, 0x46, - 0x20, 0x87, 0x39, 0x4a, 0xe3, 0x12, 0x1a, 0x79, 0x8e, 0xc3, 0x33, 0xc8, 0x38, 0x1a, 0x31, 0x84, - 0x3d, 0xa1, 0x48, 0x2a, 0xf4, 0x20, 0x6a, 0x83, 0xf8, 0xbf, 0x9e, 0xe0, 0x3e, 0xfe, 0x26, 0xea, - 0x90, 0x37, 0x5e, 0x93, 0x84, 0xec, 0x2b, 0x50, 0x66, 0xf3, 0xe0, 0xd4, 0x32, 0xf5, 0x99, 0x6f, - 0x99, 0xb4, 0xc7, 0x88, 0x67, 0x13, 0xdb, 0x89, 0xcc, 0x47, 0x12, 0xa7, 0x6d, 0x72, 0xea, 0x08, - 0xc0, 0xde, 0x85, 0xcd, 0x78, 0x1a, 0x66, 0x46, 0x78, 0xca, 0x9d, 0x58, 0x4a, 0x5a, 0x2d, 0x02, - 0x1f, 0x21, 0x94, 0x7d, 0x0a, 0xd7, 0x7c, 0x2b, 0xb0, 0xcd, 0xb9, 0xe1, 0xe8, 0xe9, 0x89, 0xe0, - 0x51, 0x39, 0xb6, 0x25, 0x76, 0x2f, 0x31, 0x21, 0x58, 0xfc, 0xd4, 0xb8, 0x20, 0x43, 0x9c, 0xe3, - 0x58, 0x8e, 0x1d, 0x4c, 0x69, 0xde, 0xf2, 0x5a, 0x6d, 0x6a, 0x5c, 0x1c, 0xc5, 0x50, 0xf2, 0x61, - 0x9b, 0x39, 0xf6, 0xc2, 0xf3, 0x75, 0x3e, 0x97, 0x08, 0xd7, 0x38, 0x9a, 0xa9, 0x50, 0xc5, 0x02, - 0xe9, 0xcc, 0x19, 0xb9, 0xa5, 0x64, 0xb5, 0xf2, 0xd4, 0x20, 0xe3, 0x2c, 0xdd, 0x52, 0xde, 0x87, - 0x5a, 0x44, 0xc3, 0x5d, 0x0f, 0xc4, 0xed, 0xbf, 0x20, 0xe2, 0xde, 0x07, 0xd4, 0x34, 0xce, 0x1d, - 0x72, 0x5a, 0x6b, 0xdc, 0xb9, 0x5f, 0x80, 0xe5, 0x9c, 0xde, 0x00, 0x6e, 0xce, 0x46, 0x16, 0xd9, - 0x24, 0x8a, 0x02, 0xa5, 0x3b, 0xa6, 0xfa, 0xcf, 0x67, 0x80, 0x2d, 0x4f, 0xcf, 0xeb, 0x9e, 0xa9, - 0xe1, 0xf0, 0xca, 0x37, 0x36, 0xf8, 0x9b, 0xbd, 0x07, 0x85, 0xa9, 0xc7, 0x45, 0x66, 0xf6, 0x35, - 0x8f, 0xa6, 0x37, 0xa6, 0x1e, 0x89, 0xd0, 0x77, 0x61, 0x73, 0xe4, 0xb9, 0xa2, 0xa1, 0x7c, 0x45, - 0x71, 0xfe, 0xaa, 0xc5, 0x60, 0x5c, 0x57, 0xea, 0x7f, 0x98, 0x81, 0x5a, 0x7a, 0xd2, 0xd9, 0x03, - 0x0a, 0x62, 0x93, 0x0a, 0x83, 0x93, 0xa6, 0xe8, 0xcf, 0x28, 0xb8, 0xcd, 0xaa, 0x26, 0xbe, 0x0d, - 0x40, 0xd2, 0x4a, 0x3f, 0x09, 0x04, 0xdf, 0x57, 0xb4, 0x12, 0x41, 0x76, 0x03, 0x8f, 0x6e, 0x6d, - 0x79, 0x9c, 0x32, 0x8e, 0xcf, 0xed, 0x64, 0x71, 0xdf, 0xe0, 0x20, 0x22, 0xf8, 0x38, 0x71, 0xd3, - 0xc4, 0x6f, 0x92, 0x56, 0x33, 0x66, 0x44, 0xa5, 0xfe, 0x45, 0x06, 0x20, 0x9e, 0x77, 0x1c, 0xfd, - 0x33, 0xeb, 0x92, 0x58, 0x53, 0x8c, 0x67, 0xe1, 0xcc, 0xba, 0x3c, 0x12, 0x6d, 0x13, 0xb7, 0x94, - 0x81, 0xf0, 0x8c, 0xad, 0x68, 0x25, 0x7e, 0x31, 0x19, 0xf0, 0x77, 0x8e, 0xe2, 0x5e, 0x32, 0xd1, - 0x74, 0x7e, 0x15, 0x19, 0xd0, 0xfb, 0xa0, 0x4d, 0x9e, 0x9b, 0x9e, 0x1d, 0xe2, 0x29, 0x4f, 0xbc, - 0xe8, 0xe4, 0xf7, 0xa8, 0x1d, 0x09, 0x45, 0x42, 0x5e, 0x4e, 0x4c, 0xc8, 0x5d, 0xd5, 0xf8, 0xad, - 0x69, 0x44, 0xa8, 0x3a, 0x72, 0x53, 0x6f, 0x84, 0x21, 0xbd, 0xd5, 0x8e, 0x4c, 0x00, 0x19, 0xf9, - 0x8c, 0x93, 0x9f, 0xfe, 0xdf, 0x22, 0x8f, 0x5e, 0xf1, 0x2e, 0x46, 0xec, 0xed, 0xd1, 0x7b, 0x97, - 0x07, 0x38, 0xd3, 0x8e, 0x14, 0x89, 0x44, 0xc2, 0xdf, 0xef, 0x56, 0x47, 0x9e, 0xc3, 0xc5, 0x21, - 0x02, 0xd5, 0x7f, 0x39, 0x0f, 0x10, 0x1b, 0x7f, 0x53, 0x5c, 0x9a, 0x49, 0x71, 0x29, 0x7b, 0x02, - 0xd7, 0xc4, 0x43, 0xf4, 0xc8, 0x55, 0xd0, 0x76, 0xf5, 0x13, 0x43, 0xba, 0x26, 0x33, 0x81, 0xe5, - 0x4e, 0x60, 0x1d, 0x77, 0xd7, 0x08, 0xd9, 0x33, 0x94, 0x0b, 0x71, 0x9e, 0xf0, 0x72, 0xf6, 0x5a, - 0x16, 0xad, 0xc6, 0xd9, 0x87, 0x97, 0x33, 0xf6, 0x31, 0x5c, 0xf5, 0xad, 0xb1, 0x6f, 0x05, 0xa7, - 0x7a, 0x18, 0x24, 0x2b, 0xe3, 0x6f, 0x07, 0xb6, 0x04, 0x72, 0x18, 0x44, 0x75, 0x7d, 0x0c, 0x57, - 0x85, 0x44, 0x59, 0x68, 0x1e, 0xbf, 0x5d, 0xdd, 0xe2, 0xc8, 0x64, 0xeb, 0x68, 0xe6, 0xc9, 0x22, - 0x2e, 0xe3, 0xe9, 0x15, 0x71, 0xe6, 0x71, 0x30, 0x44, 0xe4, 0x18, 0x32, 0x6b, 0x93, 0x68, 0x2a, - 0x6a, 0x3c, 0xc1, 0x54, 0xc8, 0xe1, 0x0a, 0x21, 0x01, 0x54, 0x7b, 0x52, 0x7b, 0x4c, 0xf1, 0x02, - 0x29, 0xea, 0x8f, 0x67, 0x5a, 0x1a, 0xe1, 0xd8, 0x87, 0xb8, 0x2b, 0xc5, 0xdd, 0x96, 0x21, 0xaf, - 0xb8, 0xb7, 0x9c, 0x12, 0x77, 0x54, 0xe3, 0xc1, 0xaf, 0xde, 0x07, 0x96, 0x68, 0xb9, 0xa4, 0xae, - 0x10, 0xf5, 0x66, 0xd4, 0x6c, 0x41, 0xfc, 0x2e, 0x50, 0x13, 0x63, 0xc7, 0xb8, 0x05, 0x1b, 0x30, - 0x22, 0x85, 0x33, 0xdd, 0xd5, 0xb8, 0x77, 0xba, 0x11, 0xea, 0xe1, 0xa9, 0xa5, 0x5b, 0xae, 0x49, - 0xf2, 0xa9, 0xa8, 0x6d, 0x45, 0x1d, 0x6d, 0x84, 0xc3, 0x53, 0xab, 0xed, 0x9a, 0xc9, 0x5b, 0xb6, - 0xcd, 0x1f, 0xbe, 0x65, 0xfb, 0x1c, 0xea, 0x69, 0x3b, 0x4b, 0x62, 0xb8, 0x79, 0xf4, 0x8d, 0xed, - 0xa4, 0xc7, 0x61, 0x34, 0xe2, 0x8f, 0x60, 0xeb, 0xd4, 0x08, 0xd2, 0x36, 0x1a, 0xba, 0xfc, 0x2b, - 0x6a, 0x9b, 0xa7, 0x46, 0x90, 0x34, 0xcc, 0xa8, 0x7f, 0x37, 0x03, 0xb5, 0xb4, 0x39, 0x9c, 0x3f, - 0x69, 0xe6, 0x7b, 0x5b, 0x86, 0x76, 0xf8, 0x68, 0x07, 0x7b, 0x0b, 0x4a, 0xdc, 0x2d, 0x71, 0x3e, - 0x75, 0xe5, 0x5a, 0x98, 0x9d, 0x71, 0x79, 0x8a, 0x02, 0x72, 0x76, 0xf6, 0x06, 0x01, 0x39, 0xe3, - 0xef, 0xb9, 0xde, 0x83, 0xc2, 0xfc, 0x2c, 0x8e, 0xab, 0xb3, 0x92, 0x74, 0x4e, 0xa4, 0xea, 0x7f, - 0xb1, 0x0e, 0x95, 0xe4, 0x2d, 0xce, 0x8f, 0xf1, 0x3e, 0xfc, 0x49, 0xae, 0xa4, 0x3b, 0xf4, 0xe2, - 0x41, 0xa7, 0x07, 0x53, 0x38, 0x4e, 0xdc, 0xf5, 0x10, 0x4e, 0x8d, 0xa0, 0x31, 0x0f, 0x71, 0xaf, - 0x20, 0x45, 0xce, 0x73, 0xe4, 0xa3, 0x32, 0xbe, 0x32, 0x50, 0x26, 0x88, 0xf7, 0x64, 0x1f, 0x8b, - 0x37, 0xab, 0xf4, 0xde, 0x9d, 0x1e, 0x07, 0xe4, 0x97, 0xf8, 0xa5, 0x22, 0x9f, 0xbb, 0xd3, 0x63, - 0x88, 0x27, 0xb0, 0x19, 0xbf, 0x10, 0xe4, 0x59, 0x36, 0x96, 0xb2, 0x54, 0xa3, 0xe7, 0x81, 0x22, - 0x16, 0x4f, 0xd5, 0x0e, 0x74, 0xcf, 0x31, 0xe5, 0x4b, 0xe5, 0x82, 0xbc, 0x63, 0xef, 0x3b, 0xa6, - 0x08, 0xb2, 0xc0, 0x69, 0x5c, 0xeb, 0x5c, 0xd2, 0x44, 0xf7, 0xf0, 0x3d, 0xeb, 0x5c, 0xbc, 0x58, - 0xfe, 0x8f, 0xb2, 0xb0, 0xb5, 0x74, 0x71, 0x83, 0x8a, 0x65, 0x1c, 0xa7, 0x12, 0x7f, 0xb2, 0xbb, - 0x50, 0x99, 0x1a, 0xe1, 0xe8, 0x14, 0x75, 0x95, 0xb1, 0x7d, 0x21, 0x83, 0x6d, 0x12, 0xec, 0x88, - 0x40, 0xb8, 0x9f, 0x70, 0x59, 0xcb, 0xaf, 0xb6, 0xb9, 0xe0, 0xe3, 0x62, 0xbc, 0x4b, 0x77, 0xda, - 0xf2, 0xb1, 0x44, 0xee, 0x35, 0x8f, 0x25, 0x6e, 0x42, 0xc9, 0xf5, 0xc8, 0x31, 0x76, 0x76, 0x26, - 0xc4, 0x74, 0xc1, 0xf5, 0xc2, 0xbe, 0x7b, 0x74, 0xc6, 0x9e, 0xc0, 0xd5, 0x79, 0x40, 0xbe, 0x64, - 0x27, 0x96, 0x1f, 0x9c, 0xda, 0x91, 0x09, 0x95, 0x0b, 0x90, 0x2b, 0xf3, 0xc0, 0x3a, 0x8c, 0x70, - 0xc2, 0x92, 0xda, 0x80, 0x0a, 0xcd, 0x81, 0x3b, 0xf2, 0xe8, 0x52, 0xa6, 0x40, 0xc2, 0xe3, 0xf6, - 0x8a, 0xdb, 0xaa, 0xe7, 0xd6, 0x65, 0x5b, 0x50, 0x69, 0xe5, 0xb3, 0x38, 0xc1, 0xde, 0xa3, 0x77, - 0x70, 0x27, 0x56, 0x7c, 0x36, 0x4a, 0x31, 0xa7, 0x56, 0x22, 0x2c, 0x31, 0xf1, 0x73, 0xb8, 0xc1, - 0x1f, 0x29, 0x4f, 0x67, 0x9e, 0x6b, 0xb9, 0xa1, 0x1e, 0x67, 0x0c, 0xd2, 0xfe, 0x0d, 0x09, 0xb6, - 0xbe, 0x46, 0x8f, 0x96, 0x45, 0x8e, 0x23, 0x59, 0x56, 0x80, 0xf5, 0x72, 0x03, 0x25, 0x0d, 0x18, - 0x2c, 0xdf, 0x12, 0x11, 0x16, 0x7f, 0xaa, 0xb7, 0x60, 0xa3, 0x13, 0x5d, 0xab, 0x45, 0x3e, 0xe8, - 0x59, 0x11, 0x87, 0xcf, 0x83, 0x12, 0xb7, 0xb7, 0x1e, 0x1a, 0x33, 0xf6, 0x08, 0xb2, 0x53, 0x63, - 0x26, 0xdc, 0x74, 0xea, 0x91, 0x2f, 0x13, 0xc7, 0x3e, 0x3e, 0x34, 0x66, 0xfc, 0x54, 0x86, 0x44, - 0x37, 0x3f, 0x87, 0xa2, 0x04, 0xfc, 0xb4, 0x97, 0x7b, 0xeb, 0x50, 0x6a, 0x25, 0xaf, 0xc5, 0x51, - 0x93, 0x0b, 0xfd, 0xb9, 0x4b, 0xfa, 0xad, 0x88, 0x38, 0x36, 0x32, 0xdc, 0xa1, 0x00, 0xc9, 0x05, - 0xbc, 0xfe, 0x03, 0x0b, 0xf8, 0x16, 0x80, 0x4f, 0xb7, 0x4a, 0x74, 0xb1, 0x94, 0x8d, 0xde, 0xe4, - 0x74, 0xcc, 0x8e, 0x79, 0xb1, 0xda, 0xb9, 0x38, 0xf7, 0xe3, 0x9d, 0x8b, 0xf3, 0x2b, 0x9d, 0x8b, - 0x1f, 0xc4, 0x9b, 0x28, 0x4e, 0x2b, 0x56, 0x5c, 0xe2, 0x5b, 0xf9, 0x2c, 0x7a, 0x87, 0x8c, 0xb5, - 0xff, 0x02, 0x6a, 0xb2, 0x77, 0xa2, 0x3c, 0x48, 0x3d, 0x7d, 0x16, 0x38, 0x7e, 0x8f, 0x5e, 0x0d, - 0x93, 0xc9, 0xb4, 0x60, 0x2a, 0xbf, 0xc1, 0x81, 0xf9, 0x5f, 0xc9, 0x00, 0x13, 0xb7, 0x20, 0x7b, - 0x73, 0xc7, 0x19, 0x5a, 0x17, 0x24, 0xff, 0x1e, 0xc1, 0x96, 0xb8, 0xe6, 0x4f, 0x04, 0xaf, 0x10, - 0x8e, 0x6d, 0x1c, 0x11, 0x3b, 0xb6, 0xad, 0x8a, 0x73, 0xb1, 0xbe, 0x32, 0xce, 0xc5, 0xea, 0xf8, - 0x19, 0x77, 0xa0, 0x9c, 0x8c, 0x12, 0xc1, 0x95, 0x58, 0x30, 0xa2, 0x00, 0x11, 0xea, 0xff, 0xb0, - 0x0e, 0x10, 0xdf, 0xd4, 0xfc, 0xa1, 0x3d, 0xc3, 0x57, 0x4c, 0x49, 0x76, 0xd5, 0x94, 0x3c, 0x04, - 0x25, 0x49, 0x97, 0x08, 0x57, 0x52, 0x8b, 0x09, 0xa5, 0x32, 0x67, 0x07, 0xc9, 0x38, 0x11, 0xf4, - 0x54, 0x54, 0x38, 0xd3, 0x72, 0x24, 0xbf, 0x36, 0x16, 0x62, 0xa6, 0x68, 0x07, 0x7c, 0xe7, 0x61, - 0x5f, 0xc2, 0x8d, 0x28, 0xa7, 0x7e, 0x6e, 0x87, 0xa7, 0xde, 0x3c, 0x14, 0x22, 0x29, 0x10, 0xb2, - 0xf8, 0x9a, 0x2c, 0xe9, 0x25, 0x47, 0x73, 0x51, 0x13, 0xb0, 0xcf, 0xa0, 0x34, 0x9e, 0x3b, 0x8e, - 0x1e, 0x5a, 0x17, 0xa1, 0x10, 0x29, 0xf5, 0xd4, 0x25, 0x57, 0x62, 0x7a, 0xb5, 0xe2, 0x58, 0x24, - 0xd4, 0x7f, 0x36, 0x0f, 0xf9, 0x5f, 0xcf, 0x2d, 0xff, 0x92, 0x7d, 0x0e, 0xa5, 0x20, 0x9c, 0x86, - 0x49, 0x7f, 0x33, 0x71, 0x79, 0x41, 0x78, 0x72, 0x17, 0xb3, 0xa6, 0x96, 0x1b, 0xf2, 0xdb, 0x5f, - 0xa4, 0x25, 0x09, 0xb5, 0x0d, 0xf9, 0x20, 0xb4, 0x66, 0x81, 0x78, 0x67, 0xc2, 0x13, 0x6c, 0x07, - 0xf2, 0xae, 0x67, 0x5a, 0x41, 0xfa, 0x35, 0x49, 0x0f, 0xf5, 0x2a, 0x8e, 0x60, 0x2a, 0x6c, 0x44, - 0x33, 0xbe, 0xe4, 0xf3, 0xc5, 0x31, 0xf4, 0x46, 0xd5, 0x32, 0x50, 0x66, 0xca, 0xf0, 0x2f, 0x51, - 0x1a, 0x15, 0x08, 0xb2, 0x7e, 0x19, 0x13, 0x19, 0x36, 0x4a, 0x24, 0xd9, 0x0e, 0x94, 0xf1, 0xe7, - 0x4b, 0xdf, 0x0e, 0xad, 0xc1, 0x53, 0xb9, 0x87, 0x25, 0x40, 0x78, 0xf0, 0x36, 0xad, 0xd0, 0x1a, - 0x85, 0x83, 0xef, 0x1d, 0x79, 0xbc, 0x4d, 0x40, 0xd8, 0x2f, 0x80, 0x9d, 0x18, 0xa3, 0xb3, 0x89, - 0x4f, 0x7e, 0x92, 0xdf, 0xcf, 0x2d, 0xdf, 0x8e, 0xc4, 0x6d, 0x39, 0x31, 0x28, 0xda, 0x56, 0x4c, - 0xf6, 0x6b, 0x4e, 0xc5, 0xae, 0xc1, 0xc6, 0xd4, 0xb8, 0x68, 0x79, 0x33, 0xe1, 0xc0, 0x2e, 0x52, - 0xec, 0x29, 0x5c, 0x43, 0x15, 0x40, 0x06, 0x19, 0x41, 0x1e, 0x12, 0xf7, 0x8a, 0x3c, 0xe2, 0xe4, - 0x95, 0x53, 0x23, 0x88, 0x03, 0x07, 0x08, 0xbb, 0xf0, 0x2e, 0x6c, 0x4b, 0xf3, 0x8e, 0x69, 0xcd, - 0x2c, 0xd7, 0xb4, 0xdc, 0x91, 0x1d, 0x85, 0x25, 0x58, 0x62, 0xfe, 0x2b, 0x82, 0xb8, 0x95, 0xa0, - 0x65, 0xf7, 0xa0, 0x8a, 0x15, 0xfb, 0x56, 0x38, 0xf7, 0x5d, 0xdc, 0xb1, 0xf8, 0x13, 0x0c, 0x54, - 0x48, 0x34, 0x09, 0xe3, 0x8e, 0x12, 0x22, 0xc1, 0x5d, 0x7b, 0x78, 0x60, 0xaa, 0x6a, 0x04, 0x1d, - 0x84, 0xd6, 0x4c, 0xfd, 0x13, 0xa8, 0xa6, 0xf8, 0x60, 0xe9, 0x9e, 0x6a, 0xd0, 0xee, 0xb6, 0x9b, - 0x43, 0x6e, 0xbb, 0x16, 0x17, 0x2a, 0xeb, 0x89, 0x9b, 0x97, 0x5c, 0xc2, 0xa6, 0x9d, 0xa7, 0x7b, - 0x9b, 0xb6, 0xb6, 0xdf, 0xa6, 0xcb, 0x85, 0xac, 0x92, 0x55, 0xff, 0xd5, 0x75, 0xd8, 0x1a, 0xfa, - 0x86, 0x1b, 0x18, 0x5c, 0x73, 0x74, 0x43, 0xdf, 0x73, 0xd8, 0x2f, 0xa0, 0x18, 0x8e, 0x9c, 0x24, - 0x63, 0xde, 0x91, 0x62, 0x70, 0x81, 0xf4, 0xf1, 0x70, 0xc4, 0x9d, 0x13, 0x0a, 0x21, 0xff, 0xc1, - 0x3e, 0x84, 0xfc, 0x89, 0x35, 0xb1, 0x5d, 0xb1, 0x13, 0x5c, 0x5d, 0xcc, 0xb8, 0x8b, 0xc8, 0x83, - 0x35, 0x8d, 0x53, 0xb1, 0x8f, 0x61, 0x63, 0xe4, 0x4d, 0xa5, 0xa2, 0x11, 0x87, 0x34, 0x48, 0x54, - 0x84, 0xd8, 0x83, 0x35, 0x4d, 0xd0, 0xb1, 0xcf, 0xa1, 0xe8, 0x7b, 0x8e, 0x83, 0x7c, 0x20, 0x54, - 0x90, 0xfa, 0x62, 0x1e, 0x4d, 0xe0, 0x0f, 0xd6, 0xb4, 0x88, 0x56, 0x7d, 0x0c, 0x05, 0xd1, 0x58, - 0x1c, 0x86, 0xdd, 0xf6, 0x7e, 0x47, 0x8c, 0x60, 0xb3, 0x7f, 0x78, 0xd8, 0x19, 0xf2, 0x70, 0x2e, - 0x5a, 0xbf, 0xdb, 0xdd, 0x6d, 0x34, 0x9f, 0x2b, 0xeb, 0xbb, 0x45, 0xd8, 0xe0, 0xec, 0xa2, 0xfe, - 0x69, 0x06, 0x36, 0x17, 0x3a, 0xc0, 0x9e, 0x41, 0x8e, 0x2c, 0x00, 0x7c, 0x78, 0xee, 0xaf, 0xec, - 0x65, 0x22, 0xcd, 0xcf, 0x37, 0x98, 0x43, 0xfd, 0x12, 0x6a, 0x69, 0x78, 0xe2, 0x66, 0xa4, 0x0a, - 0x25, 0xad, 0xdd, 0x68, 0xe9, 0xfd, 0x5e, 0xf7, 0x5b, 0x7e, 0xd5, 0x48, 0xc9, 0x97, 0x5a, 0x87, - 0xae, 0x24, 0xfe, 0x26, 0x28, 0x8b, 0x03, 0xc3, 0xf6, 0xf1, 0xac, 0x3a, 0x9d, 0x39, 0x16, 0x1d, - 0x09, 0x12, 0x53, 0x76, 0x7b, 0xc5, 0x48, 0x0a, 0x32, 0xee, 0x70, 0x3c, 0x4a, 0xa5, 0xd5, 0x3f, - 0x01, 0xb6, 0x3c, 0x82, 0x7f, 0xb8, 0xe2, 0xff, 0xef, 0x0c, 0xe4, 0x8e, 0x1c, 0xc3, 0x65, 0xf7, - 0x20, 0x4f, 0xc1, 0x15, 0xc5, 0x7e, 0x92, 0x5c, 0xdd, 0xc8, 0x16, 0x84, 0x63, 0xef, 0x43, 0x36, - 0x1c, 0xc9, 0x30, 0x31, 0xd7, 0x5f, 0xc3, 0x7c, 0x07, 0x6b, 0x1a, 0x52, 0xb1, 0x87, 0x90, 0x35, - 0x4d, 0xf9, 0x62, 0x51, 0xd8, 0x36, 0x5a, 0x46, 0x68, 0xb4, 0xac, 0xb1, 0xed, 0xda, 0x22, 0x18, - 0x24, 0x92, 0xb0, 0x77, 0x20, 0x6b, 0x8e, 0x9c, 0xf4, 0xf3, 0x53, 0x6e, 0x38, 0x8e, 0x0a, 0x34, - 0x47, 0x0e, 0x6a, 0xdc, 0xa1, 0x7f, 0xa9, 0xfb, 0x73, 0x97, 0x5e, 0xae, 0x04, 0xe2, 0x14, 0x5c, - 0x46, 0xad, 0x6a, 0x4e, 0xcf, 0x5f, 0x02, 0x11, 0x6f, 0x62, 0xe6, 0x5b, 0x33, 0xc3, 0x8f, 0xce, - 0xbf, 0x76, 0x70, 0xc4, 0x01, 0xbb, 0x1b, 0x40, 0x11, 0xf4, 0xd5, 0x0f, 0x28, 0xf2, 0x1f, 0x1e, - 0xa4, 0x54, 0xf9, 0x6b, 0x45, 0xb0, 0x65, 0x81, 0x51, 0xff, 0x61, 0x16, 0xca, 0x89, 0xf6, 0xb0, - 0x4f, 0xa1, 0x68, 0xa6, 0x17, 0xe2, 0x8d, 0xa5, 0x46, 0x3f, 0x6e, 0xc9, 0x25, 0x68, 0x0a, 0xf6, - 0x26, 0xcf, 0x97, 0x50, 0x7f, 0x65, 0xf8, 0x36, 0x8f, 0x28, 0xbb, 0x9e, 0x74, 0x41, 0x19, 0x58, - 0xe1, 0x0b, 0x89, 0x39, 0x58, 0xd3, 0x2a, 0x41, 0x22, 0x4d, 0xa7, 0x3d, 0xd1, 0xa5, 0x6c, 0x2a, - 0x8a, 0x2f, 0x07, 0x1e, 0xac, 0x69, 0x12, 0x8f, 0xa4, 0xd6, 0x85, 0x35, 0x9a, 0x87, 0xf2, 0xb4, - 0x57, 0x95, 0x1d, 0x22, 0x20, 0x85, 0x12, 0xe7, 0x3f, 0xd9, 0x13, 0x94, 0xfe, 0x86, 0xe3, 0x78, - 0xa4, 0x3c, 0xe6, 0x93, 0xe6, 0xc5, 0x56, 0x04, 0xe7, 0xa1, 0xcb, 0x65, 0x8a, 0x3d, 0x80, 0xbc, - 0x17, 0x9e, 0x5a, 0xf2, 0x0c, 0x25, 0x63, 0x08, 0x22, 0xa8, 0xd5, 0xec, 0x22, 0xa7, 0x10, 0x5a, - 0xfd, 0xb3, 0x0c, 0x14, 0xc4, 0x08, 0xb0, 0x2d, 0xa8, 0x0e, 0xda, 0x43, 0xfd, 0x45, 0x43, 0xeb, - 0x34, 0x76, 0xbb, 0x6d, 0xf1, 0x6a, 0x76, 0x5f, 0x6b, 0xf4, 0x84, 0x80, 0xd4, 0xda, 0x2f, 0xfa, - 0xcf, 0xdb, 0xfc, 0xba, 0xb1, 0xd5, 0xee, 0x7d, 0xab, 0x64, 0xf9, 0x75, 0x7b, 0xfb, 0xa8, 0xa1, - 0xa1, 0xac, 0x2c, 0x43, 0xa1, 0xfd, 0x4d, 0xbb, 0x79, 0x4c, 0xc2, 0xb2, 0x06, 0xd0, 0x6a, 0x37, - 0xba, 0xdd, 0x7e, 0x13, 0x85, 0xe7, 0x06, 0x63, 0x50, 0x6b, 0x6a, 0xed, 0xc6, 0xb0, 0xad, 0x37, - 0x9a, 0xcd, 0xfe, 0x71, 0x6f, 0xa8, 0x14, 0xb0, 0xc6, 0x46, 0x77, 0xd8, 0xd6, 0x22, 0x10, 0xc5, - 0x75, 0x6d, 0x69, 0xfd, 0xa3, 0x08, 0x52, 0xda, 0x2d, 0xe1, 0xc9, 0x9b, 0xe6, 0x4a, 0xfd, 0x0f, - 0xb6, 0xa0, 0x96, 0x66, 0x4d, 0xf6, 0x05, 0x14, 0x4d, 0x33, 0x35, 0xc7, 0xb7, 0x56, 0xb1, 0xf0, - 0xe3, 0x96, 0x29, 0xa7, 0x99, 0xff, 0x60, 0x77, 0xe5, 0x42, 0x5a, 0x5f, 0x5a, 0x48, 0x72, 0x19, - 0x7d, 0x05, 0x9b, 0x22, 0xb0, 0x5d, 0x64, 0x12, 0x4f, 0xad, 0x92, 0x26, 0x21, 0x5b, 0x02, 0x77, - 0xb0, 0xa6, 0xd5, 0x46, 0x29, 0x08, 0xfb, 0x25, 0xd4, 0x0c, 0x6e, 0x68, 0x4e, 0x9a, 0xd4, 0x23, - 0xb5, 0xb8, 0x41, 0x76, 0xe6, 0x38, 0x7b, 0xd5, 0x48, 0x02, 0x90, 0x11, 0x4d, 0xdf, 0x9b, 0xc5, - 0x99, 0xf3, 0x29, 0x5f, 0x28, 0xdf, 0x9b, 0x25, 0xf2, 0x56, 0xcc, 0x44, 0x9a, 0x7d, 0x0e, 0x15, - 0xd1, 0xf2, 0xd8, 0xc0, 0x14, 0x2d, 0x59, 0xde, 0x6c, 0x52, 0x73, 0x0f, 0xd6, 0xb4, 0xf2, 0x28, - 0x4e, 0xb2, 0xa7, 0xa8, 0xdb, 0xc6, 0x87, 0x82, 0x42, 0x92, 0xd7, 0xa8, 0xb5, 0x32, 0x17, 0x18, - 0x51, 0x8a, 0x7d, 0x0c, 0x40, 0xed, 0xe4, 0x79, 0x8a, 0x29, 0x2f, 0x61, 0xdf, 0x9b, 0xc9, 0x2c, - 0x25, 0x53, 0x26, 0x12, 0xcd, 0xe3, 0xe6, 0xc1, 0xd2, 0x72, 0xf3, 0xc8, 0x44, 0x18, 0x37, 0x8f, - 0x5b, 0x16, 0xa3, 0xe6, 0xf1, 0x6c, 0xb0, 0xd4, 0x3c, 0x99, 0x8b, 0x37, 0x8f, 0x67, 0x92, 0xcd, - 0xe3, 0x79, 0xca, 0x8b, 0xcd, 0x93, 0x59, 0xa8, 0x79, 0x3c, 0xc7, 0x2f, 0x97, 0x4e, 0x33, 0x95, - 0xd7, 0x9e, 0x66, 0x70, 0xda, 0xd2, 0xe7, 0x99, 0x5f, 0x42, 0x2d, 0x38, 0xf5, 0xce, 0x13, 0x02, - 0xa4, 0x9a, 0xcc, 0x3d, 0x38, 0xf5, 0xce, 0x93, 0x12, 0xa4, 0x1a, 0x24, 0x01, 0xd8, 0x5a, 0xde, - 0x45, 0xf2, 0x5b, 0xaa, 0x25, 0x5b, 0x4b, 0x3d, 0x7c, 0x61, 0x5b, 0xe7, 0xd8, 0x5a, 0x43, 0x26, - 0x70, 0x50, 0x62, 0x63, 0x5b, 0x20, 0xcc, 0x67, 0x29, 0xdf, 0x5a, 0x51, 0x13, 0x44, 0x66, 0xb7, - 0x00, 0x79, 0x6b, 0xee, 0x26, 0xb3, 0x29, 0x49, 0xde, 0x3a, 0x76, 0x53, 0x19, 0x2b, 0x9c, 0x54, - 0x64, 0x8d, 0x57, 0x45, 0x60, 0x7d, 0x3f, 0xb7, 0xdc, 0x91, 0x25, 0x7c, 0xe8, 0x53, 0xab, 0x62, - 0x20, 0x70, 0xf1, 0xaa, 0x90, 0x90, 0x88, 0xaf, 0xa3, 0xec, 0x6c, 0x91, 0xaf, 0x13, 0x99, 0x89, - 0xaf, 0xa3, 0xac, 0xd1, 0x82, 0x8a, 0xf2, 0x5e, 0x59, 0x5a, 0x50, 0x89, 0xcc, 0x7c, 0x41, 0x45, - 0xb9, 0x9f, 0x82, 0xe0, 0x26, 0x3e, 0xb8, 0x29, 0x4f, 0x7b, 0xde, 0x6a, 0x31, 0xba, 0x30, 0x8a, - 0x52, 0xc8, 0xab, 0xbe, 0x85, 0xa7, 0x27, 0xc1, 0x0a, 0x57, 0x93, 0xbc, 0xaa, 0x11, 0x26, 0x5a, - 0x4a, 0x7e, 0x9c, 0x4c, 0x54, 0x36, 0xb3, 0x43, 0xbf, 0x6e, 0x2e, 0x57, 0x76, 0x64, 0x87, 0x7e, - 0x5c, 0x19, 0xa6, 0xd8, 0x87, 0x40, 0x6c, 0xc8, 0xb3, 0x58, 0x49, 0xd1, 0x8d, 0xc3, 0x22, 0x32, - 0x14, 0x4d, 0xf1, 0x1b, 0x99, 0x45, 0xd4, 0x31, 0x32, 0x47, 0xf5, 0x71, 0x92, 0x59, 0x78, 0x15, - 0xcd, 0x56, 0x13, 0x99, 0x85, 0x13, 0x35, 0xcd, 0x11, 0x7b, 0x04, 0x94, 0x9b, 0xe8, 0x27, 0xa9, - 0x18, 0xb5, 0xbe, 0x37, 0xe3, 0xd4, 0x05, 0x24, 0x40, 0x5a, 0xec, 0x81, 0xe3, 0xb9, 0xb2, 0xe3, - 0xa7, 0xa9, 0x1e, 0x20, 0x22, 0x12, 0x06, 0xa3, 0x28, 0xa5, 0xfe, 0x33, 0x1b, 0x50, 0x10, 0xb2, - 0x96, 0x5d, 0x81, 0x4d, 0x21, 0xf2, 0x5b, 0x8d, 0x61, 0x63, 0xb7, 0x31, 0x40, 0x25, 0x8d, 0x41, - 0x8d, 0xcb, 0xfc, 0x08, 0x96, 0xc1, 0x7d, 0x80, 0x84, 0x7e, 0x04, 0x5a, 0xc7, 0x7d, 0x40, 0xe4, - 0xe5, 0x4e, 0x1d, 0x59, 0xb6, 0x09, 0x65, 0x9e, 0x91, 0x03, 0x28, 0x88, 0x07, 0xe5, 0xe2, 0xe9, - 0x7c, 0x22, 0x0b, 0xf7, 0xbe, 0xd9, 0x88, 0xb3, 0x70, 0x40, 0x21, 0xca, 0x22, 0xdd, 0x73, 0x18, - 0xd4, 0x86, 0xda, 0x71, 0xaf, 0x19, 0xd7, 0x53, 0xa2, 0xc0, 0x0b, 0xbc, 0x98, 0x17, 0x9d, 0xf6, - 0x4b, 0x05, 0x30, 0x13, 0x2f, 0x85, 0xd2, 0x65, 0x54, 0x33, 0xa9, 0x10, 0x4a, 0x56, 0xd8, 0x75, - 0xb8, 0x32, 0x38, 0xe8, 0xbf, 0xd4, 0x79, 0xa6, 0xa8, 0x0b, 0x55, 0xb6, 0x0d, 0x4a, 0x02, 0xc1, - 0x8b, 0xaf, 0x61, 0x95, 0x04, 0x95, 0x84, 0x03, 0x65, 0x93, 0x62, 0x1f, 0x22, 0x6c, 0xc8, 0xf7, - 0x5d, 0x05, 0xbb, 0xc2, 0xb3, 0xf6, 0xbb, 0xc7, 0x87, 0xbd, 0x81, 0xb2, 0x85, 0x8d, 0x20, 0x08, - 0x6f, 0x39, 0x8b, 0x8a, 0x89, 0x77, 0xeb, 0x2b, 0xb4, 0x81, 0x23, 0xec, 0x65, 0x43, 0xeb, 0x75, - 0x7a, 0xfb, 0x03, 0x65, 0x3b, 0x2a, 0xb9, 0xad, 0x69, 0x7d, 0x6d, 0xa0, 0x5c, 0x8d, 0x00, 0x83, - 0x61, 0x63, 0x78, 0x3c, 0x50, 0xae, 0x45, 0xad, 0x3c, 0xd2, 0xfa, 0xcd, 0xf6, 0x60, 0xd0, 0xed, - 0x0c, 0x86, 0xca, 0x75, 0x76, 0x15, 0xb6, 0xe2, 0x16, 0x49, 0xe2, 0x7a, 0xa2, 0xa1, 0xda, 0x7e, - 0x7b, 0xa8, 0xdc, 0x88, 0x9a, 0xd1, 0xec, 0x77, 0xbb, 0x0d, 0xf2, 0x18, 0xba, 0x89, 0x44, 0xe4, - 0xac, 0x26, 0x7a, 0xf3, 0x16, 0xb6, 0xeb, 0xb8, 0x97, 0x04, 0xdd, 0x4a, 0xb0, 0xc6, 0xa0, 0xfd, - 0xeb, 0xe3, 0x76, 0xaf, 0xd9, 0x56, 0xde, 0x8e, 0x59, 0x23, 0x82, 0xdd, 0x8e, 0x58, 0x23, 0x02, - 0xdd, 0x89, 0xea, 0x94, 0xa0, 0x81, 0xb2, 0x13, 0x0d, 0xd8, 0xf1, 0xd1, 0xbe, 0xd6, 0x68, 0xb5, - 0x15, 0x15, 0x21, 0x5a, 0xbb, 0xd7, 0x38, 0x94, 0x13, 0x7b, 0x2f, 0x31, 0xb1, 0x47, 0x9d, 0xa1, - 0xa6, 0xdc, 0x8f, 0x26, 0x92, 0x92, 0xef, 0xb0, 0xb7, 0xe0, 0x7a, 0x92, 0xe5, 0xf4, 0x97, 0x9d, - 0xe1, 0x81, 0xf0, 0x29, 0x7b, 0xc0, 0x5d, 0x98, 0x08, 0xd9, 0x6c, 0x35, 0xb9, 0xf3, 0x1c, 0xe5, - 0xc5, 0xd4, 0x43, 0x35, 0x57, 0xbc, 0xab, 0xdc, 0x7d, 0xb4, 0x29, 0x86, 0xa2, 0xd7, 0x6b, 0x37, - 0x87, 0x7d, 0x6d, 0xb0, 0x5b, 0xa1, 0x4f, 0xcc, 0x08, 0x15, 0x44, 0xfd, 0x1a, 0x58, 0xf2, 0x0b, - 0x0a, 0xe2, 0x31, 0x12, 0x83, 0xdc, 0xd8, 0xf7, 0xa6, 0xf2, 0xaa, 0x15, 0x7f, 0xb3, 0x1d, 0x28, - 0xcf, 0xe6, 0x27, 0xe4, 0x71, 0x15, 0x87, 0xcc, 0x49, 0x82, 0xd4, 0x7f, 0x2b, 0x03, 0xb5, 0xb4, - 0xfa, 0x41, 0x86, 0xee, 0xb1, 0xee, 0x7a, 0x21, 0x0f, 0xcb, 0x1a, 0x44, 0x1f, 0x36, 0x18, 0xf7, - 0xbc, 0x90, 0xe2, 0xb2, 0x06, 0xa9, 0xdb, 0xfd, 0xf5, 0x85, 0xdb, 0xfd, 0x0e, 0x5c, 0x49, 0x7d, - 0xb0, 0x22, 0x15, 0x14, 0xb7, 0x1e, 0x85, 0x76, 0x5f, 0x68, 0xbf, 0xc6, 0x82, 0xe5, 0x3e, 0x89, - 0xc0, 0x47, 0xb9, 0x38, 0xf0, 0xd1, 0x01, 0x54, 0x53, 0xda, 0x0e, 0xd9, 0x95, 0xc6, 0xe9, 0x96, - 0x16, 0xed, 0xf1, 0x9b, 0x9b, 0xa9, 0xfe, 0x1b, 0x19, 0xa8, 0x24, 0x75, 0x9f, 0x9f, 0x5d, 0x12, - 0xf9, 0x08, 0x8b, 0xdf, 0xba, 0x6d, 0xca, 0x18, 0xab, 0x12, 0xd4, 0xa1, 0x4f, 0x6b, 0xf1, 0x3b, - 0x83, 0xbd, 0xb3, 0x41, 0xd4, 0x9d, 0x24, 0x88, 0x3c, 0x22, 0x4e, 0xad, 0xd1, 0xd9, 0xde, 0x73, - 0x24, 0x90, 0x1e, 0x11, 0x11, 0x44, 0xbd, 0x03, 0xa5, 0xbd, 0x33, 0xe9, 0x32, 0x9d, 0x0c, 0x4e, - 0x5c, 0xe2, 0x71, 0x96, 0xd4, 0xbf, 0xc8, 0x40, 0x2d, 0xb6, 0xa2, 0x90, 0x03, 0x1a, 0xff, 0xd0, - 0x09, 0x67, 0x87, 0x75, 0xf3, 0x24, 0xf6, 0x7a, 0x59, 0x4f, 0x7a, 0xbd, 0xdc, 0x13, 0x85, 0x65, - 0x93, 0x42, 0x3f, 0xaa, 0x4b, 0x44, 0x71, 0x7a, 0x0a, 0x15, 0xfc, 0xaf, 0x59, 0x63, 0xcb, 0xf7, - 0x2d, 0x33, 0xfd, 0x44, 0x34, 0x26, 0x4e, 0x11, 0xd1, 0x29, 0x2f, 0x0a, 0xe6, 0xb6, 0x32, 0x42, - 0x24, 0x45, 0x2e, 0xfd, 0x3f, 0xb3, 0x50, 0x4e, 0x68, 0x92, 0x3f, 0x8a, 0xfd, 0x6e, 0x41, 0x29, - 0x8e, 0x57, 0x28, 0x42, 0xe7, 0x44, 0x80, 0xd4, 0x5c, 0x65, 0x17, 0xe6, 0xaa, 0x0e, 0x05, 0x9f, - 0x07, 0xae, 0x10, 0x46, 0x6d, 0x99, 0x4c, 0x9b, 0x8f, 0xf3, 0x6f, 0xb8, 0xd7, 0xfa, 0x04, 0x2a, - 0x09, 0xdb, 0xaf, 0x74, 0x53, 0x59, 0xa4, 0x2f, 0xc7, 0x76, 0xe0, 0x80, 0x5d, 0x85, 0x8d, 0xf1, - 0x99, 0x6e, 0x9e, 0xf0, 0x80, 0x2a, 0x25, 0x2d, 0x3f, 0x3e, 0x6b, 0x9d, 0xd0, 0xad, 0xdf, 0x38, - 0x52, 0x9e, 0xb8, 0x45, 0xae, 0x38, 0x96, 0x2a, 0xd2, 0x43, 0x28, 0x8c, 0xcf, 0x92, 0x81, 0x51, - 0x96, 0x86, 0x7c, 0x63, 0x7c, 0x46, 0xe1, 0x50, 0x3e, 0x82, 0x6d, 0xb1, 0x83, 0x1b, 0x81, 0xce, - 0xa3, 0x94, 0x51, 0x1c, 0x4b, 0x1e, 0xaa, 0x78, 0x8b, 0xe3, 0x1a, 0xc1, 0x80, 0x30, 0xc8, 0x71, - 0x2a, 0x54, 0x12, 0x0c, 0xc8, 0x2d, 0x6b, 0x25, 0x2d, 0x05, 0x63, 0xcf, 0xa0, 0x32, 0x3e, 0xe3, - 0x13, 0x3a, 0xf4, 0x0e, 0x2d, 0xf1, 0x6a, 0x73, 0x7b, 0x71, 0x2a, 0xc9, 0x43, 0x30, 0x45, 0xc9, - 0xae, 0xc1, 0x86, 0x66, 0x9c, 0x0f, 0x7e, 0xdd, 0x25, 0x35, 0xb2, 0xa4, 0x89, 0xd4, 0xd7, 0xb9, - 0x62, 0x4d, 0xd9, 0x54, 0xff, 0x93, 0x0c, 0xd4, 0xe2, 0x53, 0x00, 0x2e, 0x42, 0xf6, 0x28, 0xf9, - 0x85, 0xa2, 0xfa, 0xe2, 0x41, 0x01, 0x49, 0x1e, 0x0f, 0x2f, 0x67, 0x3c, 0x72, 0xfe, 0xaa, 0x20, - 0xad, 0xab, 0x8c, 0xf1, 0xd9, 0x95, 0xdf, 0x3b, 0xd9, 0x87, 0xec, 0xf0, 0x72, 0xc6, 0x2d, 0x4e, - 0xb8, 0x29, 0xf2, 0xd3, 0x29, 0xdf, 0x0e, 0xc9, 0x67, 0xf6, 0x79, 0xfb, 0x5b, 0x1e, 0xea, 0xeb, - 0x48, 0xeb, 0x1c, 0x36, 0xb4, 0x6f, 0x75, 0x04, 0x90, 0xda, 0xb0, 0xd7, 0xd7, 0xda, 0x9d, 0xfd, - 0x1e, 0x01, 0x72, 0x64, 0x8f, 0x8a, 0x9b, 0xd8, 0x30, 0xcd, 0xbd, 0xb3, 0x64, 0x7c, 0xcb, 0x4c, - 0x2a, 0xbe, 0x65, 0x14, 0x0a, 0x36, 0x19, 0x61, 0x3b, 0x8c, 0x6e, 0x08, 0x58, 0xb4, 0x0a, 0xa3, - 0x25, 0xcd, 0xde, 0x85, 0xdc, 0xf8, 0xcc, 0xba, 0x4c, 0x1f, 0xf5, 0xd2, 0x0b, 0x88, 0x08, 0xd4, - 0xbf, 0xca, 0x00, 0x4b, 0x35, 0x84, 0x9f, 0x3e, 0x7e, 0x6e, 0x5b, 0xbe, 0x80, 0xba, 0x78, 0x15, - 0xc1, 0xa9, 0x12, 0xd6, 0x7f, 0x31, 0xa4, 0x57, 0xbd, 0xf8, 0xb5, 0x50, 0x1c, 0x47, 0x96, 0x7d, - 0x04, 0x3c, 0x78, 0x36, 0x39, 0x94, 0xe6, 0x5e, 0x73, 0x52, 0xd4, 0x62, 0x9a, 0x38, 0x5a, 0x76, - 0x32, 0x0a, 0x38, 0xbf, 0x38, 0xd8, 0x8c, 0x67, 0x8d, 0xd6, 0xbc, 0xfa, 0x2f, 0x65, 0xe0, 0x4a, - 0x9a, 0x21, 0x7e, 0xbf, 0x5e, 0xa6, 0x43, 0x9e, 0x67, 0x17, 0x43, 0x9e, 0xaf, 0xe2, 0xa7, 0xdc, - 0x4a, 0x7e, 0xfa, 0xdb, 0x19, 0xd8, 0x4e, 0x8c, 0x7e, 0x7c, 0x5e, 0xfc, 0x6b, 0x6a, 0x59, 0x22, - 0xf2, 0x79, 0x2e, 0x15, 0xf9, 0x5c, 0xfd, 0xcb, 0x0c, 0x5c, 0x5b, 0x68, 0x89, 0x66, 0xfd, 0xb5, - 0xb6, 0x25, 0x1d, 0x21, 0x9d, 0x2e, 0x2f, 0x64, 0x38, 0xac, 0xcc, 0xc3, 0x6c, 0x22, 0x42, 0x3a, - 0xdd, 0x68, 0xd1, 0xb5, 0xea, 0xdb, 0x22, 0x6a, 0xa2, 0x1e, 0x5c, 0xba, 0x23, 0x31, 0xd9, 0x25, - 0x82, 0x0c, 0x2e, 0xdd, 0x91, 0xfa, 0xf7, 0x32, 0x70, 0x63, 0xa1, 0x0f, 0x8d, 0x79, 0xe8, 0x89, - 0x3b, 0xf8, 0xbf, 0xa6, 0x6e, 0xdc, 0x81, 0x32, 0x79, 0x28, 0x88, 0x8b, 0x7d, 0x3e, 0xac, 0x60, - 0xc4, 0xf5, 0x2a, 0x90, 0x35, 0x8d, 0x4b, 0x11, 0x40, 0x08, 0x7f, 0xe2, 0x82, 0x3d, 0xf5, 0xe6, - 0xbe, 0xf0, 0x09, 0xa5, 0xdf, 0xea, 0xa7, 0xb0, 0x15, 0x37, 0xbd, 0x29, 0x02, 0xd5, 0xdf, 0x81, - 0xb2, 0x6b, 0x9d, 0xeb, 0x32, 0x8c, 0xbd, 0xf0, 0x8e, 0x76, 0xad, 0x73, 0x41, 0xa0, 0xee, 0x25, - 0x65, 0x61, 0xf4, 0x31, 0x30, 0xc7, 0x4c, 0xf9, 0x4b, 0x79, 0x8e, 0x29, 0x51, 0x58, 0x5a, 0xa2, - 0x97, 0x05, 0xd7, 0x3a, 0x27, 0x3e, 0x3c, 0x17, 0xe5, 0x34, 0x4c, 0x11, 0x36, 0x7e, 0xa5, 0xf3, - 0xdd, 0x0d, 0x28, 0xce, 0xfc, 0xd4, 0x30, 0x15, 0x66, 0x3e, 0xaf, 0xf6, 0xbe, 0xf0, 0xbd, 0x7e, - 0x9d, 0x7f, 0x09, 0xf7, 0xc6, 0x16, 0x1f, 0x0b, 0xcc, 0xc5, 0x1f, 0x0b, 0xfc, 0x4c, 0x88, 0x41, - 0x3a, 0xf9, 0xf1, 0x9a, 0x15, 0xc8, 0xda, 0xe6, 0x05, 0x55, 0x5c, 0xd5, 0xf0, 0x27, 0x69, 0x72, - 0xd6, 0xf7, 0xc2, 0xfd, 0x1b, 0x7f, 0xaa, 0xbb, 0x50, 0xd6, 0x52, 0xc7, 0xdc, 0x4a, 0xc2, 0x62, - 0x14, 0xa4, 0xe3, 0x50, 0xc6, 0x03, 0xa4, 0x95, 0x63, 0x83, 0x51, 0xa0, 0x06, 0x42, 0xf0, 0xbd, - 0x30, 0xfc, 0xd1, 0xa9, 0xe1, 0x77, 0x2d, 0x77, 0x12, 0x9e, 0xe2, 0x90, 0x73, 0x43, 0x6e, 0x72, - 0x08, 0x81, 0x83, 0x24, 0x3b, 0xe0, 0x28, 0x3a, 0x44, 0x2e, 0x3f, 0x2d, 0xe6, 0x5a, 0xe7, 0x22, - 0xff, 0xdb, 0x00, 0x38, 0xfe, 0x02, 0xcd, 0x2f, 0x45, 0x4b, 0x9e, 0x63, 0x72, 0xb4, 0xba, 0x25, - 0xfa, 0x2b, 0x02, 0x60, 0xb5, 0xac, 0xb1, 0xea, 0x88, 0x99, 0xe7, 0x1d, 0x12, 0x83, 0xf0, 0xb3, - 0xa6, 0x91, 0xdd, 0x85, 0x8a, 0xb4, 0x49, 0x50, 0xe8, 0x53, 0x5e, 0x7d, 0x59, 0xc2, 0x7a, 0xf3, - 0xa9, 0xfa, 0x77, 0xb3, 0x50, 0x69, 0x70, 0x8f, 0xaa, 0xd9, 0x65, 0x7f, 0x16, 0xb2, 0x3f, 0x81, - 0xab, 0x14, 0x0b, 0x8d, 0x7f, 0x80, 0x81, 0x1c, 0x99, 0xe8, 0xa9, 0x9c, 0x18, 0xc4, 0x47, 0x89, - 0x41, 0x14, 0x59, 0x1e, 0x0f, 0xce, 0xec, 0x19, 0x7f, 0xa1, 0xd9, 0x31, 0x2f, 0xe8, 0x39, 0x24, - 0xf7, 0x56, 0xa0, 0xb0, 0x69, 0x69, 0x04, 0xc5, 0x41, 0xc2, 0xe2, 0x67, 0x67, 0xa2, 0x58, 0xe1, - 0xae, 0x82, 0xc0, 0xa3, 0x33, 0x4e, 0xf3, 0x08, 0xb6, 0xf8, 0xa3, 0xec, 0xe5, 0x0d, 0x78, 0x93, - 0x23, 0x62, 0xfe, 0x1e, 0xc0, 0x96, 0x08, 0xdd, 0x46, 0xc1, 0xc4, 0xf5, 0x91, 0x37, 0xbb, 0x14, - 0x97, 0xa1, 0xef, 0xbe, 0xa6, 0xa9, 0x1d, 0x4e, 0x8a, 0x20, 0xde, 0xce, 0xcd, 0x20, 0x0d, 0xbd, - 0xd9, 0x86, 0xeb, 0xaf, 0xe9, 0xd3, 0x9b, 0x1c, 0x2e, 0x8a, 0x09, 0x87, 0x8b, 0x9b, 0xbb, 0xb0, - 0xbd, 0xaa, 0xbe, 0x9f, 0x52, 0x86, 0xfa, 0xe7, 0x55, 0x80, 0x98, 0x63, 0x53, 0xea, 0x68, 0x66, - 0x41, 0x1d, 0xfd, 0x49, 0xce, 0x54, 0x9f, 0x42, 0x0d, 0x87, 0x4a, 0x8f, 0x73, 0x64, 0x57, 0xe6, - 0xa8, 0x20, 0xd5, 0x30, 0x8e, 0x3b, 0xb1, 0xec, 0xa4, 0x91, 0x5b, 0xe9, 0xa4, 0xf1, 0x09, 0x14, - 0xf8, 0x55, 0x5b, 0x20, 0x1c, 0x54, 0xaf, 0x2f, 0xae, 0xbe, 0xc7, 0xe2, 0xb5, 0xa7, 0xa4, 0x63, - 0x6d, 0xa8, 0xa1, 0xe8, 0xf7, 0xed, 0xf0, 0x74, 0x9a, 0x0c, 0x7c, 0x72, 0x7b, 0x39, 0xa7, 0x24, - 0x13, 0xdf, 0x73, 0x4b, 0x26, 0x13, 0xda, 0x6b, 0x38, 0x15, 0xf6, 0x5f, 0xd2, 0x5e, 0x0b, 0x49, - 0xed, 0x75, 0x38, 0xe5, 0x56, 0x5f, 0xd4, 0x5e, 0x3f, 0x84, 0x2b, 0xe2, 0x05, 0x3a, 0x66, 0xc0, - 0xe1, 0x24, 0x7a, 0xee, 0x5a, 0xaf, 0x88, 0xf8, 0x67, 0x53, 0x3a, 0xdb, 0x21, 0xf9, 0x37, 0xb0, - 0x3d, 0x3a, 0x35, 0xdc, 0x89, 0xa5, 0x87, 0x27, 0x8e, 0x4e, 0x5f, 0x7d, 0xd2, 0xa7, 0xc6, 0x4c, - 0x28, 0xd5, 0xef, 0x2e, 0x35, 0xb6, 0x49, 0xc4, 0xc3, 0x13, 0x87, 0x1c, 0xff, 0x22, 0x57, 0x9e, - 0xad, 0xd1, 0x22, 0x7c, 0xe1, 0x46, 0x1d, 0x96, 0x6e, 0xd4, 0x17, 0xd5, 0xec, 0xf2, 0x0a, 0x35, - 0x3b, 0x56, 0x96, 0x2b, 0x49, 0x65, 0x99, 0x7d, 0x00, 0x05, 0x11, 0x40, 0x43, 0x58, 0x7e, 0xd9, - 0xf2, 0xea, 0xd0, 0x24, 0x09, 0xd6, 0x24, 0xfd, 0x3b, 0x28, 0xc6, 0x52, 0x8d, 0xd7, 0x94, 0x84, - 0xb1, 0x5d, 0x61, 0xf6, 0x8c, 0x9c, 0x14, 0x85, 0x95, 0xf7, 0x66, 0xa2, 0xe0, 0x08, 0x27, 0xce, - 0xe5, 0x0b, 0x39, 0x6e, 0xfe, 0xc7, 0x1b, 0xb0, 0x21, 0x6e, 0xe9, 0x1f, 0x41, 0xce, 0xf4, 0xbd, - 0x59, 0xf4, 0x2e, 0x69, 0x85, 0xd6, 0x4e, 0x9f, 0x1d, 0x46, 0x05, 0xff, 0x31, 0x6c, 0x18, 0xa6, - 0xa9, 0x8f, 0xcf, 0xd2, 0x37, 0xd2, 0x0b, 0x0a, 0xf4, 0xc1, 0x9a, 0x96, 0x37, 0x48, 0x93, 0xfe, - 0x02, 0x4a, 0x48, 0x1f, 0xbb, 0xfd, 0x96, 0x97, 0x8f, 0x05, 0x52, 0xd5, 0x3d, 0x58, 0xd3, 0x8a, - 0x86, 0x54, 0x7b, 0xff, 0x38, 0x6d, 0xdb, 0xcf, 0x2d, 0x75, 0x70, 0x41, 0x4f, 0x5b, 0xb0, 0xf2, - 0xff, 0x0d, 0xe0, 0xc6, 0xde, 0x68, 0xc7, 0xce, 0x27, 0x2f, 0x3f, 0x97, 0xf6, 0xf7, 0x83, 0x35, - 0x8d, 0xef, 0x5b, 0x72, 0xbf, 0xff, 0x4c, 0xda, 0xdd, 0xa3, 0x4f, 0x2e, 0xae, 0x18, 0x19, 0x14, - 0x83, 0x91, 0xf1, 0x9d, 0x64, 0x22, 0x66, 0x33, 0xe5, 0x77, 0x60, 0xd2, 0x0f, 0x17, 0xd2, 0xbb, - 0x3a, 0x65, 0x8b, 0xb6, 0xf8, 0x67, 0x50, 0xe6, 0x66, 0x58, 0x9e, 0xaf, 0xb8, 0x34, 0xb4, 0xf1, - 0xa6, 0x4c, 0x17, 0x7b, 0xf1, 0x16, 0xdd, 0x94, 0xfd, 0xf4, 0xad, 0xe4, 0xdd, 0xc9, 0xad, 0x95, - 0x03, 0xa5, 0x45, 0xd7, 0x28, 0xbc, 0xb3, 0x1a, 0xcf, 0xc3, 0xba, 0xb0, 0x2d, 0x2e, 0x19, 0xf8, - 0x06, 0x2c, 0xf7, 0x4c, 0x58, 0x9a, 0xaf, 0xd4, 0x0e, 0x7d, 0xb0, 0xa6, 0x31, 0x63, 0x79, 0xdf, - 0x6e, 0xc2, 0x96, 0x6c, 0x12, 0xed, 0xac, 0x09, 0x47, 0xae, 0x64, 0x97, 0xe2, 0x7d, 0xf7, 0x60, - 0x4d, 0xdb, 0x34, 0xd2, 0x20, 0xd6, 0x81, 0x2b, 0xb2, 0x10, 0x32, 0xb6, 0x8b, 0x91, 0xa9, 0x2c, - 0xcd, 0x62, 0x72, 0xaf, 0x3e, 0x58, 0xd3, 0xb6, 0x8c, 0xa5, 0x0d, 0xfc, 0x50, 0xb6, 0x27, 0xa9, - 0x1c, 0xf2, 0x95, 0x78, 0x67, 0xe5, 0x30, 0xc5, 0x9a, 0x6a, 0xd4, 0xb2, 0x18, 0x14, 0x7b, 0x32, - 0xdc, 0xd4, 0xe0, 0xda, 0x6a, 0x09, 0x93, 0xdc, 0x66, 0x72, 0x7c, 0x9b, 0x51, 0x93, 0xdb, 0xcc, - 0x62, 0xcc, 0xb4, 0xc4, 0xa6, 0xf3, 0x2b, 0xa8, 0xa6, 0x44, 0x2c, 0x2b, 0x43, 0x41, 0x7e, 0x03, - 0x87, 0xde, 0x7a, 0x36, 0xfb, 0x47, 0xdf, 0x2a, 0x19, 0x04, 0x77, 0x7a, 0x83, 0x61, 0xa3, 0x37, - 0x54, 0xd6, 0x79, 0xe2, 0xa8, 0xdb, 0x68, 0xb6, 0x95, 0xac, 0xfa, 0x97, 0x59, 0x28, 0x45, 0xf7, - 0x6c, 0x3f, 0xdf, 0x1a, 0x16, 0x99, 0x99, 0xb2, 0x49, 0x33, 0xd3, 0xc2, 0x51, 0x8f, 0x7f, 0xd9, - 0x2a, 0x27, 0xbf, 0x76, 0x94, 0x3c, 0x50, 0x05, 0xcb, 0xa1, 0x74, 0xf2, 0x3f, 0x32, 0x94, 0x4e, - 0xd2, 0xf3, 0x7f, 0x23, 0xed, 0xf9, 0xbf, 0xf0, 0x1d, 0xa4, 0x02, 0x7d, 0x82, 0x24, 0xf9, 0x1d, - 0x24, 0xfa, 0x20, 0xfc, 0x0b, 0xdb, 0x3a, 0x17, 0xae, 0xf2, 0x22, 0x95, 0xde, 0xa1, 0xe1, 0x0d, - 0x3b, 0xf4, 0x8f, 0x91, 0xf6, 0x4f, 0x60, 0x7b, 0x7c, 0x16, 0x7d, 0xf8, 0x24, 0x36, 0xae, 0x54, - 0xa8, 0x49, 0x2b, 0x71, 0xec, 0xdd, 0xe8, 0xab, 0xb4, 0xd5, 0xa4, 0x19, 0x28, 0x9a, 0xad, 0xe8, - 0x33, 0xb5, 0xff, 0x42, 0x06, 0x20, 0xbe, 0x81, 0xfa, 0xbd, 0x4d, 0xb9, 0x09, 0x6b, 0x59, 0xf6, - 0x07, 0xac, 0x65, 0x6f, 0x8a, 0x16, 0xfb, 0x3d, 0x94, 0xa2, 0x3b, 0xc7, 0x9f, 0xcf, 0x58, 0x3f, - 0xa9, 0xca, 0xbf, 0x25, 0xcd, 0xda, 0xd1, 0xa5, 0xdd, 0xef, 0x3b, 0x16, 0xa9, 0xea, 0xb3, 0x6f, - 0xa8, 0xfe, 0x82, 0xdb, 0x96, 0xa3, 0xca, 0xff, 0xc0, 0xab, 0x29, 0xc9, 0xe8, 0xb9, 0xf4, 0x43, - 0xac, 0xb9, 0x30, 0x90, 0xff, 0xfe, 0x55, 0xff, 0xa4, 0x0e, 0xff, 0x1f, 0x19, 0x69, 0xc5, 0x8d, - 0xbe, 0x55, 0xf3, 0x5a, 0xa5, 0x77, 0xb5, 0x21, 0xfa, 0xa7, 0x54, 0xf7, 0x83, 0x36, 0xaa, 0xdc, - 0x0f, 0xd9, 0xa8, 0xde, 0x85, 0x3c, 0xdf, 0xee, 0xf2, 0xaf, 0xb3, 0x4f, 0x71, 0xfc, 0x1b, 0xbf, - 0x4d, 0xa7, 0xaa, 0x42, 0xc9, 0xe7, 0xfd, 0xdd, 0x96, 0xe5, 0xca, 0xef, 0xea, 0xd1, 0xcb, 0xa4, - 0x7f, 0x82, 0x4b, 0xd4, 0x9f, 0x3b, 0x24, 0x3f, 0x6c, 0xb6, 0x50, 0xff, 0xbf, 0x0c, 0x54, 0x53, - 0x3e, 0x04, 0x3f, 0xa3, 0x8a, 0x95, 0x72, 0x39, 0xfb, 0x8f, 0x91, 0x5c, 0x4e, 0x39, 0x15, 0x17, - 0xd3, 0x4e, 0xc5, 0x28, 0xee, 0x2a, 0xa9, 0x23, 0xcc, 0xaa, 0xc3, 0x4e, 0x66, 0xe5, 0x61, 0xe7, - 0x76, 0xf4, 0x79, 0xf1, 0x4e, 0x8b, 0xfb, 0xf0, 0x56, 0xb5, 0x04, 0x84, 0x7d, 0x09, 0x37, 0x84, - 0x11, 0x81, 0x8f, 0x8f, 0x37, 0xd6, 0xa3, 0x8f, 0x8f, 0x8b, 0x43, 0xf9, 0x35, 0x4e, 0xc0, 0xbf, - 0x2c, 0x38, 0x6e, 0x48, 0xac, 0xda, 0x81, 0x6a, 0xca, 0x39, 0x03, 0xf7, 0x96, 0x89, 0xe3, 0x9d, - 0x18, 0x8e, 0x68, 0x8b, 0x48, 0xb1, 0x1d, 0xc8, 0x9f, 0x9f, 0x5a, 0xbe, 0xb5, 0xe2, 0xf3, 0x0e, - 0x1c, 0xa1, 0xfe, 0x12, 0x2a, 0x49, 0x47, 0x31, 0xf6, 0x01, 0xe4, 0xed, 0xd0, 0x9a, 0x4a, 0xf3, - 0xc8, 0xb5, 0x65, 0x5f, 0xb2, 0x4e, 0x68, 0x4d, 0x35, 0x4e, 0xa4, 0xfe, 0x59, 0x06, 0x94, 0x45, - 0x1c, 0x7d, 0xd1, 0xf5, 0x32, 0x08, 0xad, 0xa9, 0x6c, 0x0c, 0x4f, 0x25, 0x1a, 0xb9, 0x9e, 0x6a, - 0xa4, 0xb4, 0x22, 0x65, 0xd3, 0xdf, 0xc8, 0xe3, 0x4a, 0xc9, 0x8a, 0x8f, 0xff, 0x13, 0x82, 0x3d, - 0x80, 0xa2, 0x6f, 0xd1, 0xa7, 0xf1, 0xcd, 0x15, 0x2f, 0x76, 0x22, 0x9c, 0xfa, 0x77, 0x32, 0x50, - 0x10, 0x5e, 0x6d, 0x2b, 0xed, 0x55, 0xef, 0x41, 0x81, 0x7f, 0x26, 0x5f, 0x06, 0x8d, 0x5d, 0xf2, - 0xfd, 0x95, 0x78, 0x76, 0x9b, 0xfb, 0xfa, 0xa5, 0xed, 0x57, 0x47, 0x8e, 0xe1, 0x6a, 0x04, 0x17, - 0x1f, 0x0c, 0x35, 0xa6, 0xe2, 0x11, 0x09, 0x8f, 0xf6, 0x09, 0x04, 0xa2, 0x67, 0x22, 0xea, 0x1f, - 0x43, 0x41, 0x78, 0xcd, 0xad, 0x6c, 0xca, 0x1b, 0x3e, 0x7b, 0xae, 0xee, 0x00, 0xc4, 0x6e, 0x74, - 0xab, 0x4a, 0x50, 0x1f, 0x41, 0x51, 0x7a, 0xce, 0x21, 0xff, 0xc5, 0x55, 0x8b, 0xa7, 0x60, 0xc9, - 0xc6, 0x38, 0xe2, 0x93, 0x4d, 0x5d, 0x6f, 0x74, 0x46, 0xc6, 0xf2, 0x8f, 0x80, 0xde, 0xc5, 0x0d, - 0x97, 0xc2, 0xa2, 0xa6, 0x3f, 0xee, 0x15, 0x11, 0xb1, 0x47, 0x10, 0xc9, 0xcb, 0x37, 0x99, 0x16, - 0xd4, 0x86, 0x7c, 0x41, 0x49, 0x5c, 0xf6, 0x54, 0x58, 0x53, 0xbb, 0x14, 0x96, 0x3b, 0x93, 0xfc, - 0xb4, 0x41, 0xaa, 0x4d, 0x5a, 0x82, 0x4c, 0xad, 0x41, 0x25, 0xe9, 0xee, 0xa3, 0x36, 0x60, 0xeb, - 0xd0, 0x0a, 0x0d, 0x94, 0x3f, 0x32, 0x58, 0x24, 0xe7, 0x5f, 0xfc, 0x91, 0xe6, 0xdf, 0x45, 0x3a, - 0x8d, 0x13, 0xa9, 0x7f, 0x99, 0x03, 0x65, 0x11, 0xf7, 0x43, 0xaf, 0x49, 0xef, 0x40, 0xd9, 0x23, - 0xbe, 0x48, 0x7d, 0x12, 0x96, 0x83, 0x12, 0x2f, 0x14, 0x52, 0x5f, 0xf3, 0x2b, 0xda, 0xc1, 0x01, - 0xff, 0x9e, 0xdf, 0x75, 0xfe, 0x74, 0xd0, 0xf1, 0x46, 0xc4, 0xd6, 0x15, 0x7a, 0x29, 0xd8, 0xf5, - 0x46, 0xf4, 0x48, 0x55, 0x58, 0x27, 0xb8, 0x0f, 0x6a, 0x45, 0x2b, 0x0a, 0x93, 0x04, 0xdd, 0xdf, - 0x89, 0x77, 0x0b, 0x61, 0x20, 0xa2, 0x45, 0x14, 0x39, 0x60, 0x18, 0xc8, 0x0f, 0xf3, 0x8c, 0xc4, - 0xf7, 0x4b, 0xb3, 0xf4, 0x61, 0x9e, 0xa6, 0x4b, 0x6f, 0x54, 0xe9, 0x73, 0x05, 0x23, 0xf1, 0xe5, - 0x66, 0xf1, 0x69, 0x24, 0x44, 0xdd, 0xe3, 0x5f, 0x78, 0xf5, 0xad, 0x20, 0xe0, 0xd1, 0x99, 0x4b, - 0x22, 0x2c, 0xb7, 0x00, 0x46, 0xc1, 0xef, 0xc5, 0x27, 0x28, 0x91, 0x04, 0x44, 0x8c, 0x68, 0xfe, - 0x0d, 0x4a, 0x24, 0xb8, 0x01, 0xc5, 0xdf, 0x7a, 0xae, 0x45, 0x56, 0x8e, 0x32, 0xb5, 0xaa, 0x80, - 0xe9, 0x43, 0x63, 0x86, 0x1b, 0x81, 0x43, 0x81, 0x49, 0xf8, 0xeb, 0x4c, 0x9e, 0x50, 0xff, 0xdb, - 0x0c, 0x6c, 0x2f, 0x8e, 0x35, 0xb1, 0x51, 0x05, 0x8a, 0xcd, 0x7e, 0x57, 0xef, 0x35, 0x0e, 0xdb, - 0xca, 0x1a, 0xdb, 0x84, 0x72, 0x7f, 0xf7, 0xeb, 0x76, 0x73, 0xc8, 0x01, 0x19, 0x8a, 0x52, 0x34, - 0xd0, 0x0f, 0x3a, 0xad, 0x56, 0xbb, 0xc7, 0x4f, 0x14, 0xfd, 0xdd, 0xaf, 0xf5, 0x6e, 0xbf, 0xc9, - 0xbf, 0xbc, 0x29, 0x1d, 0x21, 0x06, 0x4a, 0x8e, 0xdc, 0x24, 0xc8, 0x1d, 0x1e, 0x93, 0x79, 0xee, - 0xe7, 0xfd, 0x72, 0xa0, 0x37, 0x7b, 0x43, 0x65, 0x03, 0x53, 0xbd, 0xe3, 0x6e, 0x97, 0x52, 0xe4, - 0xd0, 0xd9, 0xec, 0x1f, 0x1e, 0x69, 0xed, 0xc1, 0x40, 0x1f, 0x74, 0x7e, 0xd3, 0x56, 0x8a, 0x54, - 0xb3, 0xd6, 0xd9, 0xef, 0xf4, 0x38, 0xa0, 0xc4, 0x0a, 0x90, 0x3d, 0xec, 0xf4, 0x78, 0x74, 0xa6, - 0xc3, 0xc6, 0x37, 0x4a, 0x19, 0x7f, 0x0c, 0x8e, 0x0f, 0x95, 0x0a, 0x2b, 0x41, 0xbe, 0xdb, 0x7e, - 0xd1, 0xee, 0x2a, 0x55, 0xf5, 0x7f, 0xce, 0x4a, 0x8d, 0x98, 0x3c, 0x9d, 0x7e, 0x8c, 0x16, 0xb8, - 0xea, 0x7e, 0x31, 0x1a, 0xb4, 0x6c, 0x62, 0xd0, 0xd8, 0x5d, 0xa8, 0x88, 0x4d, 0x21, 0xf5, 0x19, - 0x5f, 0x01, 0x23, 0x96, 0xbb, 0x07, 0xd5, 0xc8, 0x39, 0x20, 0xf1, 0x31, 0x9d, 0x8a, 0x04, 0xae, - 0xb8, 0xbe, 0xd8, 0x58, 0x71, 0x7d, 0x31, 0xb3, 0x43, 0x3c, 0x65, 0xa3, 0xcc, 0xe5, 0x9c, 0x54, - 0x42, 0x08, 0x7d, 0x87, 0x9e, 0x1e, 0x8e, 0x22, 0x7a, 0xee, 0xda, 0xf2, 0x3b, 0xe0, 0x45, 0x04, - 0x1c, 0xbb, 0x76, 0xb8, 0xe8, 0x9c, 0x50, 0x5a, 0x72, 0x4e, 0x48, 0x6e, 0xce, 0x90, 0xde, 0x9c, - 0xdf, 0x8e, 0xf6, 0x48, 0x44, 0xf2, 0x0f, 0x80, 0x97, 0xa2, 0x5d, 0x90, 0xbe, 0xd7, 0x3c, 0xf7, - 0x29, 0x50, 0x6d, 0x82, 0xac, 0x42, 0x64, 0x8a, 0xc0, 0x44, 0xbb, 0x22, 0xbd, 0xdb, 0x4f, 0x53, - 0xd3, 0x59, 0xba, 0xa4, 0xd5, 0xd2, 0xa4, 0xec, 0x31, 0x5c, 0x11, 0xbc, 0x9d, 0x1a, 0x5b, 0xf1, - 0xe4, 0x97, 0xa3, 0x1a, 0xf1, 0x08, 0xab, 0x7f, 0x04, 0x45, 0xe9, 0xd4, 0xf6, 0xc3, 0xca, 0xee, - 0x8a, 0x79, 0x55, 0xff, 0xdd, 0x75, 0x28, 0x45, 0x2e, 0x6e, 0x3f, 0x8a, 0x3b, 0xe8, 0xab, 0x61, - 0xc1, 0x59, 0x52, 0xc4, 0x14, 0x11, 0x20, 0x67, 0x4a, 0xbc, 0x1f, 0x9b, 0xfb, 0xb6, 0xd4, 0xd8, - 0x38, 0xe4, 0xd8, 0xb7, 0x29, 0x1a, 0x9d, 0xed, 0x26, 0x1e, 0xe7, 0x96, 0xb4, 0x22, 0x02, 0x68, - 0xa1, 0xdd, 0x00, 0xfa, 0x4d, 0x39, 0x39, 0x93, 0x14, 0x30, 0x8d, 0xf9, 0xae, 0x45, 0xe7, 0x3f, - 0xce, 0x1b, 0x22, 0x45, 0xdf, 0x3c, 0xe3, 0xde, 0x35, 0xdc, 0xa7, 0x40, 0x7e, 0xd8, 0xf8, 0x2d, - 0x28, 0xcd, 0xa3, 0x2f, 0x63, 0x0b, 0x8e, 0x98, 0xcb, 0xef, 0x62, 0xa7, 0x67, 0xb5, 0xb4, 0x38, - 0xab, 0x8b, 0x3c, 0x0d, 0x4b, 0x3c, 0xad, 0x86, 0x50, 0x10, 0x6e, 0x7e, 0x3f, 0x3c, 0xe0, 0x3f, - 0x38, 0x54, 0x0a, 0x64, 0x0d, 0x47, 0xbe, 0x08, 0xc6, 0x9f, 0x0b, 0x0d, 0xcb, 0x2d, 0x34, 0x4c, - 0xfd, 0xd7, 0xd7, 0x01, 0x62, 0x77, 0x41, 0xf6, 0xe1, 0x82, 0x6b, 0x72, 0x66, 0x69, 0xdb, 0x5f, - 0xf0, 0x48, 0x5e, 0x08, 0xcf, 0xb8, 0xfe, 0x23, 0xc2, 0x33, 0x3e, 0x81, 0x6a, 0xe0, 0x8f, 0xde, - 0x68, 0x70, 0x2f, 0x07, 0xfe, 0x28, 0xb2, 0xb7, 0x7f, 0x04, 0x98, 0xa4, 0xd0, 0xcd, 0xe6, 0xeb, - 0xbf, 0x85, 0x58, 0x0a, 0xfc, 0x51, 0xff, 0xe4, 0xbb, 0x16, 0x7f, 0xb4, 0x67, 0x06, 0xa1, 0xbe, - 0x4a, 0x4a, 0x6c, 0x9a, 0x41, 0xd8, 0x4a, 0x0a, 0x8a, 0xfb, 0x50, 0x43, 0xda, 0x25, 0x61, 0x51, - 0x31, 0x83, 0xf8, 0x82, 0x45, 0xfd, 0xa7, 0xe5, 0x95, 0xf4, 0x82, 0x2d, 0x97, 0x7d, 0x2e, 0x0e, - 0xe2, 0x09, 0x25, 0xa2, 0xbe, 0xca, 0xf4, 0xcb, 0x5f, 0xe3, 0x46, 0xa4, 0xcb, 0x5f, 0x31, 0x5e, - 0xff, 0xb1, 0x5f, 0x31, 0xde, 0x01, 0x88, 0x83, 0x67, 0xe3, 0x0a, 0x8c, 0x9e, 0xeb, 0x94, 0xf8, - 0x43, 0x9c, 0x47, 0x87, 0x70, 0xa5, 0x31, 0x99, 0xf8, 0xd6, 0x84, 0xbe, 0xb4, 0xe4, 0x8e, 0xed, - 0x89, 0xf4, 0xf9, 0x6c, 0xec, 0xef, 0xeb, 0xcd, 0x7e, 0x6f, 0xaf, 0xb3, 0x2f, 0x63, 0x8b, 0xdd, - 0x85, 0xb7, 0x13, 0xc0, 0x7d, 0xad, 0x7f, 0x7c, 0x84, 0x89, 0x66, 0x63, 0xa8, 0xf7, 0xb5, 0x56, - 0x5b, 0x53, 0x32, 0x8f, 0xee, 0x42, 0xa5, 0x29, 0x76, 0xca, 0x28, 0xde, 0x99, 0xe7, 0x5a, 0xfc, - 0x7b, 0x6e, 0xdd, 0xdf, 0x7e, 0xaa, 0x64, 0x1e, 0xa9, 0x50, 0x4e, 0x7c, 0x4d, 0x11, 0x29, 0x0e, - 0x8c, 0xe0, 0x54, 0x7c, 0xdb, 0xcb, 0x70, 0x27, 0x96, 0x92, 0x79, 0xf4, 0x00, 0x75, 0xf8, 0xe4, - 0xb7, 0x0c, 0x01, 0x36, 0x7a, 0x9e, 0x3f, 0x35, 0x1c, 0x41, 0x67, 0xcd, 0x03, 0xa4, 0xfb, 0x08, - 0xae, 0xae, 0xfc, 0x32, 0x23, 0xbd, 0x09, 0xb3, 0xa7, 0x33, 0xc7, 0xe2, 0xaf, 0x9b, 0x0e, 0x2e, - 0x4f, 0x7c, 0xdb, 0x54, 0x32, 0x8f, 0x9e, 0x2d, 0x7c, 0xb9, 0xeb, 0xb8, 0xb7, 0xdb, 0x3f, 0xee, - 0xb5, 0x28, 0x14, 0x19, 0x45, 0xfc, 0x6b, 0x76, 0x8f, 0x07, 0x9d, 0x17, 0x62, 0x6b, 0x6d, 0x7f, - 0x23, 0x93, 0xeb, 0x8f, 0xbe, 0x91, 0x41, 0x35, 0x64, 0xab, 0xbb, 0xfd, 0x46, 0x8b, 0x6f, 0xc9, - 0x51, 0x00, 0xc3, 0xe1, 0x2e, 0xff, 0xe2, 0x97, 0xd6, 0x1e, 0x1c, 0x77, 0x87, 0x32, 0x36, 0x62, - 0x0d, 0xa0, 0xd3, 0x6c, 0xef, 0xb6, 0xb5, 0x7d, 0x24, 0xc8, 0x62, 0xfa, 0xb0, 0xdf, 0xdb, 0xef, - 0xb7, 0x76, 0x31, 0x9d, 0x7b, 0xf4, 0xdf, 0xac, 0x83, 0xb2, 0x18, 0x07, 0x85, 0xbd, 0x05, 0xd7, - 0x89, 0x48, 0x3f, 0xd2, 0xda, 0xad, 0x4e, 0x93, 0xbb, 0xc3, 0xbe, 0x68, 0x74, 0x3b, 0x58, 0xe7, - 0x75, 0xb8, 0xb2, 0x88, 0x6c, 0xf4, 0x5a, 0x3c, 0x62, 0xda, 0x22, 0xa2, 0xfd, 0xeb, 0xe3, 0x46, - 0x57, 0x59, 0x67, 0x6f, 0xc3, 0x8d, 0x45, 0x54, 0xaf, 0x3f, 0x14, 0xe8, 0x2c, 0xab, 0xc3, 0xf6, - 0x22, 0xba, 0xdb, 0x1e, 0xa0, 0xde, 0x70, 0x1b, 0x6e, 0xae, 0xc2, 0x88, 0x9c, 0xf9, 0x55, 0x2d, - 0xdd, 0x27, 0xb5, 0x43, 0x53, 0x36, 0x90, 0x65, 0x5e, 0x83, 0x14, 0xf9, 0x0b, 0xec, 0x1a, 0xb0, - 0xe5, 0x9e, 0x2a, 0xc5, 0x95, 0x23, 0x30, 0xe0, 0x9f, 0x19, 0x2f, 0xb1, 0x3b, 0xf0, 0xd6, 0x2a, - 0x64, 0x5f, 0x7c, 0x87, 0x1c, 0x1e, 0xfd, 0x83, 0x0c, 0xd4, 0x5f, 0xf7, 0x2c, 0x9e, 0xa9, 0x70, - 0x5b, 0x3b, 0xee, 0x51, 0x04, 0x43, 0x1e, 0x6c, 0x51, 0x7f, 0xde, 0xfe, 0x76, 0x21, 0x30, 0xdd, - 0xdb, 0x70, 0x63, 0x05, 0x8d, 0xd6, 0x78, 0xa9, 0xbf, 0xf8, 0x44, 0xc9, 0xb0, 0xf7, 0xe1, 0xdd, - 0x15, 0xe8, 0xbd, 0x6e, 0xbf, 0x31, 0xd4, 0x7f, 0xd3, 0xd6, 0xfa, 0x7a, 0xb3, 0xdb, 0x1f, 0xb4, - 0x5b, 0x48, 0xbc, 0xce, 0x76, 0xe0, 0xd6, 0x0a, 0xe2, 0x01, 0x0f, 0x84, 0xf9, 0xe2, 0x13, 0x25, - 0xcb, 0xde, 0x81, 0xbb, 0xaf, 0xa7, 0xd8, 0x43, 0xcd, 0xec, 0xc5, 0x27, 0x4a, 0xee, 0xd1, 0xaf, - 0xa0, 0xfe, 0xba, 0xb7, 0x66, 0xb8, 0x2c, 0x9a, 0x07, 0x0d, 0x7a, 0xcf, 0x87, 0xda, 0x5c, 0x5f, - 0xe7, 0x29, 0xb2, 0x39, 0x6b, 0xed, 0x6e, 0x9b, 0x1c, 0xb2, 0x1f, 0xfd, 0x2e, 0x93, 0x38, 0xd9, - 0xc8, 0xf7, 0x42, 0x11, 0x40, 0xac, 0xd5, 0x24, 0x48, 0xb3, 0x0c, 0x53, 0xc9, 0xe0, 0x2c, 0xa5, - 0x40, 0x5d, 0x6f, 0x64, 0x38, 0xca, 0x3a, 0xb9, 0x5e, 0x4b, 0x38, 0xbd, 0x73, 0x55, 0xb2, 0x38, - 0x74, 0x11, 0xac, 0xeb, 0x9d, 0x1f, 0xf9, 0xb6, 0xe7, 0xdb, 0xe1, 0x25, 0x47, 0xe7, 0x1e, 0xfd, - 0x93, 0xc2, 0x6d, 0x20, 0x25, 0xef, 0xb0, 0x82, 0x86, 0x69, 0xc6, 0x30, 0xda, 0x62, 0x39, 0xaf, - 0x93, 0x7e, 0xb1, 0x80, 0xc8, 0x20, 0x7f, 0x48, 0xf3, 0xcb, 0x22, 0x72, 0x1d, 0x91, 0x9a, 0x45, - 0x4e, 0xbb, 0x4b, 0xc8, 0xec, 0xee, 0x57, 0x7f, 0xff, 0xaf, 0x6e, 0x67, 0xfe, 0xab, 0xbf, 0xba, - 0x9d, 0xf9, 0x5f, 0xfe, 0xea, 0xf6, 0xda, 0x9f, 0xfd, 0x6f, 0xb7, 0x33, 0xbf, 0xf9, 0x70, 0x62, - 0x87, 0xa7, 0xf3, 0x93, 0xc7, 0x23, 0x6f, 0xfa, 0xd1, 0xd4, 0x08, 0x7d, 0xfb, 0x82, 0x2b, 0x3a, - 0x32, 0xe1, 0x5a, 0x1f, 0xcd, 0xce, 0x26, 0x1f, 0xcd, 0x4e, 0x3e, 0x42, 0x91, 0x7b, 0xb2, 0x31, - 0xf3, 0xbd, 0xd0, 0x7b, 0xfa, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x75, 0x89, 0x46, 0xdb, 0x2c, - 0x96, 0x00, 0x00, + 0x0f, 0xf8, 0x81, 0x84, 0x80, 0x5f, 0x4f, 0xba, 0x20, 0x21, 0x24, 0x04, 0x42, 0xa0, 0x2b, 0xee, + 0x7b, 0x42, 0x02, 0xae, 0xf8, 0xf3, 0x10, 0x1f, 0x42, 0x3c, 0x01, 0x02, 0xa4, 0x07, 0x5c, 0xfe, + 0xf2, 0x04, 0x12, 0x48, 0x48, 0xfc, 0x01, 0xad, 0xb5, 0xf7, 0xae, 0x0f, 0xdb, 0x99, 0xcc, 0xcc, + 0x39, 0x57, 0x7a, 0x7f, 0xba, 0xbd, 0xd7, 0x5a, 0xfb, 0x7b, 0xed, 0xb5, 0xd7, 0x5e, 0x7b, 0xed, + 0x55, 0x00, 0x33, 0xc7, 0x70, 0x1f, 0xcf, 0x7c, 0x2f, 0xf4, 0x58, 0x0e, 0x7f, 0xdf, 0xfc, 0x70, + 0x62, 0x87, 0xa7, 0xf3, 0x93, 0xc7, 0x23, 0x6f, 0xfa, 0xd1, 0xc4, 0x9b, 0x78, 0x1f, 0x11, 0xf2, + 0x64, 0x3e, 0xa6, 0x14, 0x25, 0xe8, 0x17, 0xcf, 0x74, 0x13, 0x1c, 0x6f, 0x74, 0x26, 0x7e, 0x6f, + 0x86, 0xf6, 0xd4, 0x0a, 0x42, 0x63, 0x3a, 0xe3, 0x00, 0xf5, 0x2f, 0x32, 0x90, 0x1b, 0x5e, 0xce, + 0x2c, 0x56, 0x83, 0x75, 0xdb, 0xac, 0x67, 0x76, 0x32, 0x0f, 0xf3, 0xda, 0xba, 0x6d, 0xb2, 0x1d, + 0x28, 0xbb, 0x5e, 0xd8, 0x9b, 0x3b, 0x8e, 0x71, 0xe2, 0x58, 0xf5, 0xf5, 0x9d, 0xcc, 0xc3, 0xa2, + 0x96, 0x04, 0xb1, 0xb7, 0xa0, 0x64, 0xcc, 0x43, 0x4f, 0xb7, 0xdd, 0x91, 0x5f, 0xcf, 0x12, 0xbe, + 0x88, 0x80, 0x8e, 0x3b, 0xf2, 0xd9, 0x36, 0xe4, 0xcf, 0x6d, 0x33, 0x3c, 0xad, 0xe7, 0xa8, 0x44, + 0x9e, 0x40, 0x68, 0x30, 0x32, 0x1c, 0xab, 0x9e, 0xe7, 0x50, 0x4a, 0x20, 0x34, 0xa4, 0x4a, 0x36, + 0x76, 0x32, 0x0f, 0x4b, 0x1a, 0x4f, 0xb0, 0xdb, 0x00, 0x96, 0x3b, 0x9f, 0xbe, 0x32, 0x9c, 0xb9, + 0x15, 0xd4, 0x0b, 0x84, 0x4a, 0x40, 0xd4, 0xaf, 0xa0, 0x34, 0x0d, 0x26, 0x07, 0x96, 0x61, 0x5a, + 0x3e, 0xbb, 0x0e, 0x85, 0x69, 0x30, 0xd1, 0x43, 0x63, 0x22, 0xba, 0xb0, 0x31, 0x0d, 0x26, 0x43, + 0x63, 0xc2, 0x6e, 0x40, 0x91, 0x10, 0x97, 0x33, 0xde, 0x87, 0xbc, 0x86, 0x84, 0xd8, 0x63, 0xf5, + 0xef, 0x6c, 0x40, 0xa1, 0x6b, 0x87, 0x96, 0x6f, 0x38, 0xec, 0x1a, 0x6c, 0xd8, 0x81, 0x3b, 0x77, + 0x1c, 0xca, 0x5e, 0xd4, 0x44, 0x8a, 0x5d, 0x83, 0xbc, 0xfd, 0xec, 0x95, 0xe1, 0xf0, 0xbc, 0x07, + 0x6b, 0x1a, 0x4f, 0xb2, 0x3a, 0x6c, 0xd8, 0x9f, 0x7c, 0x8e, 0x88, 0xac, 0x40, 0x88, 0x34, 0x61, + 0x9e, 0x3e, 0x41, 0x4c, 0x2e, 0xc2, 0x50, 0x9a, 0x30, 0x9f, 0x7f, 0x8a, 0x18, 0xec, 0x7d, 0x96, + 0x30, 0x94, 0xc6, 0x5a, 0xe6, 0x54, 0x0b, 0x0e, 0x40, 0x15, 0x6b, 0x99, 0xcb, 0x5a, 0xe6, 0xbc, + 0x96, 0x82, 0x40, 0x88, 0x34, 0x61, 0x78, 0x2d, 0xc5, 0x08, 0x13, 0xd5, 0x32, 0xe7, 0xb5, 0x94, + 0x76, 0x32, 0x0f, 0x73, 0x84, 0xe1, 0xb5, 0x6c, 0x43, 0xce, 0x44, 0x38, 0xec, 0x64, 0x1e, 0x66, + 0x0e, 0xd6, 0x34, 0x4a, 0x21, 0x34, 0x40, 0x68, 0x19, 0x07, 0x18, 0xa1, 0x81, 0x80, 0x9e, 0x20, + 0xb4, 0x82, 0xa3, 0x81, 0xd0, 0x13, 0x01, 0x1d, 0x23, 0xb4, 0xba, 0x93, 0x79, 0xb8, 0x8e, 0x50, + 0x4c, 0xb1, 0x9b, 0x50, 0x30, 0x8d, 0xd0, 0x42, 0x44, 0x4d, 0x74, 0x59, 0x02, 0x10, 0x87, 0x1c, + 0x87, 0xb8, 0x4d, 0xd1, 0x69, 0x09, 0x60, 0x2a, 0x94, 0x91, 0x4c, 0xe2, 0x15, 0x81, 0x4f, 0x02, + 0xd9, 0x67, 0x50, 0x31, 0xad, 0x91, 0x3d, 0x35, 0x1c, 0xde, 0xa7, 0xad, 0x9d, 0xcc, 0xc3, 0xf2, + 0x93, 0xcd, 0xc7, 0xb4, 0x26, 0x22, 0xcc, 0xc1, 0x9a, 0x96, 0x22, 0x63, 0xcf, 0xa0, 0x2a, 0xd2, + 0x9f, 0x3c, 0xa1, 0x81, 0x65, 0x94, 0x4f, 0x49, 0xe5, 0xfb, 0xe4, 0xc9, 0xb3, 0x83, 0x35, 0x2d, + 0x4d, 0xc8, 0xee, 0x43, 0x25, 0x5a, 0x22, 0x98, 0xf1, 0x8a, 0x68, 0x55, 0x0a, 0x8a, 0xdd, 0xfa, + 0x2e, 0xf0, 0x5c, 0x24, 0xd8, 0x16, 0xe3, 0x26, 0x01, 0x6c, 0x07, 0xc0, 0xb4, 0xc6, 0xc6, 0xdc, + 0x09, 0x11, 0x7d, 0x55, 0x0c, 0x60, 0x02, 0xc6, 0x6e, 0x43, 0x69, 0x3e, 0xc3, 0x5e, 0xbe, 0x30, + 0x9c, 0xfa, 0x35, 0x41, 0x10, 0x83, 0xb0, 0x74, 0xe4, 0x73, 0xc4, 0x5e, 0x17, 0xb3, 0x2b, 0x01, + 0x38, 0xbd, 0xaf, 0xac, 0x11, 0xa2, 0xea, 0xa2, 0x62, 0x91, 0xc6, 0x55, 0x64, 0x07, 0xbb, 0xb6, + 0x5b, 0xbf, 0x41, 0x1c, 0xcc, 0x13, 0xec, 0x16, 0x64, 0x03, 0x7f, 0x54, 0xbf, 0x49, 0xfd, 0x07, + 0xde, 0xff, 0xf6, 0xc5, 0xcc, 0xd7, 0x10, 0xbc, 0x5b, 0x80, 0x3c, 0xad, 0x26, 0xf5, 0x16, 0x14, + 0x8f, 0x0c, 0xdf, 0x98, 0x6a, 0xd6, 0x98, 0x29, 0x90, 0x9d, 0x79, 0x81, 0x58, 0x47, 0xf8, 0x53, + 0xed, 0xc2, 0xc6, 0x0b, 0xc3, 0x47, 0x1c, 0x83, 0x9c, 0x6b, 0x4c, 0x2d, 0x42, 0x96, 0x34, 0xfa, + 0x8d, 0x6b, 0x27, 0xb8, 0x0c, 0x42, 0x6b, 0x2a, 0x84, 0x84, 0x48, 0x21, 0x7c, 0xe2, 0x78, 0x27, + 0x62, 0x8d, 0x14, 0x35, 0x91, 0x52, 0xff, 0x99, 0x0c, 0x6c, 0x34, 0x3d, 0x07, 0x8b, 0xbb, 0x0e, + 0x05, 0xdf, 0x72, 0xf4, 0xb8, 0xba, 0x0d, 0xdf, 0x72, 0x8e, 0xbc, 0x00, 0x11, 0x23, 0x8f, 0x23, + 0xf8, 0xaa, 0xdd, 0x18, 0x79, 0x84, 0x90, 0x0d, 0xc8, 0x26, 0x1a, 0x70, 0x03, 0x8a, 0xe1, 0x89, + 0xa3, 0x13, 0x3c, 0x47, 0xf0, 0x42, 0x78, 0xe2, 0xf4, 0x10, 0x75, 0x1d, 0x0a, 0xe6, 0x09, 0xc7, + 0xe4, 0x09, 0xb3, 0x61, 0x9e, 0x20, 0x42, 0xfd, 0x12, 0x4a, 0x9a, 0x71, 0x2e, 0x9a, 0x71, 0x15, + 0x36, 0xb0, 0x00, 0x21, 0xff, 0x72, 0x5a, 0x3e, 0x3c, 0x71, 0x3a, 0x26, 0x82, 0xb1, 0x11, 0xb6, + 0x49, 0x6d, 0xc8, 0x69, 0xf9, 0x91, 0xe7, 0x74, 0x4c, 0x75, 0x08, 0xd0, 0xf4, 0x7c, 0xff, 0x67, + 0x77, 0x61, 0x1b, 0xf2, 0xa6, 0x35, 0x0b, 0x4f, 0xb9, 0xe8, 0xd0, 0x78, 0x42, 0x7d, 0x04, 0x45, + 0x9c, 0x97, 0xae, 0x1d, 0x84, 0xec, 0x36, 0xe4, 0x1c, 0x3b, 0x08, 0xeb, 0x99, 0x9d, 0xec, 0xc2, + 0xac, 0x11, 0x5c, 0xdd, 0x81, 0xe2, 0xa1, 0x71, 0xf1, 0x02, 0x67, 0x0e, 0x4b, 0xa3, 0x29, 0x14, + 0x53, 0x22, 0xe6, 0xb3, 0x02, 0x30, 0x34, 0xfc, 0x89, 0x15, 0x92, 0xa4, 0xfb, 0xbf, 0x32, 0x50, + 0x1e, 0xcc, 0x4f, 0xbe, 0x9f, 0x5b, 0xfe, 0x25, 0xb6, 0xf9, 0x21, 0x64, 0xc3, 0xcb, 0x19, 0xe5, + 0xa8, 0x3d, 0xb9, 0xc6, 0x8b, 0x4f, 0xe0, 0x1f, 0x63, 0x26, 0x0d, 0x49, 0xb0, 0x13, 0xae, 0x67, + 0x5a, 0x72, 0x0c, 0xf2, 0xda, 0x06, 0x26, 0x3b, 0x26, 0x6e, 0x17, 0xde, 0x4c, 0xcc, 0xc2, 0xba, + 0x37, 0x63, 0x3b, 0x90, 0x1f, 0x9d, 0xda, 0x8e, 0x49, 0x13, 0x90, 0x6e, 0x33, 0x47, 0xe0, 0x2c, + 0xf9, 0xde, 0xb9, 0x1e, 0xd8, 0xbf, 0x95, 0xe2, 0xbf, 0xe0, 0x7b, 0xe7, 0x03, 0xfb, 0xb7, 0x96, + 0x3a, 0x14, 0x7b, 0x10, 0xc0, 0xc6, 0xa0, 0xd9, 0xe8, 0x36, 0x34, 0x65, 0x0d, 0x7f, 0xb7, 0xbf, + 0xe9, 0x0c, 0x86, 0x03, 0x25, 0xc3, 0x6a, 0x00, 0xbd, 0xfe, 0x50, 0x17, 0xe9, 0x75, 0xb6, 0x01, + 0xeb, 0x9d, 0x9e, 0x92, 0x45, 0x1a, 0x84, 0x77, 0x7a, 0x4a, 0x8e, 0x15, 0x20, 0xdb, 0xe8, 0x7d, + 0xab, 0xe4, 0xe9, 0x47, 0xb7, 0xab, 0x6c, 0xa8, 0xff, 0xef, 0x3a, 0x94, 0xfa, 0x27, 0xdf, 0x59, + 0xa3, 0x10, 0xfb, 0x8c, 0x5c, 0x6a, 0xf9, 0xaf, 0x2c, 0x9f, 0xba, 0x9d, 0xd5, 0x44, 0x0a, 0x3b, + 0x62, 0x9e, 0x50, 0xe7, 0xb2, 0xda, 0xba, 0x79, 0x42, 0x74, 0xa3, 0x53, 0x6b, 0x6a, 0x50, 0xe7, + 0x90, 0x8e, 0x52, 0xb8, 0x2a, 0xbc, 0x93, 0xef, 0xa8, 0x7b, 0x59, 0x0d, 0x7f, 0xb2, 0x3b, 0x50, + 0xe6, 0x65, 0x24, 0xf9, 0x0b, 0x38, 0x68, 0x91, 0xf9, 0x36, 0x92, 0xcc, 0x47, 0x39, 0xa9, 0x54, + 0x8e, 0x14, 0x7b, 0x1b, 0x07, 0xf5, 0x04, 0x47, 0x7b, 0x27, 0xdf, 0x71, 0x6c, 0x91, 0x73, 0xb4, + 0x77, 0xf2, 0x1d, 0xa1, 0xde, 0x87, 0xad, 0x60, 0x7e, 0x12, 0x8c, 0x7c, 0x7b, 0x16, 0xda, 0x9e, + 0xcb, 0x69, 0x4a, 0x44, 0xa3, 0x24, 0x11, 0x44, 0xfc, 0x10, 0x8a, 0xb3, 0xf9, 0x89, 0x6e, 0xbb, + 0x63, 0x8f, 0xc4, 0x7e, 0xf9, 0x49, 0x95, 0x4f, 0xcc, 0xd1, 0xfc, 0xa4, 0xe3, 0x8e, 0x3d, 0xad, + 0x30, 0xe3, 0x3f, 0x98, 0x0a, 0x55, 0xd7, 0x0b, 0x75, 0x54, 0x15, 0xf4, 0xa9, 0x15, 0x1a, 0xb4, + 0x1f, 0xf0, 0x0d, 0xbf, 0xeb, 0x8d, 0xce, 0x0e, 0xad, 0xd0, 0x60, 0x8f, 0xa0, 0x18, 0xb8, 0xc6, + 0x2c, 0x38, 0xf5, 0x42, 0xda, 0x18, 0xca, 0x4f, 0x6a, 0x82, 0x77, 0x04, 0x54, 0x8b, 0xf0, 0xea, + 0x03, 0x28, 0x88, 0x3a, 0x50, 0x4f, 0x08, 0x2d, 0xd7, 0x70, 0x43, 0x3d, 0x52, 0x30, 0x8a, 0x1c, + 0xd0, 0x31, 0xd5, 0x3f, 0xcf, 0x80, 0x32, 0x48, 0x34, 0x9b, 0x2a, 0x5a, 0x25, 0x65, 0xde, 0x06, + 0x30, 0x46, 0x23, 0x6f, 0xce, 0x8b, 0xe1, 0xcc, 0x58, 0x12, 0x90, 0x8e, 0x99, 0x1c, 0xeb, 0x6c, + 0x6a, 0xac, 0xef, 0x42, 0x45, 0xe6, 0x4b, 0x08, 0x88, 0xb2, 0x80, 0xc9, 0xd1, 0x0e, 0xe6, 0x29, + 0x29, 0x51, 0x08, 0xe6, 0x3c, 0xf7, 0x35, 0xd8, 0x20, 0x6d, 0x24, 0x90, 0x33, 0xc8, 0x53, 0xea, + 0x7f, 0x9f, 0x81, 0x6a, 0xc7, 0x35, 0xad, 0x8b, 0xc1, 0xc8, 0x70, 0xe5, 0x00, 0xda, 0x81, 0x6e, + 0x23, 0x4c, 0x0f, 0x46, 0x86, 0x2b, 0x14, 0x89, 0xb2, 0x1d, 0x44, 0x74, 0xd8, 0x07, 0x4e, 0x40, + 0x55, 0xad, 0x53, 0x89, 0x25, 0x82, 0x50, 0x65, 0x0f, 0x60, 0xf3, 0xc4, 0x72, 0x3c, 0x77, 0xa2, + 0x87, 0x9e, 0xce, 0x35, 0x22, 0xde, 0x97, 0x2a, 0x07, 0x0f, 0xbd, 0x21, 0x69, 0x46, 0xdb, 0x90, + 0x9f, 0x19, 0x7e, 0x18, 0xd4, 0x73, 0x3b, 0x59, 0x5c, 0xf2, 0x94, 0xc0, 0x61, 0xb6, 0x03, 0x7d, + 0xee, 0xda, 0xdf, 0xcf, 0x79, 0x37, 0x8a, 0x5a, 0xd1, 0x0e, 0x8e, 0x29, 0xcd, 0x1e, 0x82, 0xc2, + 0x6b, 0xa6, 0x62, 0x93, 0x3c, 0x59, 0x23, 0x38, 0x15, 0x4c, 0x82, 0xf1, 0x7f, 0x5f, 0x87, 0xe2, + 0xde, 0xdc, 0x1d, 0xe1, 0x64, 0xb0, 0x7b, 0x90, 0x1b, 0xcf, 0xdd, 0x11, 0xf5, 0x25, 0xda, 0x76, + 0xa3, 0x35, 0xa5, 0x11, 0x12, 0xa5, 0x95, 0xe1, 0x4f, 0x50, 0xca, 0x2d, 0x49, 0x2b, 0x84, 0xd3, + 0xcc, 0x4d, 0x26, 0xfa, 0xc8, 0x73, 0xc7, 0xf6, 0x84, 0x7a, 0x54, 0xd1, 0x4a, 0xc6, 0x64, 0xd2, + 0x24, 0x00, 0x6b, 0xc0, 0x66, 0x8c, 0xe6, 0x8a, 0x5a, 0x8e, 0x04, 0xd3, 0x0d, 0x5e, 0x52, 0x63, + 0x32, 0xf1, 0xad, 0x89, 0x11, 0x5a, 0x9c, 0x9e, 0x64, 0x53, 0x35, 0xca, 0x4e, 0xf2, 0xed, 0xef, + 0x65, 0x78, 0x9b, 0xf7, 0x1c, 0x63, 0xc2, 0x8a, 0x90, 0xeb, 0xf5, 0x7b, 0x6d, 0x65, 0x8d, 0x55, + 0xa0, 0xd8, 0xe9, 0x0d, 0xdb, 0x5a, 0xaf, 0xd1, 0x55, 0x32, 0x24, 0x5c, 0x86, 0x8d, 0xdd, 0x6e, + 0x5b, 0x59, 0x47, 0xcc, 0x8b, 0x7e, 0xb7, 0x31, 0xec, 0x74, 0xdb, 0x4a, 0x8e, 0x63, 0xb4, 0x4e, + 0x73, 0xa8, 0x14, 0x99, 0x02, 0x95, 0x23, 0xad, 0xdf, 0x3a, 0x6e, 0xb6, 0xf5, 0xde, 0x71, 0xb7, + 0xab, 0x28, 0xec, 0x0a, 0x6c, 0x46, 0x90, 0x3e, 0x07, 0xee, 0x60, 0x96, 0x17, 0x0d, 0xad, 0xa1, + 0xed, 0x2b, 0xbf, 0x62, 0x45, 0xc8, 0x36, 0xf6, 0xf7, 0x95, 0xdf, 0xa1, 0x9c, 0x2a, 0xbd, 0xec, + 0xf4, 0xf4, 0x17, 0x8d, 0xee, 0x71, 0x5b, 0xf9, 0xdd, 0xba, 0x4c, 0xf7, 0xb5, 0x56, 0x5b, 0x53, + 0x7e, 0x97, 0x63, 0x5b, 0x50, 0xf9, 0x4d, 0xbf, 0xd7, 0x3e, 0x6c, 0x1c, 0x1d, 0x51, 0x43, 0x7e, + 0x57, 0x54, 0xff, 0x71, 0x0e, 0x72, 0x38, 0x56, 0x4c, 0x8d, 0x65, 0x72, 0x34, 0x88, 0xd8, 0xb9, + 0xdd, 0xdc, 0x3f, 0xf8, 0x47, 0x77, 0xd6, 0xb8, 0x34, 0xbe, 0x0b, 0x59, 0xc7, 0x0e, 0x89, 0x71, + 0xa2, 0x95, 0x2c, 0x34, 0xd8, 0x83, 0x35, 0x0d, 0x71, 0xec, 0x36, 0x64, 0xb8, 0x58, 0x8e, 0x16, + 0xa7, 0xdc, 0xd7, 0x0f, 0xd6, 0xb4, 0xcc, 0x8c, 0xdd, 0x82, 0xcc, 0x2b, 0x21, 0xa3, 0x2b, 0x1c, + 0xcf, 0x77, 0x76, 0xc4, 0xbe, 0x62, 0x3b, 0x90, 0x1d, 0x79, 0x5c, 0x3f, 0x8d, 0xf0, 0x7c, 0x9f, + 0xc3, 0xf2, 0x47, 0x9e, 0xc3, 0xee, 0x41, 0xd6, 0x37, 0xce, 0x89, 0x77, 0x22, 0x86, 0x88, 0x36, + 0x52, 0x24, 0xf2, 0x8d, 0x73, 0x6c, 0xc4, 0x98, 0xa4, 0x5a, 0xd4, 0x08, 0xc9, 0x51, 0x58, 0xcd, + 0x98, 0xed, 0x40, 0xe6, 0x9c, 0xe4, 0x5a, 0xa4, 0x92, 0xbd, 0xb4, 0x5d, 0xd3, 0x3b, 0x1f, 0xcc, + 0xac, 0x11, 0x52, 0x9c, 0xb3, 0x77, 0x20, 0x1b, 0xcc, 0x4f, 0x48, 0xae, 0x95, 0x9f, 0x6c, 0x2d, + 0xed, 0x50, 0x58, 0x51, 0x30, 0x3f, 0x61, 0x0f, 0x20, 0x37, 0xf2, 0x7c, 0x5f, 0xc8, 0x36, 0x45, + 0x36, 0x58, 0x6e, 0xce, 0xa8, 0xa2, 0x22, 0x1e, 0x2b, 0x0c, 0x49, 0xa2, 0x45, 0x44, 0xf1, 0xee, + 0x88, 0x15, 0x86, 0xec, 0xbe, 0xd8, 0x72, 0x53, 0x72, 0x4d, 0x6e, 0xc8, 0x58, 0x0e, 0x62, 0x71, + 0x92, 0xa6, 0xc6, 0x05, 0xe9, 0xbf, 0x11, 0x91, 0xdc, 0x89, 0xb1, 0x4d, 0x53, 0xe3, 0x82, 0xdd, + 0x87, 0xec, 0x2b, 0x6b, 0x44, 0xaa, 0x70, 0x54, 0x9b, 0x98, 0xa4, 0x17, 0xd4, 0x3d, 0x44, 0xd3, + 0xca, 0xf2, 0x1c, 0x93, 0xb4, 0xe2, 0x68, 0x2e, 0xf7, 0x3c, 0xc7, 0x7c, 0x41, 0x73, 0x49, 0x48, + 0x54, 0x40, 0x8c, 0xf9, 0x05, 0xca, 0x3b, 0x85, 0xab, 0x0a, 0xc6, 0xfc, 0xa2, 0x63, 0xe2, 0x56, + 0xe4, 0x9a, 0xaf, 0x48, 0x17, 0xce, 0x68, 0xf8, 0x13, 0x0f, 0x6b, 0x81, 0xe5, 0x58, 0xa3, 0xd0, + 0x7e, 0x65, 0x87, 0x97, 0xa4, 0xed, 0x66, 0xb4, 0x24, 0x68, 0x77, 0x03, 0x72, 0xd6, 0xc5, 0xcc, + 0x57, 0x0f, 0xa0, 0x20, 0x6a, 0x59, 0x3a, 0xf1, 0xdd, 0x80, 0xa2, 0x1d, 0xe0, 0x3a, 0x0c, 0x42, + 0xa1, 0xc9, 0x15, 0xec, 0xa0, 0x89, 0x49, 0x14, 0xc8, 0xa6, 0x11, 0x1a, 0x62, 0xf1, 0xd2, 0x6f, + 0xf5, 0x09, 0x40, 0xdc, 0x2d, 0x6c, 0x93, 0x63, 0xb9, 0x52, 0x69, 0x74, 0x2c, 0x37, 0xca, 0xb3, + 0x9e, 0xc8, 0x73, 0x03, 0x4a, 0x91, 0x9e, 0xce, 0x2a, 0x90, 0x31, 0xc4, 0x66, 0x9c, 0x31, 0xd4, + 0x87, 0xa8, 0x36, 0x4b, 0x4d, 0x3c, 0x8d, 0xc3, 0x94, 0xdc, 0xa2, 0x33, 0x27, 0xea, 0x2f, 0xa1, + 0xa2, 0x59, 0xc1, 0xdc, 0x09, 0x9b, 0x9e, 0xd3, 0xb2, 0xc6, 0xec, 0x03, 0x80, 0x28, 0x1d, 0x08, + 0x9d, 0x29, 0xe6, 0xdd, 0x96, 0x35, 0xd6, 0x12, 0x78, 0xf5, 0x7f, 0xcd, 0x91, 0xf6, 0xd9, 0xe2, + 0x6a, 0x9f, 0xd0, 0xef, 0x32, 0x09, 0xfd, 0x2e, 0xda, 0x7d, 0xd6, 0xd3, 0x3a, 0xee, 0xa9, 0x6d, + 0x9a, 0x96, 0x2b, 0x75, 0x59, 0x9e, 0xc2, 0xc9, 0x36, 0x9c, 0x89, 0x10, 0x58, 0x4c, 0x56, 0x3a, + 0x9d, 0xf9, 0x56, 0x10, 0x70, 0x2d, 0xca, 0x70, 0x26, 0x72, 0x6d, 0xe7, 0x7f, 0x68, 0x6d, 0xdf, + 0x80, 0x22, 0x6e, 0xc0, 0x74, 0x06, 0xdd, 0xe0, 0xa3, 0x2f, 0x0e, 0xdb, 0xec, 0x5d, 0x28, 0x88, + 0xd3, 0x83, 0x58, 0x54, 0x82, 0x5d, 0x5a, 0x1c, 0xa8, 0x49, 0x2c, 0xab, 0xa3, 0xca, 0x39, 0x9d, + 0x5a, 0x6e, 0x28, 0xb5, 0x06, 0x91, 0x64, 0xef, 0x43, 0xc9, 0x73, 0x75, 0x7e, 0xc4, 0x10, 0xab, + 0x4a, 0xb0, 0x6f, 0xdf, 0x3d, 0x26, 0xa8, 0x56, 0xf4, 0xc4, 0x2f, 0x6c, 0x8a, 0xe3, 0x9d, 0xeb, + 0x23, 0xc3, 0x37, 0x69, 0x65, 0x15, 0xb5, 0x82, 0xe3, 0x9d, 0x37, 0x0d, 0xdf, 0xe4, 0x5a, 0xd4, + 0xf7, 0xee, 0x7c, 0x4a, 0xab, 0xa9, 0xaa, 0x89, 0x14, 0xbb, 0x05, 0xa5, 0x91, 0x33, 0x0f, 0x42, + 0xcb, 0xdf, 0xbd, 0xe4, 0x87, 0x46, 0x2d, 0x06, 0x60, 0xbb, 0x66, 0xbe, 0x3d, 0x35, 0xfc, 0x4b, + 0x5a, 0x3a, 0x45, 0x4d, 0x26, 0x69, 0x2b, 0x3b, 0xb3, 0xcd, 0x0b, 0x7e, 0x72, 0xd4, 0x78, 0x02, + 0xe9, 0x4f, 0xe9, 0x5c, 0x1f, 0xd0, 0xfa, 0x28, 0x6a, 0x32, 0x49, 0xf3, 0x40, 0x3f, 0x69, 0x45, + 0x94, 0x34, 0x91, 0x4a, 0x1d, 0x01, 0xb6, 0x5e, 0x7b, 0x04, 0x60, 0x8b, 0x5a, 0x98, 0xe7, 0xdb, + 0x13, 0x5b, 0xe8, 0x50, 0x57, 0xb8, 0x16, 0xc6, 0x41, 0x44, 0xf0, 0x05, 0x54, 0x27, 0x96, 0x6b, + 0xf9, 0x46, 0x68, 0x99, 0x3a, 0xca, 0xc5, 0x6d, 0x1a, 0x38, 0x31, 0xcd, 0xfb, 0x12, 0x85, 0xb2, + 0xa6, 0x32, 0x49, 0xa4, 0xd4, 0xef, 0xa1, 0x20, 0xe6, 0x06, 0x37, 0x47, 0x5c, 0x77, 0x69, 0xb9, + 0xce, 0x37, 0x47, 0x84, 0xb3, 0x7b, 0x50, 0x15, 0x8d, 0x08, 0x42, 0xdf, 0x76, 0x27, 0x82, 0xeb, + 0x2a, 0x1c, 0x38, 0x20, 0x18, 0xea, 0x30, 0xc8, 0x17, 0xba, 0x71, 0x62, 0x3b, 0xb8, 0xbe, 0xb3, + 0x42, 0x37, 0x9b, 0x3b, 0x4e, 0x83, 0x83, 0xd4, 0x3e, 0x14, 0xe5, 0x4c, 0xfe, 0x41, 0xea, 0x54, + 0x67, 0x50, 0x49, 0xf6, 0xf0, 0x0f, 0xd3, 0x11, 0xae, 0xa3, 0x04, 0xa1, 0xe7, 0x5b, 0xa6, 0x34, + 0x19, 0xd9, 0xc1, 0x80, 0xd2, 0xea, 0x9f, 0x66, 0xa0, 0x4c, 0xba, 0x52, 0x9f, 0x34, 0x41, 0xf6, + 0x01, 0xb0, 0x91, 0x6f, 0x19, 0xa1, 0xa5, 0x5b, 0x17, 0xa1, 0x6f, 0x08, 0x8d, 0x88, 0xab, 0x55, + 0x0a, 0xc7, 0xb4, 0x11, 0xc1, 0x95, 0xa2, 0x3b, 0x50, 0x9e, 0x19, 0x7e, 0x20, 0xb5, 0x71, 0x5e, + 0x3b, 0x70, 0x90, 0xd0, 0x85, 0x15, 0x77, 0xe2, 0x1b, 0x53, 0x3d, 0xf4, 0xce, 0x2c, 0x97, 0x9f, + 0x43, 0xf8, 0x09, 0xac, 0x46, 0xf0, 0x21, 0x82, 0xe9, 0x38, 0xf2, 0x3f, 0x66, 0xa0, 0x7a, 0xc4, + 0x19, 0xf4, 0xb9, 0x75, 0xd9, 0xe2, 0xc7, 0xde, 0x91, 0x14, 0x2e, 0x39, 0x8d, 0x7e, 0xb3, 0xdb, + 0x50, 0x9e, 0x9d, 0x59, 0x97, 0x7a, 0xea, 0x88, 0x58, 0x42, 0x50, 0x93, 0xc4, 0xc8, 0x7b, 0xb0, + 0xe1, 0x51, 0x47, 0xc4, 0x76, 0x2c, 0x76, 0xb1, 0x44, 0x0f, 0x35, 0x41, 0x80, 0xba, 0x63, 0x54, + 0x54, 0x52, 0x49, 0x15, 0x85, 0x51, 0xf3, 0xb7, 0x21, 0x8f, 0xa8, 0xa0, 0x9e, 0xe7, 0x4a, 0x1f, + 0x25, 0xd8, 0xc7, 0x50, 0x1d, 0x79, 0xd3, 0x99, 0x2e, 0xb3, 0x8b, 0x8d, 0x39, 0x2d, 0xfe, 0xca, + 0x48, 0x72, 0xc4, 0xcb, 0x52, 0xff, 0x32, 0x0b, 0x45, 0x6a, 0x83, 0x90, 0x80, 0xb6, 0x79, 0x21, + 0x25, 0x60, 0x49, 0xcb, 0xdb, 0x26, 0x6e, 0x30, 0x6f, 0xd0, 0x53, 0x23, 0xfd, 0x33, 0x9b, 0xd4, + 0x3f, 0xaf, 0xc1, 0x86, 0x50, 0x3e, 0x73, 0x5c, 0x44, 0xce, 0x5f, 0xaf, 0x7a, 0xe6, 0x57, 0xa9, + 0x9e, 0x38, 0x85, 0x9c, 0xc6, 0xba, 0xc0, 0xad, 0x98, 0x4b, 0x41, 0x20, 0x50, 0x1b, 0x21, 0x49, + 0xf9, 0x56, 0x48, 0xcb, 0xb7, 0x3a, 0x14, 0x5e, 0xd9, 0x81, 0x8d, 0x0c, 0x52, 0xe4, 0x12, 0x43, + 0x24, 0x13, 0xd3, 0x50, 0x7a, 0xd3, 0x34, 0x44, 0xdd, 0x36, 0x9c, 0x09, 0x3f, 0x2f, 0xc9, 0x6e, + 0x37, 0x9c, 0x89, 0xc7, 0x3e, 0x81, 0xab, 0x31, 0x5a, 0xf4, 0x86, 0xd4, 0x55, 0x32, 0x9d, 0x69, + 0x2c, 0xa2, 0xa4, 0x1e, 0xd1, 0x81, 0xf6, 0x11, 0x6c, 0x25, 0xb2, 0xcc, 0x50, 0x13, 0x0b, 0x48, + 0x3c, 0x96, 0xb4, 0xcd, 0x88, 0x9c, 0x14, 0xb4, 0x80, 0xbd, 0x87, 0xe3, 0x34, 0x72, 0xe6, 0x26, + 0x17, 0x36, 0xf3, 0xa9, 0x1b, 0xd4, 0xab, 0x34, 0xc0, 0x9b, 0x12, 0xde, 0xe4, 0x60, 0xf5, 0x3f, + 0x5b, 0x87, 0xea, 0x9e, 0xe7, 0x5b, 0xf6, 0xc4, 0x8d, 0x19, 0x74, 0xe9, 0xc4, 0x24, 0x99, 0x76, + 0x3d, 0xc1, 0xb4, 0x77, 0xa0, 0x3c, 0xe6, 0x19, 0xf5, 0xf0, 0x84, 0x1b, 0x66, 0x72, 0x1a, 0x08, + 0xd0, 0xf0, 0xc4, 0x41, 0x51, 0x23, 0x09, 0x28, 0x73, 0x8e, 0x32, 0xcb, 0x4c, 0xb8, 0x83, 0xb2, + 0x5f, 0xd0, 0x5e, 0x62, 0x5a, 0x8e, 0x15, 0xf2, 0x99, 0xac, 0x3d, 0x79, 0x5b, 0xea, 0x2f, 0x89, + 0x36, 0x3d, 0xd6, 0xac, 0x71, 0x83, 0x94, 0x3e, 0xdc, 0x5a, 0x5a, 0x44, 0x2e, 0xf2, 0x8a, 0x7d, + 0x68, 0xe3, 0x47, 0xe6, 0xe5, 0x62, 0x4d, 0x1d, 0x42, 0x29, 0x02, 0xa3, 0x06, 0xaf, 0xb5, 0x85, + 0xd6, 0xbe, 0xc6, 0xca, 0x50, 0x68, 0x36, 0x06, 0xcd, 0x46, 0xab, 0xad, 0x64, 0x10, 0x35, 0x68, + 0x0f, 0xb9, 0xa6, 0xbe, 0xce, 0x36, 0xa1, 0x8c, 0xa9, 0x56, 0x7b, 0xaf, 0x71, 0xdc, 0x1d, 0x2a, + 0x59, 0x56, 0x85, 0x52, 0xaf, 0xaf, 0x37, 0x9a, 0xc3, 0x4e, 0xbf, 0xa7, 0xe4, 0x54, 0x1d, 0x8a, + 0xcd, 0x53, 0x6b, 0x74, 0xf6, 0xba, 0x51, 0x24, 0xc3, 0x86, 0x35, 0x3a, 0x13, 0x5a, 0xf7, 0x82, + 0x61, 0xc3, 0x1a, 0x9d, 0x21, 0xdb, 0x48, 0xc9, 0xf7, 0xbd, 0x23, 0x4e, 0x6c, 0x25, 0x21, 0xf6, + 0xbe, 0x77, 0xd4, 0x36, 0x94, 0x8e, 0x0c, 0x3f, 0xb4, 0xa9, 0xd9, 0xcf, 0xa0, 0x1a, 0x25, 0x5a, + 0xd6, 0x58, 0xaa, 0x2b, 0x2c, 0x52, 0xd5, 0x23, 0x94, 0x96, 0x26, 0x54, 0x3f, 0x80, 0x4a, 0x12, + 0xc0, 0x6e, 0x41, 0xd6, 0xb4, 0xc6, 0x2b, 0xc4, 0x31, 0x82, 0xd5, 0x17, 0x50, 0x69, 0xca, 0xed, + 0xf7, 0x75, 0x3d, 0x7b, 0x02, 0x35, 0x92, 0x1d, 0xa3, 0x13, 0x29, 0x3c, 0xd6, 0x57, 0x08, 0x8f, + 0x0a, 0xd2, 0x34, 0x4f, 0x84, 0xf4, 0xf8, 0x0c, 0xca, 0x47, 0xbe, 0x37, 0xb3, 0xfc, 0x90, 0x8a, + 0x55, 0x20, 0x7b, 0x66, 0x5d, 0x8a, 0x52, 0xf1, 0x67, 0x6c, 0x8e, 0x5a, 0x4f, 0x9a, 0xa3, 0x9e, + 0x40, 0x51, 0x66, 0xfb, 0xd1, 0x79, 0xbe, 0x42, 0x21, 0x4c, 0x79, 0x6c, 0x2b, 0xc0, 0xca, 0x1e, + 0x03, 0xcc, 0x22, 0x80, 0x18, 0x38, 0x79, 0xc6, 0x11, 0x85, 0x6b, 0x09, 0x0a, 0xf5, 0x6d, 0x28, + 0xbc, 0xb0, 0xad, 0x73, 0xd1, 0xfd, 0x57, 0xb6, 0x75, 0x2e, 0xbb, 0x8f, 0xbf, 0xd5, 0xff, 0xa7, + 0x04, 0x45, 0x5a, 0xa9, 0xad, 0xd7, 0x5b, 0x00, 0x7f, 0x8a, 0x2a, 0xb8, 0x23, 0x96, 0x5b, 0x6e, + 0x85, 0x02, 0xca, 0x17, 0xdf, 0xdb, 0x00, 0x09, 0xa9, 0xc1, 0x65, 0x60, 0x29, 0x8c, 0x84, 0x05, + 0xea, 0x50, 0xb4, 0xab, 0x21, 0x1b, 0xf1, 0xc3, 0x79, 0x0c, 0x60, 0x8f, 0xb9, 0x86, 0x43, 0xc7, + 0x71, 0xae, 0x05, 0x5e, 0x91, 0x27, 0x99, 0x13, 0xc7, 0x92, 0xe7, 0x2b, 0x52, 0x7b, 0x30, 0x41, + 0x12, 0xd1, 0xf2, 0x03, 0x14, 0x7c, 0x74, 0x45, 0xa0, 0xc9, 0x24, 0x7b, 0x17, 0x72, 0xb8, 0x5d, + 0x88, 0xf3, 0xd0, 0x15, 0x39, 0x82, 0x89, 0xfd, 0x4e, 0x23, 0x02, 0xf6, 0x10, 0x0a, 0x24, 0xa4, + 0x2c, 0x94, 0x59, 0x89, 0xd1, 0x96, 0xdb, 0x87, 0x26, 0xd1, 0xec, 0x3d, 0xc8, 0x8f, 0xcf, 0xac, + 0x4b, 0x2e, 0xb0, 0xa2, 0x32, 0x53, 0x4b, 0x5a, 0xe3, 0x14, 0xec, 0x3e, 0xd4, 0x7c, 0x6b, 0xac, + 0x93, 0x4d, 0x10, 0x65, 0x50, 0x50, 0xaf, 0x91, 0x88, 0xa9, 0xf8, 0xd6, 0xb8, 0x89, 0xc0, 0xe1, + 0x89, 0x13, 0xb0, 0x07, 0xb0, 0x41, 0x8b, 0x0b, 0x15, 0xc0, 0x44, 0xcd, 0x72, 0xa5, 0x6a, 0x02, + 0xcb, 0x3e, 0x01, 0x10, 0x6a, 0xa6, 0x7e, 0x72, 0x49, 0xb6, 0xf4, 0x68, 0x31, 0x25, 0xf9, 0x3f, + 0xa9, 0x8c, 0xbe, 0x0b, 0x79, 0x64, 0x92, 0xa0, 0x7e, 0x9d, 0x4a, 0xde, 0x4a, 0x73, 0x10, 0xb5, + 0x94, 0xf0, 0xec, 0x21, 0x14, 0x91, 0x51, 0x68, 0x55, 0xd7, 0x93, 0x7a, 0xb7, 0xe0, 0x2a, 0xdc, + 0x63, 0xac, 0xf3, 0xc1, 0xf7, 0x0e, 0x7b, 0x04, 0x39, 0x13, 0x17, 0xf3, 0x0d, 0x2a, 0xf1, 0x5a, + 0x62, 0x5e, 0x50, 0x96, 0xb5, 0xac, 0x31, 0x1d, 0x05, 0x88, 0x86, 0x1d, 0x40, 0x0d, 0xd9, 0xe8, + 0x09, 0xa9, 0x0d, 0x38, 0x7c, 0xf5, 0x9b, 0x94, 0xeb, 0xee, 0x42, 0xae, 0x9e, 0x20, 0xa2, 0xc1, + 0x6e, 0xbb, 0xa1, 0x7f, 0xa9, 0x55, 0xdd, 0x24, 0x8c, 0xdd, 0xc4, 0xf3, 0x5a, 0xd7, 0x1b, 0x9d, + 0x59, 0x66, 0xfd, 0x2d, 0xa9, 0x4b, 0xf1, 0x34, 0xfb, 0x12, 0xaa, 0xc4, 0x58, 0x98, 0xc4, 0xca, + 0xeb, 0xb7, 0x48, 0xd6, 0x26, 0x59, 0x46, 0xa2, 0xb4, 0x34, 0x25, 0xee, 0x00, 0x76, 0xa0, 0x87, + 0xd6, 0x74, 0xe6, 0xf9, 0xa8, 0xb1, 0xbf, 0x2d, 0xed, 0x58, 0x43, 0x09, 0xc2, 0x2d, 0x3d, 0xba, + 0xf9, 0xd3, 0xbd, 0xf1, 0x38, 0xb0, 0xc2, 0xfa, 0x6d, 0x5a, 0x37, 0x35, 0x79, 0x01, 0xd8, 0x27, + 0x28, 0x6d, 0xa9, 0x81, 0x6e, 0x5e, 0xba, 0xc6, 0xd4, 0x1e, 0xd5, 0xef, 0xf0, 0x83, 0x81, 0x1d, + 0xb4, 0x38, 0x20, 0xa9, 0x9b, 0xef, 0xa4, 0x74, 0xf3, 0x2b, 0x90, 0x37, 0x4f, 0x70, 0x39, 0xde, + 0xa5, 0x62, 0x73, 0xe6, 0x49, 0xc7, 0x64, 0x1f, 0x42, 0x69, 0x26, 0x45, 0x60, 0x5d, 0x4d, 0x5a, + 0x20, 0x22, 0xc9, 0xa8, 0xc5, 0x14, 0x78, 0x28, 0xde, 0xb3, 0x8c, 0x70, 0xee, 0x5b, 0x7b, 0x8e, + 0x31, 0xa9, 0xdf, 0xa3, 0x92, 0x92, 0x20, 0x6c, 0x9d, 0xe3, 0x4d, 0xec, 0x91, 0x41, 0x2b, 0xff, + 0x3e, 0xd7, 0xe0, 0x04, 0xa4, 0x63, 0xc6, 0x2a, 0xad, 0x21, 0xd4, 0xb2, 0x77, 0x92, 0x2a, 0xad, + 0xe1, 0x48, 0xa3, 0x5d, 0x3c, 0x16, 0xd6, 0xcc, 0x1b, 0x9d, 0xd6, 0x1f, 0xd0, 0x7a, 0xab, 0xca, + 0xa1, 0x68, 0x23, 0xf0, 0xe6, 0x3e, 0x9d, 0x09, 0x68, 0x84, 0x3f, 0x5b, 0x10, 0x64, 0xa9, 0x65, + 0x98, 0x90, 0x78, 0x07, 0x6b, 0x49, 0x79, 0xb6, 0x9b, 0x27, 0x89, 0x7f, 0xf3, 0x57, 0xc0, 0x96, + 0x79, 0xe3, 0x4d, 0x52, 0x35, 0x2f, 0xa4, 0xea, 0x2f, 0xd6, 0x9f, 0x65, 0xd4, 0xff, 0x2e, 0x03, + 0xd5, 0x94, 0xd4, 0x58, 0xb9, 0x3d, 0x70, 0x2d, 0xcf, 0x98, 0x8a, 0x03, 0x3c, 0x4f, 0x48, 0x0d, + 0xde, 0x76, 0x27, 0xc2, 0x3a, 0xc9, 0x35, 0x78, 0x4a, 0xb3, 0xaf, 0xe0, 0xca, 0x78, 0xee, 0x38, + 0xa1, 0x75, 0x11, 0xea, 0x81, 0x37, 0xf7, 0x47, 0x96, 0xee, 0x5b, 0x63, 0x61, 0x6e, 0x5a, 0xb2, + 0x1e, 0x6e, 0x49, 0xda, 0x01, 0x91, 0x6a, 0xd6, 0x98, 0xfd, 0x31, 0xb0, 0xa8, 0x00, 0xae, 0x38, + 0x61, 0xfe, 0xfc, 0xea, 0xfc, 0x8a, 0x24, 0xa5, 0x61, 0xd0, 0xac, 0xb1, 0xfa, 0x5f, 0x65, 0xa1, + 0x72, 0x60, 0x04, 0xa7, 0x87, 0xc6, 0x6c, 0x10, 0x1a, 0x61, 0x80, 0xbc, 0x7c, 0x6a, 0x04, 0xa7, + 0x53, 0x63, 0xc6, 0xf5, 0xfd, 0x0c, 0x37, 0x8c, 0x08, 0x18, 0x2a, 0xfb, 0xb8, 0x8a, 0x30, 0xd9, + 0x77, 0x8f, 0x9e, 0x0b, 0xab, 0x47, 0x94, 0x46, 0x19, 0x1a, 0x9c, 0xce, 0xc7, 0xe3, 0xa8, 0xab, + 0x32, 0xc9, 0xee, 0x43, 0x55, 0xfc, 0x24, 0x65, 0xff, 0x42, 0x5c, 0x73, 0xa7, 0x81, 0xec, 0x29, + 0x94, 0x05, 0x60, 0x28, 0x25, 0x7e, 0x2d, 0xb2, 0x66, 0xc5, 0x08, 0x2d, 0x49, 0xc5, 0x7e, 0x0d, + 0x57, 0x13, 0xc9, 0x3d, 0xcf, 0x3f, 0x9c, 0x3b, 0xa1, 0xdd, 0xec, 0x09, 0x75, 0xe9, 0xad, 0xa5, + 0xec, 0x31, 0x89, 0xb6, 0x3a, 0x67, 0xba, 0xb5, 0x87, 0xb6, 0x4b, 0x1b, 0x48, 0x56, 0x4b, 0x03, + 0x17, 0xa8, 0x8c, 0x0b, 0xda, 0x37, 0xd2, 0x54, 0xc6, 0x05, 0x4a, 0x16, 0x01, 0x38, 0xb4, 0xc2, + 0x53, 0xcf, 0x24, 0xb5, 0x3a, 0x92, 0x2c, 0x83, 0x24, 0x4a, 0x4b, 0x53, 0xe2, 0x70, 0xe2, 0x91, + 0x75, 0xe4, 0x86, 0xa4, 0x5c, 0x67, 0x35, 0x99, 0xc4, 0x3d, 0xd5, 0x37, 0xdc, 0x89, 0x15, 0xd4, + 0xcb, 0x3b, 0xd9, 0x87, 0x19, 0x4d, 0xa4, 0xd4, 0x7f, 0x63, 0x1d, 0xf2, 0x7c, 0x26, 0xdf, 0x82, + 0xd2, 0x09, 0x5d, 0x4e, 0xb8, 0xf3, 0xa9, 0xbc, 0x44, 0x20, 0x40, 0x6f, 0x3e, 0xe5, 0x9a, 0xae, + 0xb0, 0x5a, 0x65, 0x34, 0xfa, 0x8d, 0x45, 0x7a, 0xf3, 0x10, 0xeb, 0xca, 0x12, 0x54, 0xa4, 0xb0, + 0x11, 0xbe, 0x77, 0x4e, 0xdc, 0x90, 0x23, 0x84, 0x4c, 0xd2, 0x3d, 0x05, 0x6d, 0xcf, 0x98, 0x29, + 0x4f, 0xb8, 0x22, 0x01, 0x9a, 0x6e, 0xb8, 0x68, 0x61, 0xdb, 0x58, 0xb2, 0xb0, 0xb1, 0xdb, 0x80, + 0x7a, 0xf4, 0xc8, 0xea, 0xbb, 0x56, 0xb3, 0x47, 0x23, 0x5c, 0xd4, 0x12, 0x10, 0x5c, 0xa1, 0xa6, + 0x37, 0xa3, 0x41, 0xcd, 0x6b, 0xf8, 0x93, 0x7d, 0x1e, 0x71, 0x27, 0xf5, 0x51, 0x1c, 0x50, 0xc4, + 0xf6, 0x95, 0xe4, 0x63, 0x2d, 0x45, 0x87, 0x25, 0xe1, 0x9e, 0xc4, 0x0f, 0x28, 0xf8, 0x53, 0x6d, + 0x03, 0x68, 0xde, 0x79, 0x60, 0x85, 0x64, 0x4a, 0xbe, 0x4e, 0x5d, 0x4c, 0x5d, 0x49, 0x7a, 0xe7, + 0x47, 0x5e, 0x10, 0x9d, 0xe1, 0xd7, 0x57, 0x9f, 0xe1, 0xd5, 0x8f, 0xa0, 0x80, 0x0a, 0x8b, 0x11, + 0x1a, 0xec, 0xbe, 0xb0, 0xde, 0x71, 0x35, 0x4b, 0x98, 0x31, 0xe3, 0x3a, 0x84, 0x3d, 0xaf, 0x2b, + 0xeb, 0xa5, 0x3c, 0x77, 0x13, 0xa7, 0xe4, 0x68, 0xb3, 0x14, 0x05, 0x0a, 0x15, 0xe8, 0x2d, 0x28, + 0x61, 0xd3, 0xe8, 0xee, 0x45, 0x08, 0xa6, 0xa2, 0xef, 0x9d, 0x37, 0x31, 0xad, 0xfe, 0x4f, 0x19, + 0x28, 0xf7, 0x7d, 0x13, 0x77, 0xe9, 0xc1, 0xcc, 0x1a, 0xbd, 0xd1, 0xe4, 0x80, 0x0a, 0x93, 0xe7, + 0x38, 0x06, 0xed, 0x07, 0xe2, 0x94, 0x1a, 0x01, 0xd8, 0x27, 0x90, 0x1b, 0xa3, 0xdc, 0xcf, 0x26, + 0x4f, 0x19, 0x89, 0xe2, 0xe5, 0x6f, 0xdc, 0x09, 0x34, 0x22, 0x55, 0xff, 0x66, 0x54, 0x3f, 0x6d, + 0x0f, 0xc9, 0xfb, 0x83, 0x35, 0xba, 0x57, 0x1c, 0x34, 0x95, 0x0c, 0x2b, 0x42, 0xae, 0xd5, 0x1e, + 0x34, 0xf9, 0xd9, 0x02, 0x4f, 0x19, 0x03, 0x7d, 0xaf, 0xa3, 0x0d, 0x86, 0x4a, 0x8e, 0x2e, 0x2a, + 0x09, 0xd0, 0x6d, 0x0c, 0x86, 0x4a, 0x91, 0x01, 0x6c, 0x1c, 0xf7, 0x3a, 0xbf, 0x3e, 0x6e, 0x2b, + 0x8a, 0xfa, 0x0f, 0x33, 0x00, 0xb1, 0x99, 0x9b, 0xbd, 0x0f, 0xe5, 0x73, 0x4a, 0xe9, 0x89, 0x1b, + 0x96, 0x64, 0x1f, 0x81, 0xa3, 0x49, 0x99, 0xfb, 0x10, 0x2a, 0xd1, 0xbe, 0x86, 0x8a, 0xce, 0xf2, + 0x55, 0x4b, 0x39, 0xc2, 0xef, 0x5e, 0xb2, 0x0f, 0xa0, 0xe8, 0x61, 0x3f, 0x90, 0x34, 0x9b, 0xd4, + 0x72, 0x12, 0xdd, 0xd7, 0x0a, 0x1e, 0x4f, 0xa0, 0x42, 0x34, 0xf6, 0xa5, 0xd5, 0x21, 0x22, 0xdd, + 0x43, 0x50, 0xd3, 0x31, 0xe6, 0x81, 0xa5, 0x71, 0x7c, 0xb4, 0x4b, 0xe4, 0xe3, 0x5d, 0x42, 0xfd, + 0x0d, 0xd4, 0x06, 0xc6, 0x74, 0xc6, 0xf7, 0x12, 0xea, 0x18, 0x83, 0x1c, 0xf2, 0x84, 0x60, 0x3d, + 0xfa, 0x8d, 0x8b, 0xee, 0xc8, 0xf2, 0x47, 0x96, 0x2b, 0xd7, 0xa8, 0x4c, 0xa2, 0xf8, 0x3d, 0xc6, + 0xdd, 0x44, 0xf3, 0xce, 0xe5, 0x76, 0x22, 0xd3, 0xea, 0xbf, 0x9d, 0x81, 0x72, 0xa2, 0x19, 0xec, + 0x23, 0xc8, 0x91, 0xe6, 0x9c, 0x49, 0x0a, 0xc2, 0x04, 0x01, 0xff, 0xcd, 0x75, 0x2d, 0x24, 0x64, + 0x0f, 0x20, 0x1f, 0x84, 0x86, 0x2f, 0x6f, 0x4c, 0x94, 0x44, 0x8e, 0x5d, 0x6f, 0xee, 0x9a, 0x1a, + 0x47, 0x33, 0x15, 0xb2, 0x96, 0x6b, 0x0a, 0x3b, 0xcd, 0x32, 0x15, 0x22, 0xd5, 0x1d, 0x28, 0x45, + 0xc5, 0x23, 0x0b, 0x68, 0xfd, 0x97, 0x03, 0x65, 0x8d, 0x95, 0x20, 0xaf, 0x35, 0x7a, 0xfb, 0x6d, + 0x25, 0xa3, 0xfe, 0x79, 0x06, 0x20, 0xce, 0xc5, 0x1e, 0xa7, 0x5a, 0x7b, 0x73, 0xb1, 0xd4, 0xc7, + 0xf4, 0x37, 0xd1, 0xd8, 0x5b, 0x50, 0x9a, 0xbb, 0x04, 0xb4, 0x4c, 0xb1, 0x13, 0xc5, 0x00, 0x3c, + 0xee, 0x49, 0x6f, 0xa3, 0x85, 0xe3, 0xde, 0x2b, 0xc3, 0x51, 0x7f, 0x01, 0xa5, 0xa8, 0x38, 0x3c, + 0xe0, 0xee, 0xf5, 0xbb, 0xdd, 0xfe, 0xcb, 0x4e, 0x6f, 0x5f, 0x59, 0xc3, 0xe4, 0x91, 0xd6, 0x6e, + 0xb6, 0x5b, 0x98, 0xcc, 0x20, 0xcf, 0x36, 0x8f, 0x35, 0xad, 0xdd, 0x1b, 0xea, 0x5a, 0xff, 0xa5, + 0xb2, 0xae, 0xfe, 0xed, 0x0c, 0x54, 0xfb, 0x8e, 0xd9, 0xf4, 0x9c, 0xa6, 0x31, 0x43, 0xd5, 0x88, + 0x7d, 0x05, 0x5b, 0x27, 0x73, 0x54, 0xcf, 0x67, 0x8e, 0x31, 0xb2, 0x4e, 0x3d, 0xc7, 0xb4, 0xe4, + 0x22, 0x4c, 0xdd, 0x09, 0x09, 0xf3, 0xb5, 0x42, 0xc4, 0x47, 0x31, 0x2d, 0xfb, 0x0c, 0x2a, 0x33, + 0xdf, 0x3b, 0xb1, 0x84, 0x12, 0xb0, 0x74, 0xae, 0x8c, 0xf3, 0x96, 0x89, 0x8e, 0x2b, 0x00, 0xea, + 0xbf, 0xbb, 0x0e, 0x95, 0x96, 0x65, 0xce, 0x67, 0x5f, 0x7b, 0xb6, 0xdb, 0x0c, 0x2f, 0xd8, 0xa7, + 0x50, 0xf1, 0x1c, 0xb2, 0x86, 0xe8, 0x09, 0x7f, 0x88, 0x55, 0xe5, 0x80, 0x47, 0x3d, 0x20, 0xef, + 0x89, 0x0f, 0xe1, 0x0a, 0x37, 0x30, 0x08, 0xd3, 0xdc, 0x05, 0xcf, 0x8c, 0x6b, 0x26, 0xaf, 0x29, + 0x1c, 0xc5, 0x37, 0x68, 0x22, 0xff, 0x23, 0xd8, 0x4e, 0x90, 0xa3, 0x60, 0xe1, 0xf4, 0xd9, 0xa5, + 0x35, 0xb6, 0x15, 0xe5, 0x8d, 0x3c, 0x35, 0xbe, 0x86, 0x6d, 0xd9, 0xc2, 0x11, 0x1f, 0x3d, 0x9e, + 0x39, 0x97, 0x3c, 0x07, 0xa5, 0x46, 0x57, 0x34, 0x78, 0xcb, 0x4b, 0x02, 0xa9, 0xac, 0x4f, 0xe0, + 0xaa, 0x89, 0xbd, 0xd7, 0xf9, 0xe0, 0x9f, 0x59, 0xd6, 0x4c, 0x77, 0x8c, 0x20, 0x14, 0x97, 0xb9, + 0x8c, 0x90, 0xbb, 0x88, 0x7b, 0x6e, 0x59, 0xb3, 0xae, 0x11, 0x84, 0xea, 0xdf, 0xcb, 0x41, 0x89, + 0x5b, 0x47, 0x70, 0xb8, 0x1e, 0x42, 0xc1, 0x3b, 0xf9, 0x8e, 0x54, 0xa6, 0xd7, 0x5c, 0xd8, 0x6e, + 0x78, 0x27, 0xdf, 0xa1, 0x9e, 0xf5, 0xbe, 0xdc, 0xea, 0x4c, 0x6b, 0x2c, 0x66, 0xa7, 0x96, 0x3e, + 0x7f, 0x88, 0xad, 0x0f, 0xcf, 0xc6, 0x4f, 0xa1, 0x6c, 0xbb, 0x81, 0xe5, 0x87, 0xdc, 0x22, 0x54, + 0x78, 0xfd, 0x24, 0x70, 0x32, 0x32, 0x12, 0x3d, 0x85, 0x32, 0xb7, 0x10, 0xf1, 0x4c, 0xc5, 0xd7, + 0x67, 0xe2, 0x64, 0x94, 0xe9, 0x4b, 0xa8, 0xc5, 0x62, 0x8e, 0xf2, 0x95, 0x5e, 0x9b, 0xaf, 0x1a, + 0x51, 0x52, 0xd6, 0x27, 0x70, 0x2d, 0x38, 0xb3, 0x67, 0xba, 0x68, 0xa9, 0xe7, 0xd2, 0x4d, 0x8a, + 0x3e, 0x3b, 0x13, 0x37, 0x18, 0x0c, 0xb1, 0x1d, 0x42, 0xf6, 0xdd, 0xde, 0xdc, 0x71, 0x8e, 0xce, + 0xd8, 0x7b, 0xb0, 0x25, 0xc8, 0x67, 0x67, 0x92, 0x57, 0xe8, 0x54, 0x9c, 0xd7, 0x6a, 0x1c, 0x71, + 0x74, 0x26, 0x34, 0xb9, 0x2f, 0xa0, 0xce, 0x7d, 0x08, 0x44, 0xa7, 0x8c, 0xf1, 0xd8, 0x1a, 0x85, + 0x3a, 0xaa, 0x0e, 0xe2, 0xba, 0xe3, 0x2a, 0xe1, 0xb9, 0x99, 0xab, 0x41, 0x58, 0x92, 0x7c, 0x1f, + 0xc3, 0xb6, 0x3d, 0x71, 0x3d, 0x5f, 0x66, 0xb1, 0x4c, 0x9e, 0x89, 0xdf, 0x83, 0x30, 0x8e, 0x6b, + 0x08, 0x14, 0xe5, 0x78, 0x02, 0xd7, 0x04, 0x1b, 0x5c, 0xea, 0x21, 0xdd, 0x52, 0x62, 0x0e, 0x3c, + 0xa0, 0xd4, 0x92, 0x7c, 0x70, 0xc9, 0x6f, 0x30, 0x35, 0xef, 0xbc, 0x63, 0x22, 0xeb, 0x08, 0x52, + 0xc9, 0xca, 0xe1, 0x05, 0xf5, 0x66, 0x93, 0x7a, 0xc3, 0x38, 0x32, 0xe2, 0x94, 0x8e, 0x79, 0xa1, + 0xfe, 0x7b, 0x19, 0x28, 0xf1, 0xf1, 0x40, 0xd6, 0xb9, 0x0b, 0xd9, 0x1f, 0x60, 0x1b, 0xc4, 0xb1, + 0x47, 0xb0, 0x65, 0x98, 0xe6, 0x42, 0x37, 0xb8, 0x9c, 0xda, 0x34, 0x4c, 0x33, 0xd5, 0x87, 0x87, + 0xa0, 0xd8, 0x81, 0x2e, 0x4f, 0xe6, 0xb1, 0x2b, 0x43, 0x51, 0xab, 0xd9, 0x81, 0x38, 0x98, 0x73, + 0xb3, 0x7d, 0x8a, 0x13, 0x73, 0x3f, 0xcc, 0x89, 0x2a, 0x03, 0xd0, 0x2c, 0x12, 0x4a, 0xcd, 0xf0, + 0xe2, 0xeb, 0x5c, 0x31, 0xa3, 0x80, 0xfa, 0x9f, 0x97, 0xa1, 0xdc, 0x70, 0x0d, 0xe7, 0xf2, 0xb7, + 0x16, 0xf9, 0x61, 0x90, 0x11, 0x77, 0x36, 0x17, 0x73, 0xc3, 0xaf, 0x10, 0x4b, 0x04, 0xa1, 0x96, + 0xdd, 0x81, 0xb2, 0x37, 0x0f, 0x23, 0x3c, 0xbf, 0x54, 0x04, 0x0e, 0x22, 0x82, 0x28, 0x7f, 0x74, + 0x41, 0x20, 0xf3, 0xd3, 0x71, 0x21, 0xce, 0x1f, 0xa9, 0x90, 0x51, 0x7e, 0x22, 0xb8, 0x07, 0xd5, + 0xd0, 0x9e, 0x5a, 0x74, 0x8f, 0x3a, 0x9f, 0x5a, 0x26, 0x77, 0xf6, 0xe4, 0xfe, 0x83, 0x4d, 0x01, + 0xc3, 0x52, 0xa6, 0xd6, 0xd4, 0xf3, 0x2f, 0x79, 0x29, 0x1b, 0xbc, 0x14, 0x0e, 0xa2, 0x52, 0x3e, + 0x00, 0x76, 0x6e, 0xd8, 0xa1, 0x9e, 0x2e, 0x8a, 0xab, 0xed, 0x0a, 0x62, 0x86, 0xc9, 0xe2, 0xae, + 0xc1, 0x86, 0x69, 0x07, 0x67, 0x9d, 0xbe, 0x50, 0xd9, 0x45, 0x0a, 0xfb, 0x12, 0x8c, 0x0c, 0xd4, + 0x18, 0x42, 0x8b, 0xab, 0x97, 0x59, 0xad, 0x84, 0x90, 0x5d, 0x04, 0xe0, 0x8e, 0xe3, 0x5a, 0xe1, + 0xb9, 0xe7, 0x63, 0x4e, 0xae, 0x91, 0xc7, 0x00, 0xdc, 0x99, 0x91, 0x14, 0x2b, 0xa2, 0x45, 0x91, + 0xd5, 0xa2, 0x34, 0xea, 0xba, 0x7c, 0x81, 0x10, 0xb6, 0xc2, 0x9b, 0x1f, 0x43, 0xd8, 0x7d, 0xa8, + 0x51, 0xf3, 0x49, 0x63, 0xc7, 0x3e, 0x10, 0xbf, 0x67, 0xb5, 0x0a, 0x42, 0xc9, 0xd2, 0x80, 0x54, + 0x5f, 0xc2, 0x8d, 0x54, 0xff, 0x74, 0xc3, 0xf7, 0x8d, 0x4b, 0x7d, 0x6a, 0x7c, 0xe7, 0xf9, 0x64, + 0x15, 0xca, 0x6a, 0xd7, 0x92, 0xc3, 0xd6, 0x40, 0xf4, 0x21, 0x62, 0x5f, 0x9b, 0xd5, 0x76, 0x3d, + 0x9f, 0x4c, 0x46, 0x2b, 0xb3, 0x22, 0x96, 0xec, 0x1b, 0x34, 0xc1, 0x74, 0x7c, 0x08, 0xb8, 0xdf, + 0xa9, 0x56, 0x26, 0xd8, 0x2e, 0x81, 0x50, 0x81, 0x0e, 0x9e, 0x72, 0x41, 0xbe, 0x25, 0x9c, 0xc0, + 0x9e, 0x92, 0x88, 0xe6, 0x88, 0x53, 0xcb, 0x30, 0xe9, 0x2e, 0x91, 0x10, 0x07, 0x96, 0x41, 0x37, + 0xf5, 0xc1, 0x53, 0x7d, 0x36, 0x0f, 0xb9, 0xc3, 0xa8, 0x96, 0x0f, 0x9e, 0x1e, 0xcd, 0x43, 0x01, + 0x9e, 0x58, 0x21, 0x5d, 0x1d, 0x12, 0x78, 0xdf, 0x0a, 0x51, 0x0b, 0x0e, 0x9e, 0x4a, 0x0b, 0xfa, + 0x55, 0x31, 0xb6, 0x4f, 0x85, 0x89, 0x5c, 0x85, 0x6a, 0x84, 0xd4, 0xa7, 0x73, 0xee, 0x21, 0x9a, + 0xd5, 0xca, 0x92, 0xe0, 0x70, 0xee, 0xe0, 0xc4, 0x8e, 0x8c, 0xd1, 0x29, 0x1e, 0xaf, 0x0d, 0x93, + 0x9c, 0x44, 0xb3, 0x5a, 0x89, 0x20, 0x1a, 0xb6, 0xe6, 0x2d, 0xe0, 0x09, 0xfd, 0xd4, 0x0e, 0xc9, + 0x74, 0x95, 0xd5, 0x8a, 0x04, 0x38, 0xb0, 0x43, 0x5c, 0xc7, 0x1c, 0x29, 0x38, 0x90, 0x8a, 0xb8, + 0x41, 0x44, 0x9b, 0x84, 0x38, 0x24, 0x38, 0x15, 0xf4, 0x10, 0x94, 0x14, 0x2d, 0x96, 0x77, 0x93, + 0x48, 0x6b, 0x09, 0x52, 0x2c, 0xf5, 0x01, 0xf0, 0xcc, 0x3a, 0xb2, 0x1e, 0x2f, 0xf3, 0x2d, 0x7e, + 0x7c, 0x24, 0x70, 0xcb, 0x0e, 0xce, 0xa8, 0xc4, 0xfb, 0x50, 0x4b, 0xd0, 0x61, 0x79, 0xb7, 0x38, + 0x67, 0x44, 0x64, 0xa9, 0x36, 0xfa, 0xd6, 0xd4, 0x0b, 0x45, 0x37, 0xdf, 0x4e, 0xb4, 0x51, 0x23, + 0x78, 0xba, 0x8d, 0x82, 0x16, 0xcb, 0xbc, 0x9d, 0x68, 0x23, 0x27, 0xc5, 0x52, 0xef, 0x42, 0xe5, + 0xdc, 0xb7, 0xc3, 0xd0, 0x72, 0xf9, 0xe2, 0xbf, 0xc3, 0x07, 0x56, 0xc0, 0x68, 0xf5, 0xdf, 0x85, + 0x0a, 0x1f, 0x79, 0x21, 0xdf, 0x76, 0x38, 0x89, 0x80, 0x49, 0x01, 0x21, 0x46, 0x63, 0x6a, 0xbb, + 0x64, 0x9f, 0xca, 0x6a, 0x25, 0x0e, 0xc1, 0x53, 0x74, 0x02, 0x6d, 0x5c, 0x90, 0x95, 0x2a, 0x46, + 0x1b, 0x17, 0xb4, 0x24, 0x67, 0xb6, 0xe3, 0xf0, 0x85, 0x7f, 0x4f, 0x2c, 0x49, 0x84, 0xd0, 0xba, + 0x8f, 0xd0, 0x54, 0xfb, 0xfd, 0x04, 0x9a, 0xea, 0x46, 0xc6, 0x21, 0x34, 0x56, 0xfd, 0x8e, 0x60, + 0x1c, 0x04, 0x60, 0xcd, 0x31, 0xd2, 0xb8, 0x20, 0x1b, 0x54, 0x84, 0x34, 0x2e, 0x84, 0xdc, 0xc2, + 0x52, 0x29, 0xef, 0xbb, 0x91, 0xdc, 0x42, 0x10, 0xe6, 0x4e, 0x12, 0x18, 0x17, 0xf5, 0x87, 0x69, + 0x02, 0xe3, 0x82, 0x8e, 0x6e, 0x96, 0x61, 0xf2, 0x86, 0xbf, 0xc7, 0x8b, 0x47, 0x00, 0xb5, 0x7b, + 0x07, 0x2a, 0xc1, 0x53, 0x3d, 0xc6, 0x3f, 0xe2, 0xd9, 0x83, 0xa7, 0x9a, 0xa4, 0xb8, 0x0f, 0xb5, + 0x88, 0x35, 0x38, 0xcd, 0xfb, 0x7c, 0xe2, 0x4d, 0xc1, 0x1a, 0x74, 0xf5, 0xfa, 0xbb, 0x0c, 0xdc, + 0xec, 0x93, 0x79, 0x8d, 0xc4, 0xff, 0xa1, 0x15, 0x04, 0xc6, 0xc4, 0xda, 0xf3, 0xfc, 0xbd, 0xf9, + 0x6f, 0x7f, 0x7b, 0xc9, 0x1e, 0xc2, 0xe6, 0x91, 0xe1, 0x5b, 0x6e, 0x18, 0x5d, 0x1a, 0x0a, 0x93, + 0xd5, 0x22, 0x98, 0x3d, 0x03, 0x85, 0x83, 0xb8, 0x03, 0x5c, 0x53, 0x5e, 0x84, 0x2d, 0x5a, 0xe6, + 0x97, 0xa8, 0xf0, 0x14, 0x5a, 0x6a, 0xd9, 0x41, 0xa8, 0x19, 0xee, 0x04, 0x65, 0x94, 0xe2, 0x78, + 0xe7, 0x78, 0x94, 0x42, 0xfd, 0x5a, 0x4f, 0x68, 0xf4, 0x62, 0x97, 0x8c, 0xd5, 0xf8, 0x1a, 0x11, + 0xc6, 0x7a, 0xf8, 0x97, 0xa0, 0xcc, 0x67, 0xb3, 0x74, 0xd6, 0xf5, 0xd7, 0x64, 0x25, 0xc2, 0x38, + 0xeb, 0xfb, 0x50, 0x4e, 0xd4, 0xba, 0x42, 0xeb, 0x87, 0xb8, 0x2e, 0x24, 0x4e, 0xd4, 0xb3, 0xc2, + 0x01, 0x17, 0xe2, 0xd2, 0xd5, 0x7f, 0x61, 0x1d, 0x14, 0x61, 0x2f, 0x33, 0x4c, 0xcb, 0xa7, 0xbb, + 0xc7, 0xd4, 0x79, 0x31, 0xf3, 0xc6, 0xf3, 0xe2, 0x0e, 0xe4, 0x1d, 0x7b, 0x1a, 0xf9, 0xa1, 0xa5, + 0x6e, 0xc4, 0x08, 0x81, 0x73, 0xed, 0xf9, 0xf6, 0x84, 0x4e, 0xb6, 0x49, 0x9f, 0x4c, 0xb2, 0x9c, + 0xe2, 0x41, 0x91, 0xa6, 0xe8, 0x31, 0x80, 0x69, 0x07, 0xa1, 0x4e, 0xb6, 0x9e, 0xb4, 0x91, 0x30, + 0x1a, 0x7f, 0xad, 0x64, 0x46, 0x53, 0xf1, 0x10, 0x94, 0x84, 0x76, 0xe8, 0x46, 0x66, 0x9a, 0xbc, + 0x16, 0x6b, 0x8d, 0x4d, 0xb7, 0xe9, 0x86, 0x4b, 0x94, 0xa8, 0x09, 0x6d, 0x2c, 0x51, 0xa2, 0x16, + 0xf4, 0xf7, 0xdf, 0x81, 0x5c, 0xcf, 0x33, 0x2d, 0xf6, 0x31, 0x94, 0xc8, 0xd1, 0x39, 0x31, 0xc1, + 0x42, 0x7b, 0x47, 0x34, 0xfd, 0xa1, 0x99, 0x2a, 0xba, 0xe2, 0xd7, 0xeb, 0x5d, 0xa3, 0xef, 0xd2, + 0xa9, 0x93, 0xae, 0xc7, 0xb1, 0x4b, 0x65, 0x61, 0x19, 0x23, 0x43, 0x0e, 0xc7, 0xe0, 0xde, 0x4a, + 0x17, 0x20, 0xbe, 0xe5, 0xd2, 0x51, 0x21, 0xaf, 0x45, 0x69, 0x3a, 0xeb, 0xfb, 0x1e, 0xaa, 0x5e, + 0x7c, 0x07, 0xca, 0xaf, 0x38, 0xeb, 0x73, 0x3c, 0x6d, 0x49, 0x1f, 0x43, 0xe9, 0x3b, 0xcf, 0x76, + 0x79, 0xc3, 0x37, 0x96, 0x1a, 0x8e, 0x47, 0x29, 0xde, 0xf0, 0xef, 0xc4, 0x2f, 0x76, 0x0f, 0x0a, + 0x9e, 0xcb, 0xcb, 0x2e, 0x2c, 0x95, 0xbd, 0xe1, 0xb9, 0x5d, 0xee, 0xe9, 0x56, 0xb5, 0x03, 0xdd, + 0xb7, 0x27, 0xa7, 0xa1, 0x8e, 0x39, 0xc5, 0xb5, 0x7a, 0xd9, 0x0e, 0x34, 0x84, 0x61, 0xb1, 0xc8, + 0x78, 0x63, 0xdb, 0x41, 0x0d, 0x8f, 0x0a, 0x2b, 0x2d, 0x15, 0x06, 0x1c, 0x4d, 0x05, 0xbe, 0x03, + 0xc5, 0x89, 0xef, 0x91, 0x5a, 0x5b, 0x87, 0x25, 0xca, 0x02, 0xe1, 0x76, 0x2f, 0x51, 0x7d, 0xa2, + 0x9f, 0xb6, 0x3b, 0xd1, 0xc9, 0x7c, 0x53, 0xde, 0xc9, 0x3e, 0x2c, 0x6a, 0x15, 0x09, 0x24, 0xc3, + 0xcc, 0x3b, 0x50, 0x34, 0x26, 0x13, 0x5d, 0x38, 0xec, 0x2d, 0x95, 0x65, 0x4c, 0x26, 0x54, 0xe5, + 0x63, 0xa8, 0x9e, 0xdb, 0xae, 0x1e, 0xcc, 0xac, 0x11, 0xa7, 0xad, 0x2e, 0x0f, 0xe5, 0xb9, 0xed, + 0x22, 0x77, 0x13, 0x7d, 0x72, 0x19, 0xd4, 0x7e, 0xfc, 0x32, 0xd8, 0x7c, 0xdd, 0x32, 0x50, 0x61, + 0x43, 0x5c, 0x8e, 0x28, 0x4b, 0x24, 0x02, 0xc3, 0x3e, 0x81, 0xb2, 0x6f, 0xb8, 0x67, 0xba, 0xf0, + 0x51, 0xf8, 0x36, 0x69, 0x82, 0xd0, 0x0c, 0xf7, 0x4c, 0xb8, 0x28, 0x80, 0x1f, 0xfd, 0x4e, 0xab, + 0xcc, 0x5b, 0x6f, 0x38, 0xbc, 0x25, 0xce, 0x84, 0xec, 0x87, 0xcf, 0x84, 0x9f, 0xd1, 0xe1, 0xcb, + 0x72, 0x43, 0x5d, 0x66, 0xb8, 0xb2, 0x3a, 0x43, 0x85, 0x93, 0xf5, 0x79, 0x36, 0xec, 0x00, 0x99, + 0x00, 0x75, 0xb2, 0x17, 0x6e, 0xa7, 0x3a, 0x10, 0xd9, 0x06, 0x35, 0xf0, 0x63, 0x3b, 0x61, 0x03, + 0x36, 0x63, 0x3f, 0x69, 0xee, 0x9c, 0x7e, 0x35, 0x79, 0x09, 0x92, 0x72, 0xac, 0x96, 0xc7, 0x3d, + 0x3b, 0xe5, 0x6d, 0x7d, 0x0f, 0xaa, 0xdc, 0x29, 0x88, 0x8f, 0x5b, 0x40, 0x4a, 0x52, 0x49, 0xab, + 0x10, 0x90, 0x8f, 0x53, 0x40, 0x02, 0x46, 0x9c, 0x41, 0xc3, 0x0b, 0xd2, 0x92, 0x62, 0x01, 0xc3, + 0x0f, 0x9d, 0xe1, 0x85, 0x56, 0x32, 0xe5, 0x4f, 0xdc, 0xfc, 0x4f, 0x6c, 0xd7, 0x44, 0xd6, 0x0b, + 0x8d, 0x49, 0x50, 0xaf, 0xd3, 0xca, 0x2c, 0x0b, 0xd8, 0xd0, 0x98, 0x04, 0xec, 0x53, 0xa8, 0x18, + 0xfc, 0xb0, 0xc1, 0xdb, 0x7d, 0x23, 0x69, 0x32, 0x4b, 0x1c, 0x43, 0xb4, 0xb2, 0x91, 0x38, 0x93, + 0x7c, 0x01, 0x4c, 0xde, 0xdd, 0x26, 0x0c, 0x0c, 0x37, 0x97, 0xb8, 0x71, 0x53, 0x5c, 0xde, 0x46, + 0xe6, 0x85, 0x3b, 0x50, 0x16, 0xf7, 0x28, 0x41, 0x68, 0xcd, 0xea, 0x6f, 0x51, 0x83, 0x80, 0x83, + 0x06, 0xa1, 0x35, 0x63, 0x5f, 0x40, 0x35, 0x7d, 0xca, 0xba, 0xb5, 0xe2, 0x0a, 0x94, 0xd8, 0x42, + 0xab, 0x8c, 0x92, 0xe7, 0xae, 0x7b, 0xdc, 0xdf, 0x9f, 0x34, 0x24, 0xca, 0xc8, 0xaf, 0xf9, 0x2a, + 0xae, 0x17, 0x36, 0x25, 0x0c, 0x07, 0x50, 0x9e, 0xfc, 0xc3, 0x0b, 0x52, 0xaa, 0xa2, 0x01, 0x8c, + 0x8e, 0x8e, 0x78, 0x38, 0x92, 0xa7, 0xc8, 0x16, 0x30, 0x79, 0x6b, 0x83, 0x9b, 0x0b, 0x77, 0x78, + 0x21, 0x1d, 0x2a, 0xba, 0x15, 0x5d, 0xdc, 0x7b, 0x34, 0xee, 0x1c, 0x94, 0xdc, 0x8d, 0x9e, 0x41, + 0x6d, 0xe6, 0x5b, 0x7a, 0xa2, 0x66, 0x35, 0xd9, 0xa9, 0x23, 0xdf, 0x8a, 0x2b, 0xaf, 0xcc, 0x12, + 0x29, 0xf6, 0x15, 0x6c, 0x25, 0x72, 0xce, 0xcf, 0x28, 0xf3, 0x3d, 0xca, 0xbc, 0xbd, 0x90, 0xf9, + 0xf8, 0x0c, 0xb3, 0xd7, 0x66, 0xa9, 0x34, 0xdb, 0x86, 0x7c, 0x27, 0x68, 0xbb, 0x26, 0xe9, 0x56, + 0x45, 0x8d, 0x27, 0xd8, 0x53, 0xa8, 0xf0, 0x83, 0x0c, 0x9d, 0xa2, 0x83, 0xfa, 0x83, 0xa4, 0x4d, + 0x9c, 0x4e, 0x33, 0xfc, 0x28, 0x5e, 0x76, 0xa2, 0xdf, 0x01, 0xfb, 0x1c, 0xb6, 0xf8, 0x85, 0x45, + 0x52, 0x44, 0xbe, 0xbb, 0x3c, 0xe5, 0x44, 0xb4, 0x17, 0xcb, 0x49, 0x0d, 0x6e, 0xf8, 0x73, 0x97, + 0x0e, 0x37, 0x22, 0x27, 0x37, 0xa5, 0x51, 0xfe, 0x87, 0x94, 0xff, 0xba, 0x58, 0x5d, 0x9c, 0x8c, + 0xe7, 0x25, 0xd9, 0x74, 0xcd, 0x4f, 0x82, 0x8e, 0x30, 0xdf, 0x6b, 0xca, 0xe4, 0x26, 0x26, 0x2a, + 0xf3, 0xbd, 0x9f, 0x52, 0x26, 0x99, 0x9f, 0xa8, 0x4c, 0x06, 0xb9, 0xf9, 0xdc, 0x36, 0x49, 0xd3, + 0xab, 0x68, 0xf4, 0x9b, 0xbd, 0x03, 0x35, 0xdf, 0x1a, 0xcd, 0xfd, 0xc0, 0x7e, 0x65, 0xe9, 0x81, + 0xed, 0x9e, 0x91, 0x8e, 0x57, 0xd4, 0xaa, 0x11, 0x74, 0x60, 0xbb, 0x67, 0x28, 0x32, 0xac, 0x8b, + 0xd0, 0xf2, 0x5d, 0xfe, 0x50, 0xe2, 0x83, 0xa4, 0xc8, 0x68, 0x13, 0x02, 0xd7, 0xb9, 0x06, 0x56, + 0xf4, 0x7b, 0x61, 0x66, 0x03, 0x3e, 0xb3, 0x8f, 0x7f, 0xd4, 0xcc, 0x0e, 0x68, 0x66, 0x1f, 0x40, + 0xd1, 0x76, 0x43, 0xcb, 0x7f, 0x65, 0x38, 0xf5, 0x8f, 0x96, 0xa4, 0x71, 0x84, 0x63, 0xf7, 0xa1, + 0x10, 0x38, 0x36, 0xae, 0xf7, 0xfa, 0xc7, 0x4b, 0x64, 0x12, 0xc5, 0x1e, 0x42, 0x29, 0x7a, 0x0f, + 0x58, 0xff, 0x64, 0x89, 0x2e, 0x46, 0xb2, 0xdb, 0x90, 0x3b, 0x47, 0x86, 0x7a, 0xb2, 0x7c, 0x87, + 0x81, 0x70, 0xdc, 0xbe, 0xc7, 0xa8, 0xb3, 0xd3, 0xf6, 0xfd, 0x74, 0x69, 0xfb, 0xde, 0xb3, 0x1d, + 0x87, 0x6f, 0xdf, 0x63, 0xf1, 0x0b, 0x37, 0x3f, 0xca, 0x81, 0x3d, 0xf9, 0x74, 0x79, 0xf3, 0x43, + 0xdc, 0x0b, 0x7a, 0x39, 0x59, 0x0e, 0xc8, 0x30, 0xcf, 0xef, 0x17, 0x3e, 0x4b, 0x8e, 0x55, 0xda, + 0x62, 0xaf, 0x41, 0x10, 0xa5, 0xf1, 0x00, 0x22, 0xae, 0x25, 0x50, 0x69, 0xfa, 0x9c, 0x3f, 0xb3, + 0xe1, 0x90, 0x8e, 0x79, 0xc1, 0x3e, 0x86, 0xaa, 0xf4, 0xc7, 0xc2, 0xea, 0x82, 0xfa, 0x17, 0x4b, + 0x2d, 0x48, 0x13, 0xb0, 0x16, 0x54, 0xc6, 0xa8, 0xbb, 0x4f, 0xb9, 0x2a, 0x5f, 0x7f, 0x46, 0x0d, + 0xd9, 0x91, 0x1b, 0xeb, 0xeb, 0x54, 0x7d, 0x2d, 0x95, 0x8b, 0x3d, 0x06, 0x66, 0x8f, 0xf9, 0x7c, + 0xee, 0xf9, 0xde, 0x94, 0xab, 0xeb, 0xf5, 0x2f, 0x85, 0x11, 0x6d, 0x09, 0x43, 0xb7, 0x94, 0x96, + 0x6b, 0xea, 0xd3, 0x40, 0xa8, 0x09, 0xbf, 0xa0, 0x76, 0x0a, 0xe1, 0x15, 0xbd, 0x1b, 0x96, 0x56, + 0x68, 0xa4, 0x3d, 0x0c, 0xb8, 0xd6, 0xf0, 0x25, 0x20, 0xbb, 0xbe, 0x8a, 0xb3, 0xfe, 0xd1, 0x0f, + 0x66, 0x45, 0x5a, 0x99, 0xf5, 0x19, 0xd4, 0xb8, 0xe9, 0x8e, 0x34, 0x32, 0x64, 0xd1, 0x5f, 0x26, + 0x25, 0x57, 0xd2, 0xb6, 0xad, 0x55, 0xcc, 0xa4, 0xa5, 0xfb, 0x0b, 0xd8, 0x4c, 0x58, 0xee, 0xa8, + 0xda, 0x3f, 0x4e, 0x56, 0x1b, 0x99, 0xee, 0xb4, 0xea, 0x5c, 0xfe, 0xa4, 0x2a, 0x9f, 0x42, 0x95, + 0x76, 0xd1, 0xe8, 0x61, 0xd6, 0xdf, 0x58, 0xf9, 0x30, 0xab, 0x82, 0x44, 0x32, 0x85, 0xc2, 0x3f, + 0x5e, 0xa7, 0xa3, 0xd0, 0xaa, 0x7f, 0xc5, 0x85, 0x7f, 0x04, 0x6c, 0x86, 0x16, 0x7b, 0x0a, 0x60, + 0xcc, 0x66, 0xce, 0x25, 0x67, 0xcd, 0x5f, 0x11, 0x6b, 0x6e, 0x27, 0x58, 0xb3, 0x81, 0x48, 0xe2, + 0xcd, 0x92, 0x21, 0x7f, 0xb2, 0x27, 0x50, 0x99, 0x79, 0x41, 0xa8, 0x9b, 0x53, 0x87, 0xfa, 0xdf, + 0x48, 0xae, 0xed, 0x23, 0x2f, 0x08, 0x5b, 0x53, 0x07, 0x7b, 0x01, 0xb3, 0xe8, 0x37, 0xeb, 0xc2, + 0x15, 0xcf, 0xd5, 0xcd, 0xf9, 0xcc, 0xb1, 0x47, 0x38, 0x02, 0x06, 0xf9, 0x24, 0xd4, 0x77, 0xa9, + 0xc6, 0x5b, 0x89, 0x1a, 0xfb, 0x6e, 0x4b, 0x12, 0x09, 0xe7, 0xc0, 0x2d, 0x6f, 0x11, 0x44, 0xe7, + 0x4c, 0x9a, 0x83, 0xc8, 0x99, 0xb6, 0xc9, 0x55, 0x03, 0x82, 0x4a, 0x6f, 0xda, 0x67, 0xb0, 0x19, + 0x53, 0x61, 0x07, 0x83, 0x7a, 0x2b, 0xc9, 0xc9, 0x09, 0xef, 0xfc, 0xaa, 0xcc, 0x88, 0xb0, 0x80, + 0xc6, 0xce, 0x73, 0x9c, 0xf9, 0x4c, 0x88, 0xd2, 0x7a, 0x5b, 0x8c, 0x1d, 0x01, 0xb9, 0x94, 0x4c, + 0x1c, 0xc5, 0xad, 0x69, 0x7d, 0x2f, 0x79, 0x14, 0xb7, 0xa6, 0xa8, 0x66, 0x08, 0x7f, 0xc1, 0x57, + 0xb6, 0x75, 0x1e, 0xd4, 0xf7, 0xc9, 0xc9, 0x53, 0xf8, 0xa2, 0xbf, 0x40, 0x10, 0xee, 0xfb, 0xa6, + 0xed, 0xe3, 0x11, 0x80, 0xdc, 0xd6, 0x0e, 0xb8, 0x33, 0x33, 0x07, 0x21, 0x05, 0x6b, 0x42, 0x9d, + 0xc4, 0xb9, 0x58, 0xab, 0xa9, 0xcb, 0xc1, 0xce, 0xd2, 0x92, 0xbc, 0x8a, 0xb4, 0xfc, 0xee, 0xf1, + 0x28, 0x71, 0x4d, 0xf8, 0x2b, 0x78, 0x7b, 0x75, 0x21, 0xf2, 0xdd, 0xea, 0xd7, 0xa4, 0x6f, 0xdc, + 0x58, 0x91, 0xbb, 0xc9, 0x9f, 0xb2, 0xfe, 0x02, 0xaa, 0x13, 0x83, 0x46, 0xc2, 0xd1, 0xa7, 0x9e, + 0x69, 0xd5, 0x9f, 0x27, 0x9f, 0x94, 0xd2, 0xa4, 0xed, 0x1b, 0x38, 0x28, 0xce, 0xa1, 0x67, 0x5a, + 0x5a, 0x79, 0x12, 0x27, 0xd8, 0x33, 0xa8, 0xc7, 0x4c, 0x38, 0x77, 0xb1, 0x5e, 0x3c, 0xeb, 0xd9, + 0xee, 0x28, 0xac, 0x77, 0x69, 0x4c, 0xaf, 0x45, 0xf8, 0x63, 0x44, 0xb7, 0x04, 0x96, 0x35, 0x41, + 0x21, 0xe1, 0x20, 0x76, 0xb1, 0xc0, 0x36, 0xad, 0xfa, 0x61, 0xf2, 0xc9, 0x18, 0x17, 0x9d, 0x48, + 0x42, 0xfb, 0xd5, 0xc0, 0x36, 0x2d, 0xad, 0x36, 0x4e, 0xa5, 0xd5, 0xff, 0x20, 0x0f, 0x45, 0x79, + 0xaa, 0x63, 0x65, 0x28, 0x1c, 0xf7, 0x9e, 0xf7, 0xfa, 0x2f, 0x7b, 0xfc, 0xe5, 0x69, 0x63, 0x30, + 0x68, 0x6b, 0x43, 0xc5, 0x64, 0x35, 0x00, 0x7a, 0xcd, 0xa5, 0x0f, 0x9a, 0x8d, 0x1e, 0x7f, 0x89, + 0x4a, 0x6f, 0xc8, 0x78, 0x7a, 0x9d, 0x6d, 0x41, 0x75, 0xef, 0xb8, 0x47, 0xbe, 0xa4, 0x1c, 0x94, + 0x45, 0x50, 0xfb, 0x1b, 0x7e, 0x6b, 0xcc, 0x41, 0x39, 0x04, 0x1d, 0x36, 0x86, 0x6d, 0xad, 0x23, + 0x41, 0x79, 0x76, 0x15, 0xb6, 0x22, 0x2a, 0x59, 0x82, 0x52, 0xc0, 0x86, 0x1c, 0x69, 0xfd, 0xaf, + 0xdb, 0xcd, 0xa1, 0x02, 0x74, 0xe3, 0xbc, 0xbf, 0xaf, 0x94, 0x59, 0x05, 0x8a, 0xad, 0xce, 0x60, + 0xd8, 0xe9, 0x35, 0x87, 0x4a, 0x05, 0xdb, 0xb7, 0xd7, 0xe9, 0x0e, 0xdb, 0x9a, 0x52, 0x65, 0x45, + 0xc8, 0x7d, 0xdd, 0xef, 0xf4, 0x94, 0x1a, 0x3d, 0x62, 0x6b, 0x1c, 0x1e, 0x75, 0xdb, 0xca, 0x26, + 0x42, 0x07, 0x7d, 0x6d, 0xa8, 0x28, 0x08, 0x7d, 0xd9, 0xe9, 0xb5, 0xfa, 0x2f, 0x95, 0x2d, 0x56, + 0x82, 0xfc, 0x71, 0x0f, 0xab, 0x61, 0xac, 0x0a, 0x25, 0xfa, 0xa9, 0x37, 0xba, 0x5d, 0xe5, 0x4a, + 0xe2, 0x9a, 0x7a, 0x1b, 0x51, 0x74, 0xe9, 0x3d, 0xc0, 0x36, 0x5c, 0xc5, 0xa6, 0x47, 0x49, 0xa2, + 0xbe, 0x86, 0xe5, 0x1c, 0x76, 0x7a, 0xc7, 0x03, 0xe5, 0x3a, 0x12, 0xd3, 0x4f, 0xc2, 0xd4, 0xb1, + 0x9c, 0x4e, 0x8f, 0x46, 0xee, 0x36, 0xfe, 0x6e, 0xb5, 0xbb, 0xed, 0x61, 0x5b, 0xb9, 0x83, 0xbd, + 0xea, 0xf6, 0x9b, 0xcf, 0xf5, 0xfe, 0x91, 0x72, 0x17, 0x87, 0xf0, 0x48, 0x6b, 0xeb, 0x82, 0xf0, + 0x1e, 0x53, 0xa0, 0xb2, 0x77, 0xfc, 0x9b, 0xdf, 0x7c, 0xab, 0x8b, 0x4e, 0xbd, 0x83, 0x75, 0xc6, + 0x14, 0xfa, 0xf1, 0x73, 0xe5, 0xc1, 0x02, 0x68, 0xf0, 0x5c, 0x79, 0x17, 0x07, 0x45, 0x0e, 0xaa, + 0xf2, 0x10, 0x09, 0xb4, 0x76, 0xf3, 0x58, 0x1b, 0x74, 0x5e, 0xb4, 0xf5, 0xe6, 0xb0, 0xad, 0xbc, + 0x47, 0xa3, 0xd0, 0xe9, 0x3d, 0x57, 0x1e, 0x61, 0x33, 0xf1, 0x17, 0x1f, 0xfb, 0xf7, 0x19, 0x83, + 0x5a, 0x4c, 0x4b, 0xb0, 0x0f, 0x90, 0x64, 0x57, 0xeb, 0x37, 0x5a, 0xcd, 0xc6, 0x60, 0xa8, 0x7c, + 0x88, 0x7d, 0x1c, 0x1c, 0x75, 0x3b, 0x43, 0xe5, 0x31, 0x76, 0x64, 0xbf, 0x31, 0x3c, 0x68, 0x6b, + 0xca, 0x47, 0x6c, 0x13, 0xca, 0xc3, 0xce, 0x61, 0x5b, 0x17, 0x63, 0xfa, 0x04, 0xeb, 0xd8, 0xeb, + 0x74, 0xbb, 0xca, 0x53, 0xba, 0x66, 0x6d, 0x68, 0xc3, 0x0e, 0x4d, 0xe4, 0xa7, 0x58, 0x40, 0xe3, + 0xe8, 0xa8, 0xfb, 0xad, 0xf2, 0x19, 0x76, 0xf0, 0xf0, 0xb8, 0x3b, 0xec, 0xe8, 0xc7, 0x47, 0xad, + 0xc6, 0xb0, 0xad, 0x7c, 0x4e, 0xb3, 0xdc, 0x1f, 0x0c, 0x5b, 0x87, 0x5d, 0xe5, 0x0b, 0x2a, 0x93, + 0x58, 0xaa, 0xd9, 0xed, 0xf7, 0xda, 0xca, 0x33, 0x35, 0x57, 0xdc, 0x50, 0x36, 0xd4, 0x5c, 0x71, + 0x47, 0xd9, 0x51, 0x73, 0x45, 0x55, 0x51, 0x1f, 0x95, 0x07, 0xfd, 0x63, 0xad, 0xc9, 0xdb, 0xaa, + 0xfe, 0x2d, 0x28, 0xca, 0x43, 0x3d, 0xd6, 0xd2, 0xe9, 0xf5, 0xda, 0x9a, 0xb2, 0x86, 0x2d, 0xe9, + 0xb6, 0xf7, 0x86, 0x4a, 0x86, 0xae, 0xa4, 0x3b, 0xfb, 0x07, 0x43, 0x65, 0x1d, 0x7f, 0xf6, 0x8f, + 0x71, 0x50, 0xb3, 0x34, 0x1a, 0xed, 0xc3, 0x8e, 0x92, 0xc3, 0x5f, 0x8d, 0xde, 0xb0, 0xa3, 0xe4, + 0x89, 0x67, 0x3a, 0xbd, 0xfd, 0x6e, 0x5b, 0xd9, 0x40, 0xe8, 0x61, 0x43, 0x7b, 0xae, 0x14, 0x78, + 0xa1, 0xad, 0xf6, 0x37, 0x4a, 0x91, 0x6d, 0xc0, 0x7a, 0xf7, 0x89, 0x52, 0x42, 0x50, 0xab, 0xdd, + 0x3a, 0x3e, 0x52, 0x40, 0x7d, 0x08, 0x85, 0xc6, 0x64, 0x42, 0x2b, 0x18, 0x3b, 0x7f, 0xdc, 0xed, + 0xf2, 0x25, 0xb3, 0xdb, 0x1f, 0x0e, 0xfb, 0x87, 0x4a, 0x06, 0xb9, 0x76, 0xd8, 0x3f, 0x52, 0xd6, + 0xd5, 0x0e, 0x14, 0xa5, 0xfa, 0x92, 0x78, 0x94, 0x59, 0x84, 0xdc, 0x91, 0xd6, 0x7e, 0xc1, 0xfd, + 0x28, 0x7a, 0xed, 0x6f, 0xb0, 0x99, 0xf8, 0x0b, 0x0b, 0xca, 0x62, 0x45, 0xfc, 0xf5, 0x24, 0xbd, + 0xca, 0xec, 0x76, 0x7a, 0xed, 0x86, 0xa6, 0xe4, 0xd5, 0x67, 0x50, 0x4e, 0xc8, 0x11, 0x9c, 0xec, + 0xfd, 0xc6, 0x11, 0x32, 0x4c, 0x57, 0x17, 0xc5, 0x5e, 0x03, 0x16, 0x81, 0xe2, 0x79, 0xc8, 0xa8, + 0x9f, 0xc1, 0xd6, 0xd2, 0xb6, 0x41, 0x0d, 0x6f, 0x74, 0x44, 0xc3, 0x3b, 0xfb, 0xbd, 0xbe, 0xd6, + 0xe6, 0x0f, 0x44, 0xc5, 0x0c, 0xad, 0xab, 0xef, 0x43, 0x29, 0xda, 0xdf, 0x90, 0x63, 0x9b, 0x5a, + 0x7f, 0x30, 0xe0, 0x13, 0xba, 0x86, 0x69, 0x1a, 0x55, 0x9e, 0xce, 0xa8, 0x36, 0xd4, 0xd2, 0xc2, + 0x86, 0xed, 0xc0, 0x2d, 0xce, 0xd3, 0xbb, 0xc7, 0x9d, 0x6e, 0x4b, 0x1f, 0x74, 0x5a, 0x6d, 0xfd, + 0xb8, 0x37, 0x38, 0x6a, 0x37, 0x3b, 0x7b, 0x9d, 0x76, 0x4b, 0x59, 0x63, 0x37, 0xe1, 0xda, 0x12, + 0x05, 0x7f, 0x9d, 0x9a, 0x61, 0x37, 0xe0, 0xea, 0x12, 0x8e, 0x38, 0x79, 0xfd, 0xeb, 0x5c, 0xf1, + 0x8e, 0xb2, 0xf3, 0x75, 0xae, 0x78, 0x5f, 0x79, 0x47, 0x1d, 0xc0, 0x96, 0xdc, 0xd1, 0xe9, 0x1d, + 0x0c, 0x1d, 0x35, 0xb7, 0x21, 0xdf, 0xb5, 0x5e, 0x59, 0x8e, 0x7c, 0xd0, 0x41, 0x09, 0x84, 0xf6, + 0x4f, 0xbe, 0xeb, 0x44, 0x81, 0x0c, 0x28, 0x81, 0x2a, 0x7c, 0x2f, 0x11, 0x4b, 0x81, 0x9e, 0xff, + 0xfe, 0xcb, 0x19, 0x28, 0x46, 0x7a, 0xc2, 0x7d, 0x58, 0x1f, 0x0e, 0xc4, 0xa5, 0xe0, 0xf6, 0xe3, + 0x38, 0x74, 0xcc, 0x50, 0xfe, 0xd2, 0xd6, 0x87, 0x03, 0xf6, 0x01, 0x6c, 0xf0, 0xe7, 0xdc, 0xc2, + 0x20, 0xb8, 0x9d, 0xd6, 0x3d, 0x86, 0x84, 0xd3, 0x04, 0x0d, 0xfb, 0x0c, 0x4a, 0x51, 0x6b, 0x85, + 0x85, 0xec, 0x7a, 0x3a, 0x43, 0x84, 0xd6, 0x62, 0x4a, 0xb5, 0x0b, 0xb5, 0x74, 0x81, 0xec, 0x36, + 0x00, 0x2f, 0x32, 0x61, 0x06, 0x4e, 0x40, 0xd8, 0x4d, 0x90, 0xaf, 0xcc, 0x5b, 0xd4, 0xb0, 0x6a, + 0xf4, 0xea, 0xbc, 0xa5, 0xfe, 0x69, 0x0e, 0x20, 0x3e, 0x69, 0xe0, 0x40, 0x44, 0x76, 0xbf, 0xbc, + 0x70, 0xc7, 0x78, 0x0b, 0x4a, 0x8e, 0x67, 0x98, 0xc9, 0xc8, 0x31, 0x45, 0x04, 0x10, 0x47, 0x24, + 0xdf, 0x43, 0x96, 0xb8, 0x2f, 0x14, 0xbb, 0x06, 0x1b, 0x63, 0xcf, 0x9f, 0x1a, 0xa1, 0x78, 0xbd, + 0x23, 0x52, 0xa8, 0x30, 0xf0, 0x5b, 0x5e, 0x3c, 0x6f, 0xb9, 0xf4, 0x80, 0x07, 0xe7, 0xa0, 0x22, + 0x80, 0x5d, 0x84, 0xe1, 0x86, 0x6f, 0xb9, 0x23, 0xc7, 0x0b, 0x2c, 0x13, 0xb7, 0xf0, 0x0d, 0x3a, + 0x54, 0x81, 0x04, 0xed, 0x5e, 0xf2, 0xde, 0xfa, 0x53, 0xdb, 0x35, 0x42, 0x71, 0x11, 0x48, 0xbd, + 0x95, 0x10, 0x6c, 0xee, 0x77, 0x81, 0x27, 0xcc, 0x80, 0xfc, 0xf1, 0x5f, 0x11, 0x01, 0xd4, 0xdc, + 0xb7, 0x01, 0xac, 0x60, 0x64, 0xcc, 0x78, 0xe1, 0x25, 0xfe, 0x02, 0x5b, 0x40, 0x76, 0x2f, 0x59, + 0x17, 0x6a, 0xc3, 0x13, 0x54, 0x70, 0xbc, 0x96, 0x11, 0x1a, 0x4d, 0xcf, 0x11, 0x06, 0xba, 0xfb, + 0x8b, 0x47, 0xb2, 0xc7, 0x69, 0x32, 0xee, 0x95, 0xbc, 0x90, 0x97, 0x7d, 0x0a, 0x15, 0x7b, 0x64, + 0x9d, 0x58, 0xfe, 0x84, 0x1f, 0xef, 0xca, 0xa9, 0x67, 0x37, 0x1c, 0x43, 0xe7, 0xbb, 0xb2, 0x1d, + 0x27, 0x50, 0x71, 0x9c, 0x7a, 0xee, 0xc4, 0x33, 0x4f, 0x78, 0xae, 0x4a, 0xd2, 0xd8, 0x70, 0x88, + 0x18, 0x9e, 0x47, 0x10, 0x61, 0xe2, 0x66, 0x03, 0xae, 0xac, 0x68, 0xd0, 0x4f, 0x72, 0x85, 0xfd, + 0x2f, 0xd6, 0xa1, 0x9c, 0x68, 0x13, 0xdd, 0xde, 0x18, 0x33, 0xb2, 0x3e, 0x46, 0x6f, 0x01, 0x4a, + 0x02, 0xc2, 0x1f, 0x46, 0x8d, 0x8c, 0xd0, 0x70, 0xbc, 0x49, 0xe2, 0xc9, 0x97, 0x80, 0x74, 0x4c, + 0xba, 0x50, 0x35, 0xa6, 0x56, 0x30, 0x33, 0x46, 0x72, 0x55, 0xc5, 0x80, 0x38, 0xcc, 0x51, 0x2e, + 0x19, 0xe6, 0x48, 0xe1, 0x37, 0xef, 0xdc, 0xa7, 0x8a, 0x2e, 0xda, 0xef, 0x40, 0x59, 0x6a, 0xf3, + 0x58, 0x8b, 0xb8, 0x1c, 0x96, 0xa0, 0x8e, 0xc9, 0x1e, 0x40, 0x1c, 0xc6, 0x49, 0x37, 0x02, 0xdd, + 0x1b, 0x4b, 0x87, 0xce, 0x08, 0xdc, 0x08, 0xfa, 0xe3, 0xe8, 0xc6, 0x86, 0x34, 0x33, 0xc1, 0x13, + 0x08, 0x20, 0x19, 0xfa, 0x18, 0xae, 0x08, 0x33, 0xb2, 0x65, 0xea, 0x63, 0xdb, 0x72, 0x4c, 0xdd, + 0x36, 0xb9, 0xc3, 0x45, 0x5e, 0xdb, 0x8a, 0x50, 0x7b, 0x88, 0xe9, 0x98, 0xa4, 0xf7, 0x0a, 0xdb, + 0x81, 0x69, 0x4f, 0xac, 0x20, 0x14, 0xee, 0x87, 0x15, 0x0e, 0x6c, 0x11, 0x4c, 0xfd, 0xc7, 0x39, + 0x28, 0x45, 0x93, 0xf5, 0xa6, 0xc1, 0xbc, 0x07, 0xd5, 0x91, 0xe7, 0xba, 0x16, 0xc9, 0xe4, 0x78, + 0x3c, 0x2b, 0x31, 0x90, 0x7c, 0xbe, 0x59, 0x82, 0x48, 0xbe, 0x68, 0xe0, 0xef, 0x96, 0xb6, 0x62, + 0xcc, 0x0b, 0xf1, 0xb6, 0xe1, 0x26, 0x14, 0x71, 0x31, 0x9e, 0x18, 0x81, 0x1c, 0xe6, 0x28, 0x8d, + 0x4b, 0x68, 0xe4, 0x39, 0x0e, 0xcf, 0x20, 0xc3, 0x75, 0xc4, 0x10, 0xf6, 0x84, 0x02, 0xb6, 0xd0, + 0xbb, 0xab, 0x0d, 0xe2, 0xff, 0x7a, 0x82, 0xfb, 0xf8, 0xd3, 0xab, 0x43, 0xde, 0x78, 0x4d, 0x12, + 0xb2, 0xaf, 0x40, 0x99, 0xcd, 0x83, 0x53, 0xcb, 0xd4, 0x67, 0xbe, 0x65, 0xd2, 0x1e, 0x23, 0x5e, + 0x67, 0x6c, 0x27, 0x32, 0x1f, 0x49, 0x9c, 0xb6, 0xc9, 0xa9, 0x23, 0x00, 0x7b, 0x17, 0x36, 0xe3, + 0x69, 0x98, 0x19, 0xe1, 0x29, 0xf7, 0x95, 0x29, 0x69, 0xb5, 0x08, 0x7c, 0x84, 0x50, 0xf6, 0x29, + 0x5c, 0xf3, 0xad, 0xc0, 0x36, 0xe7, 0x86, 0xa3, 0xa7, 0x27, 0x82, 0x07, 0xff, 0xd8, 0x96, 0xd8, + 0xbd, 0xc4, 0x84, 0x60, 0xf1, 0x53, 0xe3, 0x82, 0x0c, 0x71, 0x8e, 0x63, 0x39, 0x76, 0x30, 0xa5, + 0x79, 0xcb, 0x6b, 0xb5, 0xa9, 0x71, 0x71, 0x14, 0x43, 0xc9, 0x55, 0x6e, 0xe6, 0xd8, 0x0b, 0xaf, + 0xe4, 0xf9, 0x5c, 0x22, 0x5c, 0xe3, 0x68, 0xa6, 0x42, 0x15, 0x0b, 0xa4, 0x33, 0x67, 0xe4, 0xfd, + 0x92, 0xd5, 0xca, 0x53, 0x83, 0x8c, 0xb3, 0x74, 0x4b, 0x79, 0x1f, 0x6a, 0x11, 0x0d, 0x77, 0x3d, + 0x10, 0xb7, 0xff, 0x82, 0x88, 0x7b, 0x1f, 0x50, 0xd3, 0x38, 0x77, 0xc8, 0x69, 0xad, 0xf1, 0x37, + 0x04, 0x02, 0x2c, 0xe7, 0xf4, 0x06, 0x70, 0x73, 0x36, 0xb2, 0xc8, 0x26, 0x51, 0x14, 0x28, 0xdd, + 0x31, 0xd5, 0x7f, 0x31, 0x03, 0x6c, 0x79, 0x7a, 0x5e, 0xf7, 0x1a, 0x0e, 0x87, 0x57, 0x3e, 0xe5, + 0xc1, 0xdf, 0xec, 0x3d, 0x28, 0x4c, 0x3d, 0x2e, 0x32, 0xb3, 0xaf, 0x79, 0x9b, 0xbd, 0x31, 0xf5, + 0x48, 0x84, 0xbe, 0x0b, 0x9b, 0x23, 0xcf, 0x15, 0x0d, 0xe5, 0x2b, 0x8a, 0xf3, 0x57, 0x2d, 0x06, + 0xe3, 0xba, 0x52, 0xff, 0xa3, 0x0c, 0xd4, 0xd2, 0x93, 0xce, 0x1e, 0x50, 0xac, 0x9c, 0x54, 0xb4, + 0x9d, 0x34, 0x45, 0x7f, 0x46, 0x31, 0x74, 0x56, 0x35, 0xf1, 0x6d, 0x00, 0x92, 0x56, 0xfa, 0x49, + 0x20, 0xf8, 0xbe, 0xa2, 0x95, 0x08, 0xb2, 0x1b, 0x78, 0x74, 0x6b, 0xcb, 0xc3, 0xa1, 0x71, 0x7c, + 0x6e, 0x27, 0x8b, 0xfb, 0x06, 0x07, 0x11, 0xc1, 0xc7, 0x89, 0x9b, 0x26, 0x7e, 0x93, 0xb4, 0x9a, + 0x31, 0x23, 0x2a, 0xf5, 0x2f, 0x32, 0x00, 0xf1, 0xbc, 0xe3, 0xe8, 0x9f, 0x59, 0x97, 0xc4, 0x9a, + 0x62, 0x3c, 0x0b, 0x67, 0xd6, 0xe5, 0x91, 0x68, 0x9b, 0xb8, 0xa5, 0x0c, 0x84, 0x03, 0x6e, 0x45, + 0x2b, 0xf1, 0x8b, 0xc9, 0x80, 0x3f, 0xa7, 0x14, 0xf7, 0x92, 0x89, 0xa6, 0xf3, 0xab, 0xc8, 0x80, + 0x9e, 0x21, 0x6d, 0xf2, 0xdc, 0xf4, 0xba, 0x11, 0x4f, 0x79, 0xe2, 0xe1, 0x28, 0xbf, 0x47, 0xed, + 0x48, 0x28, 0x12, 0xf2, 0x72, 0x62, 0x42, 0xee, 0x11, 0xc7, 0x6f, 0x4d, 0x23, 0x42, 0xd5, 0x91, + 0x9b, 0x7a, 0x23, 0x0c, 0xe9, 0x49, 0x78, 0x64, 0x02, 0xc8, 0xc8, 0xd7, 0xa2, 0xfc, 0xf4, 0xff, + 0x16, 0x39, 0x0e, 0x8b, 0xe7, 0x37, 0x62, 0x6f, 0x8f, 0x9e, 0xd5, 0x3c, 0xc0, 0x99, 0x76, 0xa4, + 0x48, 0x24, 0x12, 0xfe, 0x4c, 0xb8, 0x3a, 0xf2, 0x1c, 0x2e, 0x0e, 0x11, 0xa8, 0xfe, 0xab, 0x79, + 0x80, 0xd8, 0xf8, 0x9b, 0xe2, 0xd2, 0x4c, 0x8a, 0x4b, 0xd9, 0x13, 0xb8, 0x26, 0xde, 0xbb, 0x47, + 0x1e, 0x89, 0xb6, 0xab, 0x9f, 0x18, 0xd2, 0x03, 0x9a, 0x09, 0x2c, 0xf7, 0x35, 0xeb, 0xb8, 0xbb, + 0x46, 0xc8, 0x9e, 0xa1, 0x5c, 0x88, 0xf3, 0x84, 0x97, 0xb3, 0xd7, 0xb2, 0x68, 0x35, 0xce, 0x3e, + 0xbc, 0x9c, 0xb1, 0x8f, 0xe1, 0xaa, 0x6f, 0x8d, 0x7d, 0x2b, 0x38, 0xd5, 0xc3, 0x20, 0x59, 0x19, + 0x7f, 0xa2, 0xb0, 0x25, 0x90, 0xc3, 0x20, 0xaa, 0xeb, 0x63, 0xb8, 0x2a, 0x24, 0xca, 0x42, 0xf3, + 0xf8, 0xed, 0xea, 0x16, 0x47, 0x26, 0x5b, 0x47, 0x33, 0x4f, 0x16, 0x71, 0x19, 0xb6, 0xaf, 0x88, + 0x33, 0x8f, 0x83, 0x21, 0x02, 0xd4, 0x90, 0x59, 0x9b, 0x44, 0x53, 0x51, 0xe3, 0x09, 0xa6, 0x42, + 0x0e, 0x57, 0x08, 0x09, 0xa0, 0xda, 0x93, 0xda, 0x63, 0x0a, 0x4b, 0x48, 0xc1, 0x85, 0x3c, 0xd3, + 0xd2, 0x08, 0xc7, 0x3e, 0xc4, 0x5d, 0x29, 0xee, 0xb6, 0x8c, 0xac, 0xc5, 0x9d, 0xf2, 0x94, 0xb8, + 0xa3, 0x1a, 0x8f, 0xb1, 0xf5, 0x3e, 0xb0, 0x44, 0xcb, 0x25, 0x75, 0x85, 0xa8, 0x37, 0xa3, 0x66, + 0x0b, 0xe2, 0x77, 0x81, 0x9a, 0x18, 0xfb, 0xdf, 0x2d, 0xd8, 0x80, 0x11, 0x29, 0x7c, 0xf6, 0xae, + 0xc6, 0xbd, 0xd3, 0x8d, 0x50, 0x0f, 0x4f, 0x2d, 0xdd, 0x72, 0xa5, 0x03, 0xde, 0x56, 0xd4, 0xd1, + 0x46, 0x38, 0x3c, 0xb5, 0xda, 0xae, 0x99, 0xbc, 0x65, 0xdb, 0xfc, 0xe1, 0x5b, 0xb6, 0xcf, 0xa1, + 0x9e, 0xb6, 0xb3, 0x24, 0x86, 0x9b, 0x07, 0xf9, 0xd8, 0x4e, 0x3a, 0x36, 0x46, 0x23, 0xfe, 0x08, + 0xb6, 0x4e, 0x8d, 0x20, 0x6d, 0xa3, 0xa1, 0xcb, 0xbf, 0xa2, 0xb6, 0x79, 0x6a, 0x04, 0x49, 0xc3, + 0x8c, 0xfa, 0x77, 0x33, 0x50, 0x4b, 0x9b, 0xc3, 0xf9, 0xcb, 0x69, 0xbe, 0xb7, 0x65, 0x68, 0x87, + 0x8f, 0x76, 0xb0, 0xb7, 0xa0, 0xc4, 0xbd, 0x1f, 0xe7, 0x53, 0x57, 0xae, 0x85, 0xd9, 0x19, 0x97, + 0xa7, 0x28, 0x20, 0x67, 0x67, 0x6f, 0x10, 0x90, 0x33, 0xfe, 0x6c, 0xec, 0x3d, 0x28, 0xcc, 0xcf, + 0xe2, 0xf0, 0x3d, 0x2b, 0x49, 0xe7, 0x44, 0xaa, 0xfe, 0x97, 0xeb, 0x50, 0x49, 0xde, 0xe2, 0xfc, + 0x18, 0xef, 0xc3, 0x9f, 0xe4, 0xb1, 0xba, 0x43, 0x0f, 0x2b, 0x74, 0x7a, 0x97, 0x85, 0xe3, 0xc4, + 0x5d, 0x0f, 0xe1, 0xd4, 0x08, 0x1a, 0xf3, 0x10, 0xf7, 0x0a, 0x52, 0xe4, 0x3c, 0x47, 0xbe, 0x5d, + 0xe3, 0x2b, 0x03, 0x65, 0x82, 0x78, 0xb6, 0xf6, 0xb1, 0x78, 0x1a, 0x4b, 0xcf, 0xea, 0xe9, 0x0d, + 0x42, 0x7e, 0x89, 0x5f, 0x2a, 0xf2, 0x55, 0x3d, 0xbd, 0xb9, 0x78, 0x02, 0x9b, 0xf1, 0x43, 0x44, + 0x9e, 0x65, 0x63, 0x29, 0x4b, 0x35, 0x7a, 0x85, 0x28, 0x42, 0xfe, 0x54, 0xed, 0x40, 0xf7, 0x1c, + 0x53, 0x3e, 0x88, 0x2e, 0xc8, 0x3b, 0xf6, 0xbe, 0x63, 0x8a, 0x58, 0x0e, 0x9c, 0xc6, 0xb5, 0xce, + 0x25, 0x4d, 0x74, 0x0f, 0xdf, 0xb3, 0xce, 0xc5, 0xc3, 0xe8, 0xff, 0x38, 0x0b, 0x5b, 0x4b, 0x17, + 0x37, 0xa8, 0x58, 0xc6, 0xe1, 0x30, 0xf1, 0x27, 0xbb, 0x0b, 0x95, 0xa9, 0x11, 0x8e, 0x4e, 0x51, + 0x57, 0x19, 0xdb, 0x17, 0x32, 0xa6, 0x27, 0xc1, 0x8e, 0x08, 0x84, 0xfb, 0x09, 0x97, 0xb5, 0xfc, + 0x6a, 0x9b, 0x0b, 0x3e, 0x2e, 0xc6, 0xbb, 0x74, 0xa7, 0x2d, 0xdf, 0x64, 0xe4, 0x5e, 0xf3, 0x26, + 0xe3, 0x26, 0x94, 0x5c, 0x8f, 0xfc, 0x6f, 0x67, 0x67, 0x42, 0x4c, 0x17, 0x5c, 0x2f, 0xec, 0xbb, + 0x47, 0x67, 0xec, 0x09, 0x5c, 0x9d, 0x07, 0xe4, 0x4b, 0x76, 0x62, 0xf9, 0xc1, 0xa9, 0x1d, 0x99, + 0x50, 0xb9, 0x00, 0xb9, 0x32, 0x0f, 0xac, 0xc3, 0x08, 0x27, 0x2c, 0xa9, 0x0d, 0xa8, 0xd0, 0x1c, + 0xb8, 0x23, 0x8f, 0x2e, 0x65, 0x0a, 0x24, 0x3c, 0x6e, 0xaf, 0xb8, 0xad, 0x7a, 0x6e, 0x5d, 0xb6, + 0x05, 0x95, 0x56, 0x3e, 0x8b, 0x13, 0xec, 0x3d, 0x7a, 0x6e, 0x77, 0x62, 0xc5, 0x67, 0xa3, 0x14, + 0x73, 0x6a, 0x25, 0xc2, 0x12, 0x13, 0x3f, 0x87, 0x1b, 0xfc, 0x2d, 0xf4, 0x74, 0xe6, 0xb9, 0x96, + 0x1b, 0xea, 0x71, 0xc6, 0x20, 0xed, 0xdf, 0x90, 0x60, 0xeb, 0x6b, 0xf4, 0x36, 0x5a, 0xe4, 0x38, + 0x92, 0x65, 0x05, 0x58, 0x2f, 0x37, 0x50, 0xd2, 0x80, 0xc1, 0xf2, 0x2d, 0x11, 0x61, 0xf1, 0xa7, + 0x7a, 0x0b, 0x36, 0x3a, 0xd1, 0xb5, 0x5a, 0xe4, 0xea, 0x9e, 0x15, 0xe1, 0xfe, 0x3c, 0x28, 0x71, + 0x7b, 0xeb, 0xa1, 0x31, 0x63, 0x8f, 0x20, 0x3b, 0x35, 0x66, 0xc2, 0x4d, 0xa7, 0x1e, 0xf9, 0x32, + 0x71, 0xec, 0xe3, 0x43, 0x63, 0xc6, 0x4f, 0x65, 0x48, 0x74, 0xf3, 0x73, 0x28, 0x4a, 0xc0, 0x4f, + 0x7b, 0x20, 0xb8, 0x0e, 0xa5, 0x56, 0xf2, 0x5a, 0x1c, 0x35, 0xb9, 0xd0, 0x9f, 0xbb, 0xa4, 0xdf, + 0x8a, 0xc0, 0x66, 0x23, 0xc3, 0x1d, 0x0a, 0x90, 0x5c, 0xc0, 0xeb, 0x3f, 0xb0, 0x80, 0x6f, 0x01, + 0x70, 0x37, 0x66, 0xba, 0x58, 0xca, 0x46, 0x4f, 0x7f, 0x3a, 0x66, 0xc7, 0xbc, 0x58, 0xed, 0x5c, + 0x9c, 0xfb, 0xf1, 0xce, 0xc5, 0xf9, 0x95, 0xce, 0xc5, 0x0f, 0xe2, 0x4d, 0x14, 0xa7, 0x15, 0x2b, + 0x2e, 0xf1, 0xad, 0x7c, 0x16, 0x3d, 0x77, 0xc6, 0xda, 0x7f, 0x01, 0x35, 0xd9, 0x3b, 0x51, 0x1e, + 0xa4, 0x5e, 0x58, 0x0b, 0x1c, 0xbf, 0x47, 0xaf, 0x86, 0xc9, 0x64, 0x5a, 0x30, 0x95, 0xdf, 0xe0, + 0xc0, 0xfc, 0xaf, 0x65, 0x80, 0x89, 0x5b, 0x90, 0xbd, 0xb9, 0xe3, 0x0c, 0xad, 0x0b, 0x92, 0x7f, + 0x8f, 0x60, 0x4b, 0x5c, 0xf3, 0x27, 0x62, 0x64, 0x08, 0xc7, 0x36, 0x8e, 0x88, 0x1d, 0xdb, 0x56, + 0x85, 0xd3, 0x58, 0x5f, 0x19, 0x4e, 0x63, 0x75, 0x98, 0x8e, 0x3b, 0x50, 0x4e, 0x06, 0xa3, 0xe0, + 0x4a, 0x2c, 0x18, 0x51, 0x1c, 0x0a, 0xf5, 0x7f, 0x58, 0x07, 0x88, 0x6f, 0x6a, 0xfe, 0xd0, 0x9e, + 0xe1, 0x2b, 0xa6, 0x24, 0xbb, 0x6a, 0x4a, 0x1e, 0x82, 0x92, 0xa4, 0x4b, 0x44, 0x45, 0xa9, 0xc5, + 0x84, 0x52, 0x99, 0xb3, 0x83, 0x64, 0x38, 0x0a, 0x7a, 0x91, 0x2a, 0x9c, 0x69, 0x39, 0x92, 0x5f, + 0x1b, 0x0b, 0x31, 0x53, 0xb4, 0x03, 0xbe, 0xf3, 0xb0, 0x2f, 0xe1, 0x46, 0x94, 0x53, 0x3f, 0xb7, + 0xc3, 0x53, 0x6f, 0x1e, 0x0a, 0x91, 0x14, 0x08, 0x59, 0x7c, 0x4d, 0x96, 0xf4, 0x92, 0xa3, 0xb9, + 0xa8, 0x09, 0xd8, 0x67, 0x50, 0x1a, 0xcf, 0x1d, 0x47, 0x0f, 0xad, 0x8b, 0x50, 0x88, 0x94, 0x7a, + 0xea, 0x92, 0x2b, 0x31, 0xbd, 0x5a, 0x71, 0x2c, 0x12, 0xea, 0x3f, 0x9f, 0x87, 0xfc, 0xaf, 0xe7, + 0x96, 0x7f, 0xc9, 0x3e, 0x87, 0x52, 0x10, 0x4e, 0xc3, 0xa4, 0xbf, 0x99, 0xb8, 0xbc, 0x20, 0x3c, + 0xb9, 0x8b, 0x59, 0x53, 0xcb, 0x0d, 0xf9, 0xed, 0x2f, 0xd2, 0x92, 0x84, 0xda, 0x86, 0x7c, 0x10, + 0x5a, 0xb3, 0x40, 0x3c, 0x67, 0xe1, 0x09, 0xb6, 0x03, 0x79, 0xd7, 0x33, 0xad, 0x20, 0xfd, 0x68, + 0xa5, 0x87, 0x7a, 0x15, 0x47, 0x30, 0x15, 0x36, 0xa2, 0x19, 0x5f, 0xf2, 0xf9, 0xe2, 0x18, 0x7a, + 0x0a, 0x6b, 0x19, 0x28, 0x33, 0x65, 0x94, 0x99, 0x28, 0x8d, 0x0a, 0x04, 0x59, 0xbf, 0x8c, 0x89, + 0x8c, 0x4e, 0x25, 0x92, 0x6c, 0x07, 0xca, 0xf8, 0xf3, 0xa5, 0x6f, 0x87, 0xd6, 0xe0, 0xa9, 0xdc, + 0xc3, 0x12, 0x20, 0x3c, 0x78, 0x9b, 0x56, 0x68, 0x8d, 0xc2, 0xc1, 0xf7, 0x8e, 0x3c, 0xde, 0x26, + 0x20, 0xec, 0x17, 0xc0, 0x4e, 0x8c, 0xd1, 0xd9, 0xc4, 0x27, 0x3f, 0xc9, 0xef, 0xe7, 0x96, 0x6f, + 0x47, 0xe2, 0xb6, 0x9c, 0x18, 0x14, 0x6d, 0x2b, 0x26, 0xfb, 0x35, 0xa7, 0x62, 0xd7, 0x60, 0x63, + 0x6a, 0x5c, 0xb4, 0xbc, 0x99, 0x70, 0x60, 0x17, 0x29, 0xf6, 0x14, 0xae, 0xa1, 0x0a, 0x20, 0x63, + 0x99, 0x20, 0x0f, 0x89, 0x7b, 0x45, 0x1e, 0xd8, 0xf2, 0xca, 0xa9, 0x11, 0xc4, 0xf1, 0x09, 0x84, + 0x5d, 0x78, 0x17, 0xb6, 0xa5, 0x79, 0xc7, 0xb4, 0x66, 0x96, 0x6b, 0x5a, 0xee, 0xc8, 0x8e, 0xa2, + 0x1f, 0x2c, 0x31, 0xff, 0x15, 0x41, 0xdc, 0x4a, 0xd0, 0xb2, 0x7b, 0x50, 0xc5, 0x8a, 0x7d, 0x2b, + 0x9c, 0xfb, 0x2e, 0xee, 0x58, 0xfc, 0xa5, 0x07, 0x2a, 0x24, 0x9a, 0x84, 0x71, 0x47, 0x09, 0x91, + 0xe0, 0xae, 0x3d, 0x3c, 0xfe, 0x55, 0x35, 0x82, 0x0e, 0x42, 0x6b, 0xa6, 0xfe, 0x09, 0x54, 0x53, + 0x7c, 0xb0, 0x74, 0x4f, 0x35, 0x68, 0x77, 0xdb, 0xcd, 0x21, 0xb7, 0x5d, 0x8b, 0x0b, 0x95, 0xf5, + 0xc4, 0xcd, 0x4b, 0x2e, 0x61, 0xd3, 0xce, 0xd3, 0xbd, 0x4d, 0x5b, 0xdb, 0x6f, 0xd3, 0xe5, 0x42, + 0x56, 0xc9, 0xaa, 0xff, 0xfa, 0x3a, 0x6c, 0x0d, 0x7d, 0xc3, 0x0d, 0x0c, 0xae, 0x39, 0xba, 0xa1, + 0xef, 0x39, 0xec, 0x17, 0x50, 0x0c, 0x47, 0x4e, 0x92, 0x31, 0xef, 0x48, 0x31, 0xb8, 0x40, 0xfa, + 0x78, 0x38, 0xe2, 0xce, 0x09, 0x85, 0x90, 0xff, 0x60, 0x1f, 0x42, 0xfe, 0xc4, 0x9a, 0xd8, 0xae, + 0xd8, 0x09, 0xae, 0x2e, 0x66, 0xdc, 0x45, 0xe4, 0xc1, 0x9a, 0xc6, 0xa9, 0xd8, 0xc7, 0xb0, 0x31, + 0xf2, 0xa6, 0x52, 0xd1, 0x88, 0x23, 0x27, 0x24, 0x2a, 0x42, 0xec, 0xc1, 0x9a, 0x26, 0xe8, 0xd8, + 0xe7, 0x50, 0xf4, 0x3d, 0xc7, 0x41, 0x3e, 0x10, 0x2a, 0x48, 0x7d, 0x31, 0x8f, 0x26, 0xf0, 0x07, + 0x6b, 0x5a, 0x44, 0xab, 0x3e, 0x86, 0x82, 0x68, 0x2c, 0x0e, 0xc3, 0x6e, 0x7b, 0xbf, 0x23, 0x46, + 0xb0, 0xd9, 0x3f, 0x3c, 0xec, 0x0c, 0x79, 0xd4, 0x18, 0xad, 0xdf, 0xed, 0xee, 0x36, 0x9a, 0xcf, + 0x95, 0xf5, 0xdd, 0x22, 0x6c, 0x70, 0x76, 0x51, 0xff, 0x34, 0x03, 0x9b, 0x0b, 0x1d, 0x60, 0xcf, + 0x20, 0x47, 0x16, 0x00, 0x3e, 0x3c, 0xf7, 0x57, 0xf6, 0x32, 0x91, 0xe6, 0xe7, 0x1b, 0xcc, 0xa1, + 0x7e, 0x09, 0xb5, 0x34, 0x3c, 0x71, 0x33, 0x52, 0x85, 0x92, 0xd6, 0x6e, 0xb4, 0xf4, 0x7e, 0xaf, + 0xfb, 0x2d, 0xbf, 0x6a, 0xa4, 0xe4, 0x4b, 0xad, 0x43, 0x57, 0x12, 0x7f, 0x13, 0x94, 0xc5, 0x81, + 0x61, 0xfb, 0x78, 0x56, 0x9d, 0xce, 0x1c, 0x8b, 0x8e, 0x04, 0x89, 0x29, 0xbb, 0xbd, 0x62, 0x24, + 0x05, 0x19, 0x77, 0x38, 0x1e, 0xa5, 0xd2, 0xea, 0x9f, 0x00, 0x5b, 0x1e, 0xc1, 0x3f, 0x5c, 0xf1, + 0xff, 0x77, 0x06, 0x72, 0x47, 0x8e, 0xe1, 0xb2, 0x7b, 0x90, 0xa7, 0x18, 0x8e, 0x62, 0x3f, 0x49, + 0xae, 0x6e, 0x64, 0x0b, 0xc2, 0xb1, 0xf7, 0x21, 0x1b, 0x8e, 0x64, 0x34, 0x9a, 0xeb, 0xaf, 0x61, + 0xbe, 0x83, 0x35, 0x0d, 0xa9, 0xd8, 0x43, 0xc8, 0x9a, 0xa6, 0x7c, 0x18, 0x29, 0x6c, 0x1b, 0x2d, + 0x23, 0x34, 0x5a, 0xd6, 0xd8, 0x76, 0x6d, 0x11, 0x73, 0x12, 0x49, 0xd8, 0x3b, 0x90, 0x35, 0x47, + 0x4e, 0xfa, 0x95, 0x2b, 0x37, 0x1c, 0x47, 0x05, 0x9a, 0x23, 0x07, 0x35, 0xee, 0xd0, 0xbf, 0xd4, + 0xfd, 0xb9, 0x4b, 0x2f, 0x57, 0x02, 0x71, 0x0a, 0x2e, 0xa3, 0x56, 0x35, 0xa7, 0xe7, 0x2f, 0x81, + 0x08, 0x6b, 0x31, 0xf3, 0xad, 0x99, 0xe1, 0x47, 0xe7, 0x5f, 0x3b, 0x38, 0xe2, 0x80, 0xdd, 0x0d, + 0xa0, 0x40, 0xfd, 0xea, 0x07, 0x14, 0x60, 0x10, 0x0f, 0x52, 0xaa, 0xfc, 0xb5, 0x22, 0xa6, 0xb3, + 0xc0, 0xa8, 0xff, 0x28, 0x0b, 0xe5, 0x44, 0x7b, 0xd8, 0xa7, 0x50, 0x34, 0xd3, 0x0b, 0xf1, 0xc6, + 0x52, 0xa3, 0x1f, 0xb7, 0xe4, 0x12, 0x34, 0x05, 0x7b, 0x93, 0xe7, 0x4b, 0xa8, 0xbf, 0x32, 0x7c, + 0x9b, 0x07, 0xae, 0x5d, 0x4f, 0xba, 0xa0, 0x0c, 0xac, 0xf0, 0x85, 0xc4, 0x1c, 0xac, 0x69, 0x95, + 0x20, 0x91, 0xa6, 0xd3, 0x9e, 0xe8, 0x52, 0x36, 0x15, 0x2c, 0x98, 0x03, 0x0f, 0xd6, 0x34, 0x89, + 0x47, 0x52, 0xeb, 0xc2, 0x1a, 0xcd, 0x43, 0x79, 0xda, 0xab, 0xca, 0x0e, 0x11, 0x90, 0x22, 0x96, + 0xf3, 0x9f, 0xec, 0x09, 0x4a, 0x7f, 0xc3, 0x71, 0x3c, 0x52, 0x1e, 0xf3, 0x49, 0xf3, 0x62, 0x2b, + 0x82, 0xf3, 0x08, 0xe9, 0x32, 0xc5, 0x1e, 0x40, 0xde, 0x0b, 0x4f, 0x2d, 0x79, 0x86, 0x92, 0xa1, + 0x0a, 0x11, 0xd4, 0x6a, 0x76, 0x91, 0x53, 0x08, 0xad, 0xfe, 0x59, 0x06, 0x0a, 0x62, 0x04, 0xd8, + 0x16, 0x54, 0x07, 0xed, 0xa1, 0xfe, 0xa2, 0xa1, 0x75, 0x1a, 0xbb, 0xdd, 0xb6, 0x78, 0x9c, 0xbb, + 0xaf, 0x35, 0x7a, 0x42, 0x40, 0x6a, 0xed, 0x17, 0xfd, 0xe7, 0x6d, 0x7e, 0xdd, 0xd8, 0x6a, 0xf7, + 0xbe, 0x55, 0xb2, 0xfc, 0xba, 0xbd, 0x7d, 0xd4, 0xd0, 0x50, 0x56, 0x96, 0xa1, 0xd0, 0xfe, 0xa6, + 0xdd, 0x3c, 0x26, 0x61, 0x59, 0x03, 0x68, 0xb5, 0x1b, 0xdd, 0x6e, 0xbf, 0x89, 0xc2, 0x73, 0x83, + 0x31, 0xa8, 0x35, 0xb5, 0x76, 0x63, 0xd8, 0xd6, 0x1b, 0xcd, 0x66, 0xff, 0xb8, 0x37, 0x54, 0x0a, + 0x58, 0x63, 0xa3, 0x3b, 0x6c, 0x6b, 0x11, 0x88, 0xc2, 0xc7, 0xb6, 0xb4, 0xfe, 0x51, 0x04, 0x29, + 0xed, 0x96, 0xf0, 0xe4, 0x4d, 0x73, 0xa5, 0xfe, 0x87, 0x5b, 0x50, 0x4b, 0xb3, 0x26, 0xfb, 0x02, + 0x8a, 0xa6, 0x99, 0x9a, 0xe3, 0x5b, 0xab, 0x58, 0xf8, 0x71, 0xcb, 0x94, 0xd3, 0xcc, 0x7f, 0xb0, + 0xbb, 0x72, 0x21, 0xad, 0x2f, 0x2d, 0x24, 0xb9, 0x8c, 0xbe, 0x82, 0x4d, 0x11, 0x3f, 0x2f, 0x32, + 0x89, 0xa7, 0x56, 0x49, 0x93, 0x90, 0x2d, 0x81, 0x3b, 0x58, 0xd3, 0x6a, 0xa3, 0x14, 0x84, 0xfd, + 0x12, 0x6a, 0x06, 0x37, 0x34, 0x27, 0x4d, 0xea, 0x91, 0x5a, 0xdc, 0x20, 0x3b, 0x73, 0x9c, 0xbd, + 0x6a, 0x24, 0x01, 0xc8, 0x88, 0xa6, 0xef, 0xcd, 0xe2, 0xcc, 0xf9, 0x94, 0x2f, 0x94, 0xef, 0xcd, + 0x12, 0x79, 0x2b, 0x66, 0x22, 0xcd, 0x3e, 0x87, 0x8a, 0x68, 0x79, 0x6c, 0x60, 0x8a, 0x96, 0x2c, + 0x6f, 0x36, 0xa9, 0xb9, 0x07, 0x6b, 0x5a, 0x79, 0x14, 0x27, 0xd9, 0x53, 0xd4, 0x6d, 0xe3, 0x43, + 0x41, 0x21, 0xc9, 0x6b, 0xd4, 0x5a, 0x99, 0x0b, 0x8c, 0x28, 0xc5, 0x3e, 0x06, 0xa0, 0x76, 0xf2, + 0x3c, 0xc5, 0x94, 0x97, 0xb0, 0xef, 0xcd, 0x64, 0x96, 0x92, 0x29, 0x13, 0x89, 0xe6, 0x71, 0xf3, + 0x60, 0x69, 0xb9, 0x79, 0x64, 0x22, 0x8c, 0x9b, 0xc7, 0x2d, 0x8b, 0x51, 0xf3, 0x78, 0x36, 0x58, + 0x6a, 0x9e, 0xcc, 0xc5, 0x9b, 0xc7, 0x33, 0xc9, 0xe6, 0xf1, 0x3c, 0xe5, 0xc5, 0xe6, 0xc9, 0x2c, + 0xd4, 0x3c, 0x9e, 0xe3, 0x97, 0x4b, 0xa7, 0x99, 0xca, 0x6b, 0x4f, 0x33, 0x38, 0x6d, 0xe9, 0xf3, + 0xcc, 0x2f, 0xa1, 0x16, 0x9c, 0x7a, 0xe7, 0x09, 0x01, 0x52, 0x4d, 0xe6, 0x1e, 0x9c, 0x7a, 0xe7, + 0x49, 0x09, 0x52, 0x0d, 0x92, 0x00, 0x6c, 0x2d, 0xef, 0x22, 0xf9, 0x2d, 0xd5, 0x92, 0xad, 0xa5, + 0x1e, 0xbe, 0xb0, 0xad, 0x73, 0x6c, 0xad, 0x21, 0x13, 0x38, 0x28, 0xb1, 0xb1, 0x2d, 0x10, 0xe6, + 0xb3, 0x94, 0x6f, 0xad, 0xa8, 0x09, 0x22, 0xb3, 0x5b, 0x80, 0xbc, 0x35, 0x77, 0x93, 0xd9, 0x94, + 0x24, 0x6f, 0x1d, 0xbb, 0xa9, 0x8c, 0x15, 0x4e, 0x2a, 0xb2, 0xc6, 0xab, 0x22, 0xb0, 0xbe, 0x9f, + 0x5b, 0xee, 0xc8, 0x12, 0x3e, 0xf4, 0xa9, 0x55, 0x31, 0x10, 0xb8, 0x78, 0x55, 0x48, 0x48, 0xc4, + 0xd7, 0x51, 0x76, 0xb6, 0xc8, 0xd7, 0x89, 0xcc, 0xc4, 0xd7, 0x51, 0xd6, 0x68, 0x41, 0x45, 0x79, + 0xaf, 0x2c, 0x2d, 0xa8, 0x44, 0x66, 0xbe, 0xa0, 0xa2, 0xdc, 0x4f, 0x41, 0x70, 0x13, 0x1f, 0xdc, + 0x94, 0xa7, 0x3d, 0x6f, 0xb5, 0x18, 0x5d, 0x18, 0x45, 0x29, 0xe4, 0x55, 0xdf, 0xc2, 0xd3, 0x93, + 0x60, 0x85, 0xab, 0x49, 0x5e, 0xd5, 0x08, 0x13, 0x2d, 0x25, 0x3f, 0x4e, 0x26, 0x2a, 0x9b, 0xd9, + 0xa1, 0x5f, 0x37, 0x97, 0x2b, 0x3b, 0xb2, 0x43, 0x3f, 0xae, 0x0c, 0x53, 0xec, 0x43, 0x20, 0x36, + 0xe4, 0x59, 0xac, 0xa4, 0xe8, 0xc6, 0x61, 0x11, 0x19, 0x8a, 0xa6, 0xf8, 0x8d, 0xcc, 0x22, 0xea, + 0x18, 0x99, 0xa3, 0xfa, 0x38, 0xc9, 0x2c, 0xbc, 0x8a, 0x66, 0xab, 0x89, 0xcc, 0xc2, 0x89, 0x9a, + 0xe6, 0x88, 0x3d, 0x02, 0xca, 0x4d, 0xf4, 0x93, 0x54, 0x28, 0x5c, 0xdf, 0x9b, 0x71, 0xea, 0x02, + 0x12, 0x20, 0x2d, 0xf6, 0xc0, 0xf1, 0x5c, 0xd9, 0xf1, 0xd3, 0x54, 0x0f, 0x10, 0x11, 0x09, 0x83, + 0x51, 0x94, 0x52, 0xff, 0xb9, 0x0d, 0x28, 0x08, 0x59, 0xcb, 0xae, 0xc0, 0xa6, 0x10, 0xf9, 0xad, + 0xc6, 0xb0, 0xb1, 0xdb, 0x18, 0xa0, 0x92, 0xc6, 0xa0, 0xc6, 0x65, 0x7e, 0x04, 0xcb, 0xe0, 0x3e, + 0x40, 0x42, 0x3f, 0x02, 0xad, 0xe3, 0x3e, 0x20, 0xf2, 0x72, 0xa7, 0x8e, 0x2c, 0xdb, 0x84, 0x32, + 0xcf, 0xc8, 0x01, 0x14, 0x2b, 0x84, 0x72, 0xf1, 0x74, 0x3e, 0x91, 0x85, 0x7b, 0xdf, 0x6c, 0xc4, + 0x59, 0x38, 0xa0, 0x10, 0x65, 0x91, 0xee, 0x39, 0x0c, 0x6a, 0x43, 0xed, 0xb8, 0xd7, 0x8c, 0xeb, + 0x29, 0x51, 0x7c, 0x07, 0x5e, 0xcc, 0x8b, 0x4e, 0xfb, 0xa5, 0x02, 0x98, 0x89, 0x97, 0x42, 0xe9, + 0x32, 0xaa, 0x99, 0x54, 0x08, 0x25, 0x2b, 0xec, 0x3a, 0x5c, 0x19, 0x1c, 0xf4, 0x5f, 0xea, 0x3c, + 0x53, 0xd4, 0x85, 0x2a, 0xdb, 0x06, 0x25, 0x81, 0xe0, 0xc5, 0xd7, 0xb0, 0x4a, 0x82, 0x4a, 0xc2, + 0x81, 0xb2, 0x49, 0x21, 0x16, 0x11, 0x36, 0xe4, 0xfb, 0xae, 0x82, 0x5d, 0xe1, 0x59, 0xfb, 0xdd, + 0xe3, 0xc3, 0xde, 0x40, 0xd9, 0xc2, 0x46, 0x10, 0x84, 0xb7, 0x9c, 0x45, 0xc5, 0xc4, 0xbb, 0xf5, + 0x15, 0xda, 0xc0, 0x11, 0xf6, 0xb2, 0xa1, 0xf5, 0x3a, 0xbd, 0xfd, 0x81, 0xb2, 0x1d, 0x95, 0xdc, + 0xd6, 0xb4, 0xbe, 0x36, 0x50, 0xae, 0x46, 0x80, 0xc1, 0xb0, 0x31, 0x3c, 0x1e, 0x28, 0xd7, 0xa2, + 0x56, 0x1e, 0x69, 0xfd, 0x66, 0x7b, 0x30, 0xe8, 0x76, 0x06, 0x43, 0xe5, 0x3a, 0xbb, 0x0a, 0x5b, + 0x71, 0x8b, 0x24, 0x71, 0x3d, 0xd1, 0x50, 0x6d, 0xbf, 0x3d, 0x54, 0x6e, 0x44, 0xcd, 0x68, 0xf6, + 0xbb, 0xdd, 0x06, 0x79, 0x0c, 0xdd, 0x44, 0x22, 0x72, 0x56, 0x13, 0xbd, 0x79, 0x0b, 0xdb, 0x75, + 0xdc, 0x4b, 0x82, 0x6e, 0x25, 0x58, 0x63, 0xd0, 0xfe, 0xf5, 0x71, 0xbb, 0xd7, 0x6c, 0x2b, 0x6f, + 0xc7, 0xac, 0x11, 0xc1, 0x6e, 0x47, 0xac, 0x11, 0x81, 0xee, 0x44, 0x75, 0x4a, 0xd0, 0x40, 0xd9, + 0x89, 0x06, 0xec, 0xf8, 0x68, 0x5f, 0x6b, 0xb4, 0xda, 0x8a, 0x8a, 0x10, 0xad, 0xdd, 0x6b, 0x1c, + 0xca, 0x89, 0xbd, 0x97, 0x98, 0xd8, 0xa3, 0xce, 0x50, 0x53, 0xee, 0x47, 0x13, 0x49, 0xc9, 0x77, + 0xd8, 0x5b, 0x70, 0x3d, 0xc9, 0x72, 0xfa, 0xcb, 0xce, 0xf0, 0x40, 0xf8, 0x94, 0x3d, 0xe0, 0x2e, + 0x4c, 0x84, 0x6c, 0xb6, 0x9a, 0xdc, 0x79, 0x8e, 0xf2, 0x62, 0xea, 0xa1, 0x9a, 0x2b, 0xde, 0x55, + 0xee, 0x3e, 0xda, 0x14, 0x43, 0xd1, 0xeb, 0xb5, 0x9b, 0xc3, 0xbe, 0x36, 0xd8, 0xad, 0xd0, 0x97, + 0x6c, 0x84, 0x0a, 0xa2, 0x7e, 0x0d, 0x2c, 0xf9, 0xa1, 0x06, 0xf1, 0x18, 0x89, 0x41, 0x6e, 0xec, + 0x7b, 0x53, 0x79, 0xd5, 0x8a, 0xbf, 0xd9, 0x0e, 0x94, 0x67, 0xf3, 0x13, 0xf2, 0xb8, 0x8a, 0x23, + 0xf3, 0x24, 0x41, 0xea, 0xbf, 0x93, 0x81, 0x5a, 0x5a, 0xfd, 0x20, 0x43, 0xf7, 0x58, 0x77, 0xbd, + 0x90, 0x47, 0x7f, 0x0d, 0xa2, 0xef, 0x27, 0x8c, 0x7b, 0x5e, 0x48, 0xe1, 0x5f, 0x83, 0xd4, 0xed, + 0xfe, 0xfa, 0xc2, 0xed, 0x7e, 0x07, 0xae, 0xa4, 0xbe, 0x8b, 0x91, 0x8a, 0xbd, 0x5b, 0x8f, 0x22, + 0xc8, 0x2f, 0xb4, 0x5f, 0x63, 0xc1, 0x72, 0x9f, 0x44, 0x7c, 0xa5, 0x5c, 0x1c, 0x5f, 0xe9, 0x00, + 0xaa, 0x29, 0x6d, 0x87, 0xec, 0x4a, 0xe3, 0x74, 0x4b, 0x8b, 0xf6, 0xf8, 0xcd, 0xcd, 0x54, 0xff, + 0xad, 0x0c, 0x54, 0x92, 0xba, 0xcf, 0xcf, 0x2e, 0x89, 0x7c, 0x84, 0xc5, 0x6f, 0xdd, 0x36, 0x65, + 0x28, 0x57, 0x09, 0xea, 0xd0, 0x17, 0xbc, 0xf8, 0x9d, 0xc1, 0xde, 0xd9, 0x20, 0xea, 0x4e, 0x12, + 0x44, 0x1e, 0x11, 0xa7, 0xd6, 0xe8, 0x6c, 0xef, 0x39, 0x12, 0x48, 0x8f, 0x88, 0x08, 0xa2, 0xde, + 0x81, 0xd2, 0xde, 0x99, 0x74, 0x99, 0x4e, 0xc6, 0x40, 0x2e, 0xf1, 0x70, 0x4e, 0xea, 0x5f, 0x64, + 0xa0, 0x16, 0x5b, 0x51, 0xc8, 0x01, 0x8d, 0x7f, 0x4f, 0x85, 0xb3, 0xc3, 0xba, 0x79, 0x12, 0x7b, + 0xbd, 0xac, 0x27, 0xbd, 0x5e, 0xee, 0x89, 0xc2, 0xb2, 0x49, 0xa1, 0x1f, 0xd5, 0x25, 0x82, 0x45, + 0x3d, 0x85, 0x0a, 0xfe, 0xd7, 0xac, 0xb1, 0xe5, 0xfb, 0x96, 0x99, 0x7e, 0x22, 0x1a, 0x13, 0xa7, + 0x88, 0xe8, 0x94, 0x17, 0xc5, 0x8c, 0x5b, 0x19, 0x88, 0x92, 0x02, 0xa4, 0xfe, 0x9f, 0x59, 0x28, + 0x27, 0x34, 0xc9, 0x1f, 0xc5, 0x7e, 0xb7, 0xa0, 0x14, 0x87, 0x45, 0x14, 0x11, 0x7a, 0x22, 0x40, + 0x6a, 0xae, 0xb2, 0x0b, 0x73, 0x55, 0x87, 0x82, 0xcf, 0x03, 0x57, 0x08, 0xa3, 0xb6, 0x4c, 0xa6, + 0xcd, 0xc7, 0xf9, 0x37, 0xdc, 0x6b, 0x7d, 0x02, 0x95, 0x84, 0xed, 0x57, 0xba, 0xa9, 0x2c, 0xd2, + 0x97, 0x63, 0x3b, 0x70, 0xc0, 0xae, 0xc2, 0xc6, 0xf8, 0x4c, 0x37, 0x4f, 0x78, 0xdc, 0x96, 0x92, + 0x96, 0x1f, 0x9f, 0xb5, 0x4e, 0xe8, 0xd6, 0x6f, 0x1c, 0x29, 0x4f, 0xdc, 0x22, 0x57, 0x1c, 0x4b, + 0x15, 0xe9, 0x21, 0x14, 0xc6, 0x67, 0xc9, 0xf8, 0x2b, 0x4b, 0x43, 0xbe, 0x31, 0x3e, 0xa3, 0xa8, + 0x2b, 0x1f, 0xc1, 0xb6, 0xd8, 0xc1, 0x8d, 0x40, 0xe7, 0xc1, 0xd0, 0x28, 0x5c, 0x26, 0x8f, 0x88, + 0xbc, 0xc5, 0x71, 0x8d, 0x60, 0x40, 0x18, 0xe4, 0x38, 0x15, 0x2a, 0x09, 0x06, 0xe4, 0x96, 0xb5, + 0x92, 0x96, 0x82, 0xb1, 0x67, 0x50, 0x19, 0x9f, 0xf1, 0x09, 0x1d, 0x7a, 0x87, 0x96, 0x78, 0xb5, + 0xb9, 0xbd, 0x38, 0x95, 0xe4, 0x21, 0x98, 0xa2, 0x64, 0xd7, 0x60, 0x43, 0x33, 0xce, 0x07, 0xbf, + 0xee, 0x92, 0x1a, 0x59, 0xd2, 0x44, 0xea, 0xeb, 0x5c, 0xb1, 0xa6, 0x6c, 0xaa, 0xff, 0x69, 0x06, + 0x6a, 0xf1, 0x29, 0x00, 0x17, 0x21, 0x7b, 0x94, 0xfc, 0x10, 0x52, 0x7d, 0xf1, 0xa0, 0x80, 0x24, + 0x8f, 0x87, 0x97, 0x33, 0x1e, 0xa0, 0x7f, 0x55, 0x2c, 0xd8, 0x55, 0xc6, 0xf8, 0xec, 0xca, 0xcf, + 0xaa, 0xec, 0x43, 0x76, 0x78, 0x39, 0xe3, 0x16, 0x27, 0xdc, 0x14, 0xf9, 0xe9, 0x94, 0x6f, 0x87, + 0xe4, 0x33, 0xfb, 0xbc, 0xfd, 0x2d, 0x8f, 0x28, 0x76, 0xa4, 0x75, 0x0e, 0x1b, 0xda, 0xb7, 0x3a, + 0x02, 0x48, 0x6d, 0xd8, 0xeb, 0x6b, 0xed, 0xce, 0x7e, 0x8f, 0x00, 0x39, 0xb2, 0x47, 0xc5, 0x4d, + 0x6c, 0x98, 0xe6, 0xde, 0x59, 0x32, 0x8c, 0x66, 0x26, 0x15, 0x46, 0x33, 0x8a, 0x38, 0x9b, 0x0c, + 0xe4, 0x1d, 0x46, 0x37, 0x04, 0x2c, 0x5a, 0x85, 0xd1, 0x92, 0x66, 0xef, 0x42, 0x6e, 0x7c, 0x66, + 0x5d, 0xa6, 0x8f, 0x7a, 0xe9, 0x05, 0x44, 0x04, 0xea, 0x5f, 0x65, 0x80, 0xa5, 0x1a, 0xc2, 0x4f, + 0x1f, 0x3f, 0xb7, 0x2d, 0x5f, 0x40, 0x5d, 0xbc, 0x8a, 0xe0, 0x54, 0x09, 0xeb, 0xbf, 0x18, 0xd2, + 0xab, 0x5e, 0xfc, 0x5a, 0x28, 0x0e, 0x57, 0xcb, 0x3e, 0x02, 0x1e, 0xa3, 0x9b, 0x1c, 0x4a, 0x73, + 0xaf, 0x39, 0x29, 0x6a, 0x31, 0x4d, 0x1c, 0x94, 0x3b, 0x19, 0x6c, 0x9c, 0x5f, 0x1c, 0x6c, 0xc6, + 0xb3, 0x46, 0x6b, 0x5e, 0xfd, 0x57, 0x32, 0x70, 0x25, 0xcd, 0x10, 0xbf, 0x5f, 0x2f, 0xd3, 0x91, + 0xd5, 0xb3, 0x8b, 0x91, 0xd5, 0x57, 0xf1, 0x53, 0x6e, 0x25, 0x3f, 0xfd, 0xed, 0x0c, 0x6c, 0x27, + 0x46, 0x3f, 0x3e, 0x2f, 0xfe, 0x35, 0xb5, 0x2c, 0x11, 0x60, 0x3d, 0x97, 0x0a, 0xb0, 0xae, 0xfe, + 0x65, 0x06, 0xae, 0x2d, 0xb4, 0x44, 0xb3, 0xfe, 0x5a, 0xdb, 0x92, 0x0e, 0xc4, 0x4e, 0x97, 0x17, + 0x32, 0xea, 0x56, 0xe6, 0x61, 0x36, 0x11, 0x88, 0x9d, 0x6e, 0xb4, 0xe8, 0x5a, 0xf5, 0x6d, 0x11, + 0x9c, 0x51, 0x0f, 0x2e, 0xdd, 0x91, 0x98, 0xec, 0x12, 0x41, 0x06, 0x97, 0xee, 0x48, 0xfd, 0xfb, + 0x19, 0xb8, 0xb1, 0xd0, 0x87, 0xc6, 0x3c, 0xf4, 0xc4, 0x1d, 0xfc, 0x5f, 0x53, 0x37, 0xee, 0x40, + 0x99, 0x3c, 0x14, 0xc4, 0xc5, 0x3e, 0x1f, 0x56, 0x30, 0xe2, 0x7a, 0x15, 0xc8, 0x9a, 0xc6, 0xa5, + 0x08, 0x20, 0x84, 0x3f, 0x71, 0xc1, 0x9e, 0x7a, 0x73, 0x5f, 0xf8, 0x84, 0xd2, 0x6f, 0xf5, 0x53, + 0xd8, 0x8a, 0x9b, 0xde, 0x14, 0xf1, 0xf0, 0xef, 0x40, 0xd9, 0xb5, 0xce, 0x75, 0x19, 0x2d, 0x5f, + 0x78, 0x47, 0xbb, 0xd6, 0xb9, 0x20, 0x50, 0xf7, 0x92, 0xb2, 0x30, 0xfa, 0xe6, 0x98, 0x63, 0xa6, + 0xfc, 0xa5, 0x3c, 0xc7, 0x94, 0x28, 0x2c, 0x2d, 0xd1, 0xcb, 0x82, 0x6b, 0x9d, 0x13, 0x1f, 0x9e, + 0x8b, 0x72, 0x1a, 0xa6, 0x88, 0x4e, 0xbf, 0xd2, 0xf9, 0xee, 0x06, 0x14, 0x67, 0x7e, 0x6a, 0x98, + 0x0a, 0x33, 0x9f, 0x57, 0x7b, 0x5f, 0xf8, 0x5e, 0xbf, 0xce, 0xbf, 0x84, 0x7b, 0x63, 0x8b, 0x6f, + 0x12, 0xe6, 0xe2, 0x6f, 0x12, 0x7e, 0x26, 0xc4, 0x20, 0x9d, 0xfc, 0x78, 0xcd, 0x0a, 0x64, 0x6d, + 0xf3, 0x82, 0x2a, 0xae, 0x6a, 0xf8, 0x93, 0x34, 0x39, 0xeb, 0x7b, 0xe1, 0xfe, 0x8d, 0x3f, 0xd5, + 0x5d, 0x28, 0x6b, 0xa9, 0x63, 0x6e, 0x25, 0x61, 0x31, 0x0a, 0xd2, 0xe1, 0x2e, 0xe3, 0x01, 0xd2, + 0xca, 0xb1, 0xc1, 0x28, 0x50, 0x03, 0x21, 0xf8, 0x5e, 0x18, 0xfe, 0xe8, 0xd4, 0xf0, 0xbb, 0x96, + 0x3b, 0x09, 0x4f, 0x71, 0xc8, 0xb9, 0x21, 0x37, 0x39, 0x84, 0xc0, 0x41, 0x92, 0x1d, 0x70, 0x14, + 0x1d, 0x22, 0x97, 0x5f, 0x30, 0x73, 0xad, 0x73, 0x91, 0xff, 0x6d, 0x00, 0x1c, 0x7f, 0x81, 0xe6, + 0x97, 0xa2, 0x25, 0xcf, 0x31, 0x39, 0x5a, 0xdd, 0x12, 0xfd, 0x15, 0x01, 0xb0, 0x5a, 0xd6, 0x58, + 0x75, 0xc4, 0xcc, 0xf3, 0x0e, 0x89, 0x41, 0xf8, 0x59, 0xd3, 0xc8, 0xee, 0x42, 0x45, 0xda, 0x24, + 0x28, 0xc2, 0x2a, 0xaf, 0xbe, 0x2c, 0x61, 0xbd, 0xf9, 0x54, 0xfd, 0xbb, 0x59, 0xa8, 0x34, 0xb8, + 0x47, 0xd5, 0xec, 0xb2, 0x3f, 0x0b, 0xd9, 0x9f, 0xc0, 0x55, 0x0a, 0xb9, 0xc6, 0xbf, 0xf3, 0x40, + 0x8e, 0x4c, 0xf4, 0x54, 0x4e, 0x0c, 0xe2, 0xa3, 0xc4, 0x20, 0x8a, 0x2c, 0x8f, 0x07, 0x67, 0xf6, + 0x8c, 0xbf, 0xd0, 0xec, 0x98, 0x17, 0xf4, 0x1c, 0x92, 0x7b, 0x2b, 0x50, 0x74, 0xb6, 0x34, 0x82, + 0xe2, 0x20, 0x61, 0xf1, 0xb3, 0x33, 0x51, 0xac, 0x70, 0x57, 0x41, 0xe0, 0xd1, 0x19, 0xa7, 0x79, + 0x04, 0x5b, 0x22, 0xee, 0xd9, 0xd2, 0x06, 0xbc, 0xc9, 0x11, 0x31, 0x7f, 0x0f, 0x60, 0x4b, 0x44, + 0x88, 0xa3, 0x98, 0xe5, 0xfa, 0xc8, 0x9b, 0x5d, 0x8a, 0xcb, 0xd0, 0x77, 0x5f, 0xd3, 0xd4, 0x0e, + 0x27, 0x45, 0x10, 0x6f, 0xe7, 0x66, 0x90, 0x86, 0xde, 0x6c, 0xc3, 0xf5, 0xd7, 0xf4, 0xe9, 0x4d, + 0x0e, 0x17, 0xc5, 0x84, 0xc3, 0xc5, 0xcd, 0x5d, 0xd8, 0x5e, 0x55, 0xdf, 0x4f, 0x29, 0x43, 0xfd, + 0xf3, 0x2a, 0x40, 0xcc, 0xb1, 0x29, 0x75, 0x34, 0xb3, 0xa0, 0x8e, 0xfe, 0x24, 0x67, 0xaa, 0x4f, + 0xa1, 0x86, 0x43, 0xa5, 0xc7, 0x39, 0xb2, 0x2b, 0x73, 0x54, 0x90, 0x6a, 0x18, 0xc7, 0x9d, 0x58, + 0x76, 0xd2, 0xc8, 0xad, 0x74, 0xd2, 0xf8, 0x04, 0x0a, 0xfc, 0xaa, 0x2d, 0x10, 0x0e, 0xaa, 0xd7, + 0x17, 0x57, 0xdf, 0x63, 0xf1, 0xda, 0x53, 0xd2, 0xb1, 0x36, 0xd4, 0x50, 0xf4, 0xfb, 0x76, 0x78, + 0x3a, 0x4d, 0x06, 0x3e, 0xb9, 0xbd, 0x9c, 0x53, 0x92, 0x89, 0xcf, 0xc6, 0x25, 0x93, 0x09, 0xed, + 0x35, 0x9c, 0x0a, 0xfb, 0x2f, 0x69, 0xaf, 0x85, 0xa4, 0xf6, 0x3a, 0x9c, 0x72, 0xab, 0x2f, 0x6a, + 0xaf, 0x1f, 0xc2, 0x15, 0xf1, 0x02, 0x1d, 0x33, 0xe0, 0x70, 0x12, 0x3d, 0x77, 0xad, 0x57, 0x44, + 0xfc, 0xb3, 0x29, 0x9d, 0xed, 0x90, 0xfc, 0x1b, 0xd8, 0x1e, 0x9d, 0x1a, 0xee, 0xc4, 0xd2, 0xc3, + 0x13, 0x47, 0xa7, 0x8f, 0x4b, 0xe9, 0x53, 0x63, 0x26, 0x94, 0xea, 0x77, 0x97, 0x1a, 0xdb, 0x24, + 0xe2, 0xe1, 0x89, 0x43, 0x8e, 0x7f, 0x91, 0x2b, 0xcf, 0xd6, 0x68, 0x11, 0xbe, 0x70, 0xa3, 0x0e, + 0x4b, 0x37, 0xea, 0x8b, 0x6a, 0x76, 0x79, 0x85, 0x9a, 0x1d, 0x2b, 0xcb, 0x95, 0xa4, 0xb2, 0xcc, + 0x3e, 0x80, 0x82, 0x08, 0xa0, 0x21, 0x2c, 0xbf, 0x6c, 0x79, 0x75, 0x68, 0x92, 0x04, 0x6b, 0x92, + 0xfe, 0x1d, 0x14, 0x63, 0xa9, 0xc6, 0x6b, 0x4a, 0xc2, 0xd8, 0xae, 0x30, 0x7b, 0x46, 0x4e, 0x8a, + 0xc2, 0xca, 0x7b, 0x33, 0x51, 0x70, 0x84, 0x13, 0xe7, 0xf2, 0x85, 0x1c, 0x37, 0xff, 0x93, 0x0d, + 0xd8, 0x10, 0xb7, 0xf4, 0x8f, 0x20, 0x67, 0xfa, 0xde, 0x2c, 0x7a, 0x97, 0xb4, 0x42, 0x6b, 0xa7, + 0xaf, 0x1b, 0xa3, 0x82, 0xff, 0x18, 0x36, 0x0c, 0xd3, 0xd4, 0xc7, 0x67, 0xe9, 0x1b, 0xe9, 0x05, + 0x05, 0xfa, 0x60, 0x4d, 0xcb, 0x1b, 0xa4, 0x49, 0x7f, 0x01, 0x25, 0xa4, 0x8f, 0xdd, 0x7e, 0xcb, + 0xcb, 0xc7, 0x02, 0xa9, 0xea, 0x1e, 0xac, 0x69, 0x45, 0x43, 0xaa, 0xbd, 0x7f, 0x9c, 0xb6, 0xed, + 0xe7, 0x96, 0x3a, 0xb8, 0xa0, 0xa7, 0x2d, 0x58, 0xf9, 0xff, 0x06, 0x70, 0x63, 0x6f, 0xb4, 0x63, + 0xe7, 0x93, 0x97, 0x9f, 0x4b, 0xfb, 0xfb, 0xc1, 0x9a, 0xc6, 0xf7, 0x2d, 0xb9, 0xdf, 0x7f, 0x26, + 0xed, 0xee, 0xd1, 0x97, 0x1d, 0x57, 0x8c, 0x0c, 0x8a, 0xc1, 0xc8, 0xf8, 0x4e, 0x32, 0x11, 0xb3, + 0x99, 0xf2, 0x73, 0x33, 0xe9, 0x87, 0x0b, 0xe9, 0x5d, 0x9d, 0xb2, 0x45, 0x5b, 0xfc, 0x33, 0x28, + 0x73, 0x33, 0x2c, 0xcf, 0x57, 0x5c, 0x1a, 0xda, 0x78, 0x53, 0xa6, 0x8b, 0xbd, 0x78, 0x8b, 0x6e, + 0xca, 0x7e, 0xfa, 0x56, 0xf2, 0xee, 0xe4, 0xd6, 0xca, 0x81, 0xd2, 0xa2, 0x6b, 0x14, 0xde, 0x59, + 0x8d, 0xe7, 0x61, 0x5d, 0xd8, 0x16, 0x97, 0x0c, 0x7c, 0x03, 0x96, 0x7b, 0x26, 0x2c, 0xcd, 0x57, + 0x6a, 0x87, 0x3e, 0x58, 0xd3, 0x98, 0xb1, 0xbc, 0x6f, 0x37, 0x61, 0x4b, 0x36, 0x89, 0x76, 0xd6, + 0x84, 0x23, 0x57, 0xb2, 0x4b, 0xf1, 0xbe, 0x7b, 0xb0, 0xa6, 0x6d, 0x1a, 0x69, 0x10, 0xeb, 0xc0, + 0x15, 0x59, 0x08, 0x19, 0xdb, 0xc5, 0xc8, 0x54, 0x96, 0x66, 0x31, 0xb9, 0x57, 0x1f, 0xac, 0x69, + 0x5b, 0xc6, 0xd2, 0x06, 0x7e, 0x28, 0xdb, 0x93, 0x54, 0x0e, 0xf9, 0x4a, 0xbc, 0xb3, 0x72, 0x98, + 0x62, 0x4d, 0x35, 0x6a, 0x59, 0x0c, 0x8a, 0x3d, 0x19, 0x6e, 0x6a, 0x70, 0x6d, 0xb5, 0x84, 0x49, + 0x6e, 0x33, 0x39, 0xbe, 0xcd, 0xa8, 0xc9, 0x6d, 0x66, 0x31, 0x66, 0x5a, 0x62, 0xd3, 0xf9, 0x15, + 0x54, 0x53, 0x22, 0x96, 0x95, 0xa1, 0x20, 0x3f, 0xb5, 0x43, 0x6f, 0x3d, 0x9b, 0xfd, 0xa3, 0x6f, + 0x95, 0x0c, 0x82, 0x3b, 0xbd, 0xc1, 0xb0, 0xd1, 0x1b, 0x2a, 0xeb, 0x3c, 0x71, 0xd4, 0x6d, 0x34, + 0xdb, 0x4a, 0x56, 0xfd, 0xcb, 0x2c, 0x94, 0xa2, 0x7b, 0xb6, 0x9f, 0x6f, 0x0d, 0x8b, 0xcc, 0x4c, + 0xd9, 0xa4, 0x99, 0x69, 0xe1, 0xa8, 0xc7, 0x3f, 0xa0, 0x95, 0x93, 0x1f, 0x55, 0x4a, 0x1e, 0xa8, + 0x82, 0xe5, 0x50, 0x3a, 0xf9, 0x1f, 0x19, 0x4a, 0x27, 0xe9, 0xf9, 0xbf, 0x91, 0xf6, 0xfc, 0x5f, + 0xf8, 0xdc, 0x52, 0x81, 0xbe, 0x74, 0x92, 0xfc, 0xdc, 0x12, 0x7d, 0x77, 0xfe, 0x85, 0x6d, 0x9d, + 0x0b, 0x57, 0x79, 0x91, 0x4a, 0xef, 0xd0, 0xf0, 0x86, 0x1d, 0xfa, 0xc7, 0x48, 0xfb, 0x27, 0xb0, + 0x3d, 0x3e, 0x8b, 0xbe, 0xaf, 0x12, 0x1b, 0x57, 0x2a, 0xd4, 0xa4, 0x95, 0x38, 0xf6, 0x6e, 0xf4, + 0xf1, 0xdb, 0x6a, 0xd2, 0x0c, 0x14, 0xcd, 0x56, 0xf4, 0x35, 0xdc, 0x7f, 0x29, 0x03, 0x10, 0xdf, + 0x40, 0xfd, 0xde, 0xa6, 0xdc, 0x84, 0xb5, 0x2c, 0xfb, 0x03, 0xd6, 0xb2, 0x37, 0x45, 0x8b, 0xfd, + 0x1e, 0x4a, 0xd1, 0x9d, 0xe3, 0xcf, 0x67, 0xac, 0x9f, 0x54, 0xe5, 0xdf, 0x92, 0x66, 0xed, 0xe8, + 0xd2, 0xee, 0xf7, 0x1d, 0x8b, 0x54, 0xf5, 0xd9, 0x37, 0x54, 0x7f, 0xc1, 0x6d, 0xcb, 0x51, 0xe5, + 0x7f, 0xe0, 0xd5, 0x94, 0x64, 0xf4, 0x5c, 0xfa, 0x21, 0xd6, 0x5c, 0x18, 0xc8, 0x7f, 0xff, 0xaa, + 0x7f, 0x52, 0x87, 0xff, 0x8f, 0x8c, 0xb4, 0xe2, 0x46, 0x9f, 0xc4, 0x79, 0xad, 0xd2, 0xbb, 0xda, + 0x10, 0xfd, 0x53, 0xaa, 0xfb, 0x41, 0x1b, 0x55, 0xee, 0x87, 0x6c, 0x54, 0xef, 0x42, 0x9e, 0x6f, + 0x77, 0xf9, 0xd7, 0xd9, 0xa7, 0x38, 0xfe, 0x8d, 0x9f, 0xc0, 0x53, 0x55, 0xa1, 0xe4, 0xf3, 0xfe, + 0x6e, 0xcb, 0x72, 0xe5, 0xe7, 0xfb, 0xe8, 0x65, 0xd2, 0x3f, 0xc5, 0x25, 0xea, 0xcf, 0x1d, 0x92, + 0x1f, 0x36, 0x5b, 0xa8, 0xff, 0x5f, 0x06, 0xaa, 0x29, 0x1f, 0x82, 0x9f, 0x51, 0xc5, 0x4a, 0xb9, + 0x9c, 0xfd, 0x27, 0x48, 0x2e, 0xa7, 0x9c, 0x8a, 0x8b, 0x69, 0xa7, 0x62, 0x14, 0x77, 0x95, 0xd4, + 0x11, 0x66, 0xd5, 0x61, 0x27, 0xb3, 0xf2, 0xb0, 0x73, 0x3b, 0xfa, 0x8a, 0x79, 0xa7, 0xc5, 0x7d, + 0x78, 0xab, 0x5a, 0x02, 0xc2, 0xbe, 0x84, 0x1b, 0xc2, 0x88, 0xc0, 0xc7, 0xc7, 0x1b, 0xeb, 0xd1, + 0x37, 0xce, 0xc5, 0xa1, 0xfc, 0x1a, 0x27, 0xe0, 0x1f, 0x30, 0x1c, 0x37, 0x24, 0x56, 0xed, 0x40, + 0x35, 0xe5, 0x9c, 0x81, 0x7b, 0xcb, 0xc4, 0xf1, 0x4e, 0x0c, 0x47, 0xb4, 0x45, 0xa4, 0xd8, 0x0e, + 0xe4, 0xcf, 0x4f, 0x2d, 0xdf, 0x5a, 0xf1, 0x15, 0x09, 0x8e, 0x50, 0x7f, 0x09, 0x95, 0xa4, 0xa3, + 0x18, 0xfb, 0x00, 0xf2, 0x76, 0x68, 0x4d, 0xa5, 0x79, 0xe4, 0xda, 0xb2, 0x2f, 0x59, 0x27, 0xb4, + 0xa6, 0x1a, 0x27, 0x52, 0xff, 0x2c, 0x03, 0xca, 0x22, 0x8e, 0x3e, 0x1c, 0x7b, 0x19, 0x84, 0xd6, + 0x54, 0x36, 0x86, 0xa7, 0x12, 0x8d, 0x5c, 0x4f, 0x35, 0x52, 0x5a, 0x91, 0xb2, 0xe9, 0x4f, 0xf1, + 0x71, 0xa5, 0x64, 0xf9, 0xf1, 0x09, 0x47, 0xb0, 0x07, 0x50, 0xf4, 0x2d, 0xfa, 0x02, 0xbf, 0xb9, + 0xe2, 0xc5, 0x4e, 0x84, 0x53, 0xff, 0x4e, 0x06, 0x0a, 0xc2, 0xab, 0x6d, 0xa5, 0xbd, 0xea, 0x3d, + 0x28, 0xf0, 0xaf, 0xf1, 0xcb, 0xa0, 0xb1, 0x4b, 0xbe, 0xbf, 0x12, 0xcf, 0x6e, 0x73, 0x5f, 0xbf, + 0xb4, 0xfd, 0xea, 0xc8, 0x31, 0x5c, 0x8d, 0xe0, 0xe2, 0xbb, 0xa4, 0xc6, 0x54, 0x3c, 0x22, 0xe1, + 0xd1, 0x3e, 0x81, 0x40, 0xf4, 0x4c, 0x44, 0xfd, 0x63, 0x28, 0x08, 0xaf, 0xb9, 0x95, 0x4d, 0x79, + 0xc3, 0xd7, 0xd5, 0xd5, 0x1d, 0x80, 0xd8, 0x8d, 0x6e, 0x55, 0x09, 0xea, 0x23, 0x28, 0x4a, 0xcf, + 0x39, 0xe4, 0xbf, 0xb8, 0x6a, 0xf1, 0x14, 0x2c, 0xd9, 0x18, 0x47, 0x7c, 0x19, 0xaa, 0xeb, 0x8d, + 0xce, 0xc8, 0x58, 0xfe, 0x11, 0xd0, 0xbb, 0xb8, 0xe1, 0x52, 0x58, 0xd4, 0xf4, 0x37, 0xc4, 0x22, + 0x22, 0xf6, 0x08, 0x22, 0x79, 0xf9, 0x26, 0xd3, 0x82, 0xda, 0x90, 0x2f, 0x28, 0x89, 0xcb, 0x9e, + 0x0a, 0x6b, 0x6a, 0x97, 0xc2, 0x72, 0x67, 0x92, 0x5f, 0x50, 0x48, 0xb5, 0x49, 0x4b, 0x90, 0xa9, + 0x35, 0xa8, 0x24, 0xdd, 0x7d, 0xd4, 0x06, 0x6c, 0x1d, 0x5a, 0xa1, 0x81, 0xf2, 0x47, 0x06, 0x8b, + 0xe4, 0xfc, 0x8b, 0x3f, 0xd2, 0xfc, 0xbb, 0x48, 0xa7, 0x71, 0x22, 0xf5, 0x2f, 0x73, 0xa0, 0x2c, + 0xe2, 0x7e, 0xe8, 0x35, 0xe9, 0x1d, 0x28, 0x7b, 0xc4, 0x17, 0xa9, 0x2f, 0xcf, 0x72, 0x50, 0xe2, + 0x85, 0x42, 0xea, 0xa3, 0x81, 0x45, 0x3b, 0x38, 0xe0, 0x9f, 0x0d, 0xbc, 0xce, 0x9f, 0x0e, 0x3a, + 0xde, 0x88, 0xd8, 0xba, 0x42, 0x2f, 0x05, 0xbb, 0xde, 0x88, 0x1e, 0xa9, 0x0a, 0xeb, 0x04, 0xf7, + 0x41, 0xad, 0x68, 0x45, 0x61, 0x92, 0xa0, 0xfb, 0x3b, 0xf1, 0x6e, 0x21, 0x0c, 0x44, 0xb4, 0x88, + 0x22, 0x07, 0x0c, 0x03, 0xf9, 0xfd, 0x9f, 0x91, 0xf8, 0x4c, 0x6a, 0x96, 0xbe, 0xff, 0xd3, 0x74, + 0xe9, 0x8d, 0x2a, 0x7d, 0x15, 0x61, 0x24, 0x3e, 0x10, 0x2d, 0xbe, 0xc0, 0x84, 0xa8, 0x7b, 0xfc, + 0x43, 0xb2, 0xbe, 0x15, 0x04, 0x3c, 0x3a, 0x73, 0x49, 0x84, 0xe5, 0x16, 0xc0, 0x28, 0xf8, 0xbd, + 0xf8, 0xd2, 0x25, 0x92, 0x80, 0x88, 0x11, 0xcd, 0x3f, 0x75, 0x89, 0x04, 0x37, 0xa0, 0xf8, 0x5b, + 0xcf, 0xb5, 0xc8, 0xca, 0x51, 0xa6, 0x56, 0x15, 0x30, 0x7d, 0x68, 0xcc, 0x70, 0x23, 0x70, 0x28, + 0x30, 0x09, 0x7f, 0x9d, 0xc9, 0x13, 0xea, 0x7f, 0x9b, 0x81, 0xed, 0xc5, 0xb1, 0x26, 0x36, 0xaa, + 0x40, 0xb1, 0xd9, 0xef, 0xea, 0xbd, 0xc6, 0x61, 0x5b, 0x59, 0x63, 0x9b, 0x50, 0xee, 0xef, 0x7e, + 0xdd, 0x6e, 0x0e, 0x39, 0x20, 0x43, 0x51, 0x8a, 0x06, 0xfa, 0x41, 0xa7, 0xd5, 0x6a, 0xf7, 0xf8, + 0x89, 0xa2, 0xbf, 0xfb, 0xb5, 0xde, 0xed, 0x37, 0xf9, 0x07, 0x3e, 0xa5, 0x23, 0xc4, 0x40, 0xc9, + 0x91, 0x9b, 0x04, 0xb9, 0xc3, 0x63, 0x32, 0xcf, 0xfd, 0xbc, 0x5f, 0x0e, 0xf4, 0x66, 0x6f, 0xa8, + 0x6c, 0x60, 0xaa, 0x77, 0xdc, 0xed, 0x52, 0x8a, 0x1c, 0x3a, 0x9b, 0xfd, 0xc3, 0x23, 0xad, 0x3d, + 0x18, 0xe8, 0x83, 0xce, 0x6f, 0xda, 0x4a, 0x91, 0x6a, 0xd6, 0x3a, 0xfb, 0x9d, 0x1e, 0x07, 0x94, + 0x58, 0x01, 0xb2, 0x87, 0x9d, 0x1e, 0x8f, 0xce, 0x74, 0xd8, 0xf8, 0x46, 0x29, 0xe3, 0x8f, 0xc1, + 0xf1, 0xa1, 0x52, 0x61, 0x25, 0xc8, 0x77, 0xdb, 0x2f, 0xda, 0x5d, 0xa5, 0xaa, 0xfe, 0xcf, 0x59, + 0xa9, 0x11, 0x93, 0xa7, 0xd3, 0x8f, 0xd1, 0x02, 0x57, 0xdd, 0x2f, 0x46, 0x83, 0x96, 0x4d, 0x0c, + 0x1a, 0xbb, 0x0b, 0x15, 0xb1, 0x29, 0xa4, 0xbe, 0x16, 0x2c, 0x60, 0xc4, 0x72, 0xf7, 0xa0, 0x1a, + 0x39, 0x07, 0x24, 0xbe, 0xd9, 0x53, 0x91, 0xc0, 0x15, 0xd7, 0x17, 0x1b, 0x2b, 0xae, 0x2f, 0x66, + 0x76, 0x88, 0xa7, 0x6c, 0x94, 0xb9, 0x9c, 0x93, 0x4a, 0x08, 0xa1, 0xcf, 0xdd, 0xd3, 0xc3, 0x51, + 0x44, 0xcf, 0x5d, 0x5b, 0x7e, 0x6e, 0xbc, 0x88, 0x80, 0x63, 0xd7, 0x0e, 0x17, 0x9d, 0x13, 0x4a, + 0x4b, 0xce, 0x09, 0xc9, 0xcd, 0x19, 0xd2, 0x9b, 0xf3, 0xdb, 0xd1, 0x1e, 0x89, 0x48, 0xfe, 0x9d, + 0xf1, 0x52, 0xb4, 0x0b, 0xd2, 0x67, 0xa1, 0xe7, 0x3e, 0x05, 0xaa, 0x4d, 0x90, 0x55, 0x88, 0x4c, + 0x11, 0x98, 0x68, 0x57, 0xa4, 0x77, 0xfb, 0x69, 0x6a, 0x3a, 0x4b, 0x97, 0xb4, 0x5a, 0x9a, 0x94, + 0x3d, 0x86, 0x2b, 0x82, 0xb7, 0x53, 0x63, 0x2b, 0x9e, 0xfc, 0x72, 0x54, 0x23, 0x1e, 0x61, 0xf5, + 0x8f, 0xa0, 0x28, 0x9d, 0xda, 0x7e, 0x58, 0xd9, 0x5d, 0x31, 0xaf, 0xea, 0xbf, 0xbf, 0x0e, 0xa5, + 0xc8, 0xc5, 0xed, 0x47, 0x71, 0x07, 0x7d, 0x9c, 0x2c, 0x38, 0x4b, 0x8a, 0x98, 0x22, 0x02, 0xe4, + 0x4c, 0x89, 0xf7, 0x63, 0x73, 0xdf, 0x96, 0x1a, 0x1b, 0x87, 0x1c, 0xfb, 0x36, 0x45, 0xa3, 0xb3, + 0xdd, 0xc4, 0xe3, 0xdc, 0x92, 0x56, 0x44, 0x00, 0x2d, 0xb4, 0x1b, 0x40, 0xbf, 0x29, 0x27, 0x67, + 0x92, 0x02, 0xa6, 0x31, 0xdf, 0xb5, 0xe8, 0xfc, 0xc7, 0x79, 0x43, 0xa4, 0xe8, 0xd3, 0x6a, 0xdc, + 0xbb, 0x86, 0xfb, 0x14, 0xc8, 0xef, 0x27, 0xbf, 0x05, 0xa5, 0x79, 0xf4, 0x01, 0x6e, 0xc1, 0x11, + 0x73, 0xf9, 0xf9, 0xed, 0xf4, 0xac, 0x96, 0x16, 0x67, 0x75, 0x91, 0xa7, 0x61, 0x89, 0xa7, 0xd5, + 0x10, 0x0a, 0xc2, 0xcd, 0xef, 0x87, 0x07, 0xfc, 0x07, 0x87, 0x4a, 0x81, 0xac, 0xe1, 0xc8, 0x17, + 0xc1, 0xf8, 0x73, 0xa1, 0x61, 0xb9, 0x85, 0x86, 0xa9, 0xff, 0xe6, 0x3a, 0x40, 0xec, 0x2e, 0xc8, + 0x3e, 0x5c, 0x70, 0x4d, 0xce, 0x2c, 0x6d, 0xfb, 0x0b, 0x1e, 0xc9, 0x0b, 0xe1, 0x19, 0xd7, 0x7f, + 0x44, 0x78, 0xc6, 0x27, 0x50, 0x0d, 0xfc, 0xd1, 0x1b, 0x0d, 0xee, 0xe5, 0xc0, 0x1f, 0x45, 0xf6, + 0xf6, 0x8f, 0x00, 0x93, 0x14, 0xba, 0xd9, 0x7c, 0xfd, 0x27, 0x17, 0x4b, 0x81, 0x3f, 0xea, 0x9f, + 0x7c, 0xd7, 0xe2, 0x8f, 0xf6, 0xcc, 0x20, 0xd4, 0x57, 0x49, 0x89, 0x4d, 0x33, 0x08, 0x5b, 0x49, + 0x41, 0x71, 0x1f, 0x6a, 0x48, 0xbb, 0x24, 0x2c, 0x2a, 0x66, 0x10, 0x5f, 0xb0, 0xa8, 0xff, 0xac, + 0xbc, 0x92, 0x5e, 0xb0, 0xe5, 0xb2, 0xcf, 0xc5, 0x41, 0x3c, 0xa1, 0x44, 0xd4, 0x57, 0x99, 0x7e, + 0xf9, 0x6b, 0xdc, 0x88, 0x74, 0xf9, 0x63, 0xc9, 0xeb, 0x3f, 0xf6, 0x63, 0xc9, 0x3b, 0x00, 0x71, + 0xf0, 0x6c, 0x5c, 0x81, 0xd1, 0x73, 0x9d, 0x12, 0x7f, 0x88, 0xf3, 0xe8, 0x10, 0xae, 0x34, 0x26, + 0x13, 0xdf, 0x9a, 0xd0, 0x07, 0x9d, 0xdc, 0xb1, 0x3d, 0x91, 0x3e, 0x9f, 0x8d, 0xfd, 0x7d, 0xbd, + 0xd9, 0xef, 0xed, 0x75, 0xf6, 0x65, 0x6c, 0xb1, 0xbb, 0xf0, 0x76, 0x02, 0xb8, 0xaf, 0xf5, 0x8f, + 0x8f, 0x30, 0xd1, 0x6c, 0x0c, 0xf5, 0xbe, 0xd6, 0x6a, 0x6b, 0x4a, 0xe6, 0xd1, 0x5d, 0xa8, 0x34, + 0xc5, 0x4e, 0x19, 0xc5, 0x3b, 0xf3, 0x5c, 0x8b, 0x7f, 0x36, 0xae, 0xfb, 0xdb, 0x4f, 0x95, 0xcc, + 0x23, 0x15, 0xca, 0x89, 0x8f, 0x36, 0x22, 0xc5, 0x81, 0x11, 0x9c, 0x8a, 0x4f, 0x88, 0x19, 0xee, + 0xc4, 0x52, 0x32, 0x8f, 0x1e, 0xa0, 0x0e, 0x9f, 0xfc, 0x64, 0x22, 0xc0, 0x46, 0xcf, 0xf3, 0xa7, + 0x86, 0x23, 0xe8, 0xac, 0x79, 0x80, 0x74, 0x1f, 0xc1, 0xd5, 0x95, 0x1f, 0x80, 0xa4, 0x37, 0x61, + 0xf6, 0x74, 0xe6, 0x58, 0xfc, 0x75, 0xd3, 0xc1, 0xe5, 0x89, 0x6f, 0x9b, 0x4a, 0xe6, 0xd1, 0xb3, + 0x85, 0x0f, 0x84, 0x1d, 0xf7, 0x76, 0xfb, 0xc7, 0xbd, 0x16, 0x85, 0x22, 0xa3, 0x88, 0x7f, 0xcd, + 0xee, 0xf1, 0xa0, 0xf3, 0x42, 0x6c, 0xad, 0xed, 0x6f, 0x64, 0x72, 0xfd, 0xd1, 0x37, 0x32, 0xa8, + 0x86, 0x6c, 0x75, 0xb7, 0xdf, 0x68, 0xf1, 0x2d, 0x39, 0x0a, 0x60, 0x38, 0xdc, 0xe5, 0x1f, 0x16, + 0xd3, 0xda, 0x83, 0xe3, 0xee, 0x50, 0xc6, 0x46, 0xac, 0x01, 0x74, 0x9a, 0xed, 0xdd, 0xb6, 0xb6, + 0x8f, 0x04, 0x59, 0x4c, 0x1f, 0xf6, 0x7b, 0xfb, 0xfd, 0xd6, 0x2e, 0xa6, 0x73, 0x8f, 0xfe, 0x9b, + 0x75, 0x50, 0x16, 0xe3, 0xa0, 0xb0, 0xb7, 0xe0, 0x3a, 0x11, 0xe9, 0x47, 0x5a, 0xbb, 0xd5, 0x69, + 0x72, 0x77, 0xd8, 0x17, 0x8d, 0x6e, 0x07, 0xeb, 0xbc, 0x0e, 0x57, 0x16, 0x91, 0x8d, 0x5e, 0x8b, + 0x47, 0x4c, 0x5b, 0x44, 0xb4, 0x7f, 0x7d, 0xdc, 0xe8, 0x2a, 0xeb, 0xec, 0x6d, 0xb8, 0xb1, 0x88, + 0xea, 0xf5, 0x87, 0x02, 0x9d, 0x65, 0x75, 0xd8, 0x5e, 0x44, 0x77, 0xdb, 0x03, 0xd4, 0x1b, 0x6e, + 0xc3, 0xcd, 0x55, 0x18, 0x91, 0x33, 0xbf, 0xaa, 0xa5, 0xfb, 0xa4, 0x76, 0x68, 0xca, 0x06, 0xb2, + 0xcc, 0x6b, 0x90, 0x22, 0x7f, 0x81, 0x5d, 0x03, 0xb6, 0xdc, 0x53, 0xa5, 0xb8, 0x72, 0x04, 0x06, + 0xfc, 0x6b, 0xe6, 0x25, 0x76, 0x07, 0xde, 0x5a, 0x85, 0xec, 0x8b, 0xcf, 0x9d, 0xc3, 0xa3, 0x7f, + 0x98, 0x81, 0xfa, 0xeb, 0x9e, 0xc5, 0x33, 0x15, 0x6e, 0x6b, 0xc7, 0x3d, 0x8a, 0x60, 0xc8, 0x83, + 0x2d, 0xea, 0xcf, 0xdb, 0xdf, 0x2e, 0x04, 0xa6, 0x7b, 0x1b, 0x6e, 0xac, 0xa0, 0xd1, 0x1a, 0x2f, + 0xf5, 0x17, 0x9f, 0x28, 0x19, 0xf6, 0x3e, 0xbc, 0xbb, 0x02, 0xbd, 0xd7, 0xed, 0x37, 0x86, 0xfa, + 0x6f, 0xda, 0x5a, 0x5f, 0x6f, 0x76, 0xfb, 0x83, 0x76, 0x0b, 0x89, 0xd7, 0xd9, 0x0e, 0xdc, 0x5a, + 0x41, 0x3c, 0xe0, 0x81, 0x30, 0x5f, 0x7c, 0xa2, 0x64, 0xd9, 0x3b, 0x70, 0xf7, 0xf5, 0x14, 0x7b, + 0xa8, 0x99, 0xbd, 0xf8, 0x44, 0xc9, 0x3d, 0xfa, 0x15, 0xd4, 0x5f, 0xf7, 0xd6, 0x0c, 0x97, 0x45, + 0xf3, 0xa0, 0x41, 0xef, 0xf9, 0x50, 0x9b, 0xeb, 0xeb, 0x3c, 0x45, 0x36, 0x67, 0xad, 0xdd, 0x6d, + 0x93, 0x43, 0xf6, 0xa3, 0xdf, 0x65, 0x12, 0x27, 0x1b, 0xf9, 0x5e, 0x28, 0x02, 0x88, 0xb5, 0x9a, + 0x04, 0x69, 0x96, 0x61, 0x2a, 0x19, 0x9c, 0xa5, 0x14, 0xa8, 0xeb, 0x8d, 0x0c, 0x47, 0x59, 0x27, + 0xd7, 0x6b, 0x09, 0xa7, 0x77, 0xae, 0x4a, 0x16, 0x87, 0x2e, 0x82, 0x75, 0xbd, 0xf3, 0x23, 0xdf, + 0xf6, 0x7c, 0x3b, 0xbc, 0xe4, 0xe8, 0xdc, 0xa3, 0x7f, 0x5a, 0xb8, 0x0d, 0xa4, 0xe4, 0x1d, 0x56, + 0xd0, 0x30, 0xcd, 0x18, 0x46, 0x5b, 0x2c, 0xe7, 0x75, 0xd2, 0x2f, 0x16, 0x10, 0x19, 0xe4, 0x0f, + 0x69, 0x7e, 0x59, 0x44, 0xae, 0x23, 0x52, 0xb3, 0xc8, 0x69, 0x77, 0x09, 0x99, 0xdd, 0xfd, 0xea, + 0x1f, 0xfc, 0xd5, 0xed, 0xcc, 0x7f, 0xfd, 0x57, 0xb7, 0x33, 0xff, 0xcb, 0x5f, 0xdd, 0x5e, 0xfb, + 0xb3, 0xff, 0xed, 0x76, 0xe6, 0x37, 0x1f, 0x4e, 0xec, 0xf0, 0x74, 0x7e, 0xf2, 0x78, 0xe4, 0x4d, + 0x3f, 0x9a, 0x1a, 0xa1, 0x6f, 0x5f, 0x70, 0x45, 0x47, 0x26, 0x5c, 0xeb, 0xa3, 0xd9, 0xd9, 0xe4, + 0xa3, 0xd9, 0xc9, 0x47, 0x28, 0x72, 0x4f, 0x36, 0x66, 0xbe, 0x17, 0x7a, 0x4f, 0xff, 0xff, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x12, 0x10, 0xb8, 0xf4, 0x93, 0x96, 0x00, 0x00, } func (m *Type) Marshal() (dAtA []byte, err error) { @@ -19724,6 +19742,21 @@ func (m *UpdateCtx) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.TargetUpdateCtxIdx != 0 { + i = encodeVarintPlan(dAtA, i, uint64(m.TargetUpdateCtxIdx)) + i-- + dAtA[i] = 0x78 + } + if m.DedupByTargetRowId { + i-- + if m.DedupByTargetRowId { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x70 + } if m.IgnoreAffectedRows { i-- if m.IgnoreAffectedRows { @@ -29935,6 +29968,12 @@ func (m *UpdateCtx) ProtoSize() (n int) { if m.IgnoreAffectedRows { n += 2 } + if m.DedupByTargetRowId { + n += 2 + } + if m.TargetUpdateCtxIdx != 0 { + n += 1 + sovPlan(uint64(m.TargetUpdateCtxIdx)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -44116,6 +44155,45 @@ func (m *UpdateCtx) Unmarshal(dAtA []byte) error { } } m.IgnoreAffectedRows = bool(v != 0) + case 14: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DedupByTargetRowId", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.DedupByTargetRowId = bool(v != 0) + case 15: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field TargetUpdateCtxIdx", wireType) + } + m.TargetUpdateCtxIdx = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowPlan + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.TargetUpdateCtxIdx |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipPlan(dAtA[iNdEx:]) diff --git a/pkg/sql/colexec/multi_update/delete.go b/pkg/sql/colexec/multi_update/delete.go index 32e1a2ac4a824..2bd1c634f3217 100644 --- a/pkg/sql/colexec/multi_update/delete.go +++ b/pkg/sql/colexec/multi_update/delete.go @@ -55,7 +55,7 @@ func (update *MultiUpdate) delete_table( for i := 0; i < rowCount; i++ { if !rowIdNulls.Contains(uint64(i)) { - for deleteIdx, inputIdx := range updateCtx.DeleteCols { + for deleteIdx, inputIdx := range updateCtx.DeleteCols[:2] { err = deleteBatch.Vecs[deleteIdx].UnionOne(inputBatch.Vecs[inputIdx], int64(i), proc.Mp()) if err != nil { return err @@ -65,7 +65,7 @@ func (update *MultiUpdate) delete_table( } } else { - for deleteIdx, inputIdx := range updateCtx.DeleteCols { + for deleteIdx, inputIdx := range updateCtx.DeleteCols[:2] { err = deleteBatch.Vecs[deleteIdx].UnionBatch(inputBatch.Vecs[inputIdx], 0, inputBatch.Vecs[inputIdx].Length(), nil, proc.GetMPool()) if err != nil { return err diff --git a/pkg/sql/colexec/multi_update/multi_update.go b/pkg/sql/colexec/multi_update/multi_update.go index a3ce1aa61f122..402fdcff6082d 100644 --- a/pkg/sql/colexec/multi_update/multi_update.go +++ b/pkg/sql/colexec/multi_update/multi_update.go @@ -20,7 +20,13 @@ import ( "time" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/hashmap" + "github.com/matrixorigin/matrixone/pkg/common/moerr" + "github.com/matrixorigin/matrixone/pkg/common/mpool" + "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" + "github.com/matrixorigin/matrixone/pkg/common/runtime" "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/perfcounter" "github.com/matrixorigin/matrixone/pkg/sql/colexec" @@ -101,6 +107,14 @@ func (update *MultiUpdate) Prepare(proc *process.Process) error { if len(update.ctr.deleteBuf) == 0 { update.ctr.deleteBuf = make([]*batch.Batch, len(update.MultiUpdateCtx)) } + if err := update.prepareSeenTargetRows(proc); err != nil { + return err + } + if update.Action == UpdateWriteS3 { + if err := update.prepareSeenTargetRowsAdmission(proc.GetService()); err != nil { + return err + } + } update.ctr.affectedRows = 0 update.ctr.flushed = false @@ -376,35 +390,234 @@ func (update *MultiUpdate) updateFlushS3Info(proc *process.Process, analyzer pro } func (update *MultiUpdate) updateOneBatch(proc *process.Process, analyzer process.Analyzer, bat *batch.Batch) (err error) { + targetBatches := make(map[int]*batch.Batch) + defer func() { + for _, targetBatch := range targetBatches { + if targetBatch != bat { + targetBatch.Clean(proc.Mp()) + } + } + }() + for i, updateCtx := range update.MultiUpdateCtx { + targetIdx := updateCtx.TargetUpdateCtxIdx + if targetIdx < 0 || targetIdx >= len(update.MultiUpdateCtx) { + return moerr.NewInternalError(proc.Ctx, "invalid multi-target update context index") + } + contextBatch, ok := targetBatches[targetIdx] + if !ok { + var duplicateRows uint64 + contextBatch, _, duplicateRows, err = filterTargetRows( + proc, + update.MultiUpdateCtx[targetIdx], + bat, + update.ctr.seenTargetRows[targetTableID(update.MultiUpdateCtx[targetIdx])], + ) + if err != nil { + return err + } + update.addAffectedRowsFunc(duplicateRows) + targetBatches[targetIdx] = contextBatch + } + if contextBatch.RowCount() == 0 { + continue + } + // delete rows if len(updateCtx.DeleteCols) > 0 { - err = update.delete_table(proc, analyzer, updateCtx, bat, i) - if err != nil { - return + if err = update.delete_table(proc, analyzer, updateCtx, contextBatch, i); err != nil { + return err } } // insert rows - if len(updateCtx.InsertCols) > 0 { - tableType := update.ctr.updateCtxInfos[updateCtx.TableDef.Name].tableType - switch tableType { - case UpdateMainTable: - err = update.insert_main_table(proc, analyzer, i, bat) - case UpdateUniqueIndexTable: - err = update.insert_unique_index_table(proc, analyzer, i, bat) - case UpdateSecondaryIndexTable: - err = update.insert_secondary_index_table(proc, analyzer, i, bat) - } - if err != nil { - return + if len(updateCtx.InsertCols) == 0 { + continue + } + tableType := update.ctr.updateCtxInfos[updateCtx.TableDef.Name].tableType + switch tableType { + case UpdateMainTable: + err = update.insert_main_table(proc, analyzer, i, contextBatch) + case UpdateUniqueIndexTable: + err = update.insert_unique_index_table(proc, analyzer, i, contextBatch) + case UpdateSecondaryIndexTable: + err = update.insert_secondary_index_table(proc, analyzer, i, contextBatch) + } + if err != nil { + return err + } + } + + return nil +} + +func filterTargetRows( + proc *process.Process, + updateCtx *MultiUpdateCtx, + input *batch.Batch, + seen *hashmap.StrHashMap, +) (*batch.Batch, bool, uint64, error) { + if !updateCtx.DedupByTargetRowID { + return input, false, 0, nil + } + if len(updateCtx.DeleteCols) < 3 || + updateCtx.DeleteCols[0] < 0 || + updateCtx.DeleteCols[0] >= len(input.Vecs) || + updateCtx.DeleteCols[2] < 0 || + updateCtx.DeleteCols[2] >= len(input.Vecs) { + return nil, false, 0, moerr.NewInternalError(proc.Ctx, "invalid multi-target update selector columns") + } + + rowIDVec := input.Vecs[updateCtx.DeleteCols[0]] + rowNumberVec := input.Vecs[updateCtx.DeleteCols[2]] + if rowIDVec.GetType().Oid != types.T_Rowid || + rowNumberVec.GetType().Oid != types.T_int64 { + return nil, false, 0, moerr.NewInternalError(proc.Ctx, "invalid multi-target update selector types") + } + + rowNumbers := vector.MustFixedColWithTypeCheck[int64](rowNumberVec) + rowIDNulls := rowIDVec.GetNulls() + rowNumberNulls := rowNumberVec.GetNulls() + var activeVec *vector.Vector + if len(updateCtx.DeleteCols) >= 4 { + activeVec = input.Vecs[updateCtx.DeleteCols[3]] + if activeVec.GetType().Oid != types.T_bool { + return nil, false, 0, moerr.NewInternalError(proc.Ctx, "invalid multi-target update selector types") + } + } + selections := make([]int64, 0, input.RowCount()) + for i := 0; i < input.RowCount(); i++ { + if rowIDNulls.Contains(uint64(i)) || + rowNumberNulls.Contains(uint64(i)) || + rowNumbers[i] != 1 { + continue + } + if activeVec != nil && (activeVec.IsNull(uint64(i)) || + !vector.GetFixedAtNoTypeCheck[bool](activeVec, i)) { + continue + } + selections = append(selections, int64(i)) + } + + // Modern execution batches can carry a statement allocation account. Keep + // that provenance on the owned filtered copy instead of cloning into an + // on-heap batch, which cannot accept an allocation selection. + filtered, err := input.Clone(proc.Mp(), true) + if err != nil { + return nil, false, 0, err + } + filtered.Shrink(selections, false) + filtered.SetRowCount(len(selections)) + if seen == nil || filtered.RowCount() == 0 { + return filtered, true, 0, nil + } + + physicalSelections := make([]int64, 0, filtered.RowCount()) + iterator := seen.NewIterator() + defer hashmap.IteratorClearOwner(iterator) + for offset := 0; offset < filtered.RowCount(); offset += hashmap.UnitLimit { + count := min(hashmap.UnitLimit, filtered.RowCount()-offset) + oldGroupCount := seen.GroupCount() + values, zValues, err := iterator.Insert( + offset, + count, + []*vector.Vector{filtered.Vecs[updateCtx.DeleteCols[0]]}, + ) + if err != nil { + filtered.Clean(proc.Mp()) + return nil, false, 0, err + } + for i, value := range values { + if zValues[i] != 0 && value > oldGroupCount { + physicalSelections = append(physicalSelections, int64(offset+i)) } } } + duplicateRows := uint64(filtered.RowCount() - len(physicalSelections)) + filtered.Shrink(physicalSelections, false) + filtered.SetRowCount(len(physicalSelections)) + return filtered, true, duplicateRows, nil +} + +func (update *MultiUpdate) prepareSeenTargetRows(proc *process.Process) error { + if update.ctr.seenTargetRows != nil { + return nil + } + targetCounts := make(map[uint64]int) + for _, ctx := range update.MultiUpdateCtx { + if ctx.DedupByTargetRowID && !features.IsIndexTable(ctx.TableDef.FeatureFlag) { + targetCounts[targetTableID(ctx)]++ + } + } + update.ctr.seenTargetRows = make(map[uint64]*hashmap.StrHashMap) + for tableID, count := range targetCounts { + if count < 2 { + continue + } + if update.mapAllocation == nil || update.iteratorAllocation == nil { + return mpool.ErrAllocationAccountInvalid + } + seen, err := hashmap.NewStrHashMapWithAllocations( + false, + proc.Mp(), + update.mapAllocation, + update.iteratorAllocation, + ) + if err != nil { + return err + } + update.ctr.seenTargetRows[tableID] = seen + } + return nil +} + +func (update *MultiUpdate) prepareSeenTargetRowsAdmission(sid string) error { + if len(update.ctr.seenTargetRows) == 0 { + return nil + } + if update.ctr.seenRowsRSC != nil { + return nil + } + value, ok := runtime.ServiceRuntime(sid).GetGlobalVariables(runtime.CNMemoryThrottler) + if !ok { + return moerr.NewInternalErrorNoCtxf("can not get global variable %s", runtime.CNMemoryThrottler) + } + update.ctr.seenRowsRSC = value.(rscthrottler.RSCThrottler) + if err := update.admitSeenTargetRowsGrowth(update.seenTargetRowsSize()); err != nil { + update.ctr.seenRowsRSC = nil + return err + } + return nil +} +func (update *MultiUpdate) admitSeenTargetRowsGrowth(increment int64) error { + if increment <= 0 || update.ctr.seenRowsRSC == nil { + return nil + } + if _, granted := update.ctr.seenRowsRSC.Acquire(increment); !granted { + return moerr.NewInternalErrorNoCtx( + "multi-target update Rowid deduplication exceeded the CN memory admission limit", + ) + } + update.ctr.seenRowsGrant += increment return nil } +func (update *MultiUpdate) seenTargetRowsSize() int64 { + var size int64 + for _, seen := range update.ctr.seenTargetRows { + size += seen.Size() + } + return size +} + +func targetTableID(ctx *MultiUpdateCtx) uint64 { + if ctx.TargetTableID != 0 { + return ctx.TargetTableID + } + return ctx.TableDef.TblId +} + func (update *MultiUpdate) resetMultiUpdateCtxs() { update.ctr.updateCtxInfos = make(map[string]*updateCtxInfo, len(update.MultiUpdateCtx)) diff --git a/pkg/sql/colexec/multi_update/multi_update_partition.go b/pkg/sql/colexec/multi_update/multi_update_partition.go index 843c372858f5c..f004a273c6319 100644 --- a/pkg/sql/colexec/multi_update/multi_update_partition.go +++ b/pkg/sql/colexec/multi_update/multi_update_partition.go @@ -17,6 +17,7 @@ package multi_update import ( "bytes" + "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" "github.com/matrixorigin/matrixone/pkg/partitionprune" "github.com/matrixorigin/matrixone/pkg/pb/partition" @@ -29,29 +30,33 @@ import ( type PartitionMultiUpdate struct { vm.OperatorBase - raw *MultiUpdate - affectedRows uint64 + raw *MultiUpdate + rawContexts []*MultiUpdateCtx + targets []*partitionUpdateTarget + affectedRows uint64 + writers map[uint64]*s3WriterDelegate + freeWriters []*s3WriterDelegate + nextWriterID uint64 +} + +type partitionUpdateTarget struct { + contexts []*MultiUpdateCtx tableID uint64 meta partition.PartitionMetadata mainIndexes []uint64 partitionIndexes map[uint64][]engine.Relation - rawTableIDs []uint64 - rawTableFlags []uint64 - writers map[uint64]*s3WriterDelegate - freeWriters []*s3WriterDelegate + writerIDs map[uint64]uint64 } func NewPartitionMultiUpdate( raw *MultiUpdate, - tableID uint64, ) vm.Operator { if raw.Action == UpdateFlushS3Info { return raw } return &PartitionMultiUpdate{ - raw: raw, - tableID: tableID, + raw: raw, } } @@ -65,7 +70,7 @@ func NewPartitionMultiUpdateFrom( op.CountDeleteAffectRows = from.raw.CountDeleteAffectRows op.RejectZeroTemporal = from.raw.RejectZeroTemporal op.Engine = from.raw.Engine - return NewPartitionMultiUpdate(op, from.tableID) + return NewPartitionMultiUpdate(op) } func (op *PartitionMultiUpdate) String(buf *bytes.Buffer) { @@ -77,6 +82,18 @@ func (op *PartitionMultiUpdate) OpType() vm.OpType { return vm.PartitionMultiUpdate } +func (op *PartitionMultiUpdate) SetAllocationAccount(account *mpool.AllocationAccount) error { + return op.raw.SetAllocationAccount(account) +} + +func (op *PartitionMultiUpdate) ClearAllocationAccount(account *mpool.AllocationAccount) error { + return op.raw.ClearAllocationAccount(account) +} + +func (op *PartitionMultiUpdate) ActivatesAllocationAccountLifecycle() bool { + return op.raw.ActivatesAllocationAccountLifecycle() +} + func (op *PartitionMultiUpdate) Prepare( proc *process.Process, ) error { @@ -86,46 +103,80 @@ func (op *PartitionMultiUpdate) Prepare( op.OpAnalyzer.Reset() } - var err error - op.meta, _, err = proc.GetPartitionService().GetStorage().GetMetadata( - proc.Ctx, - op.tableID, - proc.GetTxnOperator(), - ) - if err != nil { - return err - } - _, _, r, err := op.raw.Engine.GetRelationById( - proc.Ctx, - proc.GetTxnOperator(), - op.tableID, - ) - if err != nil { + op.raw.OperatorBase = op.OperatorBase + if err := op.raw.Prepare(proc); err != nil { return err } - if len(r.GetExtraInfo().IndexTables) > 0 { - op.mainIndexes = r.GetExtraInfo().IndexTables - op.partitionIndexes = make(map[uint64][]engine.Relation, len(op.meta.Partitions)) - } - op.raw.OperatorBase = op.OperatorBase - if err = op.raw.Prepare(proc); err != nil { - return err + op.rawContexts = op.raw.MultiUpdateCtx + op.targets = buildPartitionUpdateTargets(op.rawContexts) + for _, target := range op.targets { + if !features.IsPartitioned(target.contexts[0].TableDef.FeatureFlag) { + continue + } + + var err error + target.meta, _, err = proc.GetPartitionService().GetStorage().GetMetadata( + proc.Ctx, + target.tableID, + proc.GetTxnOperator(), + ) + if err != nil { + return err + } + _, _, r, err := op.raw.Engine.GetRelationById( + proc.Ctx, + proc.GetTxnOperator(), + target.tableID, + ) + if err != nil { + return err + } + if len(r.GetExtraInfo().IndexTables) > 0 { + target.mainIndexes = r.GetExtraInfo().IndexTables + target.partitionIndexes = make(map[uint64][]engine.Relation, len(target.meta.Partitions)) + } } op.affectedRows = 0 op.raw.getS3WriterFunc = op.getS3Writer op.raw.getFlushableS3WriterFunc = op.getFlushableS3Writer op.raw.addAffectedRowsFunc = op.doAddAffectedRows - op.writers = make(map[uint64]*s3WriterDelegate, len(op.meta.Partitions)) + op.writers = make(map[uint64]*s3WriterDelegate) + op.nextWriterID = 0 + return nil +} - op.rawTableIDs = make([]uint64, 0, len(op.raw.MultiUpdateCtx)) - op.rawTableFlags = make([]uint64, 0, len(op.raw.MultiUpdateCtx)) - for _, c := range op.raw.MultiUpdateCtx { - op.rawTableIDs = append(op.rawTableIDs, c.TableDef.TblId) - op.rawTableFlags = append(op.rawTableFlags, c.TableDef.FeatureFlag) +func buildPartitionUpdateTargets(contexts []*MultiUpdateCtx) []*partitionUpdateTarget { + targetsByMain := make(map[int]*partitionUpdateTarget) + targets := make([]*partitionUpdateTarget, 0, len(contexts)) + for i, ctx := range contexts { + if features.IsIndexTable(ctx.TableDef.FeatureFlag) { + continue + } + target := &partitionUpdateTarget{ + contexts: []*MultiUpdateCtx{cloneTargetContext(ctx)}, + tableID: ctx.TableDef.TblId, + writerIDs: make(map[uint64]uint64), + } + targetsByMain[i] = target + targets = append(targets, target) } - return nil + for _, ctx := range contexts { + if !features.IsIndexTable(ctx.TableDef.FeatureFlag) { + continue + } + if target := targetsByMain[ctx.TargetUpdateCtxIdx]; target != nil { + target.contexts = append(target.contexts, cloneTargetContext(ctx)) + } + } + return targets +} + +func cloneTargetContext(ctx *MultiUpdateCtx) *MultiUpdateCtx { + cloned := ctx.clone() + cloned.TargetUpdateCtxIdx = 0 + return cloned } func (op *PartitionMultiUpdate) Call( @@ -155,70 +206,10 @@ func (op *PartitionMultiUpdate) writeTable( op.raw.delegated = true op.raw.input = input - pos := int32(-1) - if len(op.raw.MultiUpdateCtx[0].PartitionCols) > 0 { - pos = int32(op.raw.MultiUpdateCtx[0].PartitionCols[0]) - } - - res, err := partitionprune.Prune(proc, input.Batch, op.meta, pos) - if err != nil { - return vm.CallResult{}, err - } - defer res.Close() - if res.Empty() { - panic("Prune result is empty") - } - - var rel engine.Relation - res.Iter( - func( - partition partition.Partition, - bat *batch.Batch, - ) bool { - _, _, rel, err = op.raw.Engine.GetRelationById( - proc.Ctx, - proc.GetTxnOperator(), - partition.PartitionID, - ) - if err != nil { - return false - } - - // mapping all main table and index table to partition's. - // Clone each context to avoid mutating shared plan objects - // that may be read concurrently by other operators. - cloned := make([]*MultiUpdateCtx, len(op.raw.MultiUpdateCtx)) - for i, c := range op.raw.MultiUpdateCtx { - r := rel - if features.IsIndexTable(op.rawTableFlags[i]) { - r, err = op.getPartitionIndex( - proc, - op.rawTableIDs[i], - partition.PartitionID, - rel, - ) - if err != nil { - return false - } - } - - cloned[i] = c.clone() - cloned[i].ObjRef.ObjName = r.GetTableName() - cloned[i].TableDef = r.GetTableDef(proc.Ctx) - } - op.raw.MultiUpdateCtx = cloned - op.raw.resetMultiUpdateCtxs() - if err = op.raw.resetMultiSources(proc); err != nil { - return false - } - op.raw.input = vm.CallResult{Batch: bat} - - _, err = op.raw.Call(proc) - return err == nil - }, - ) - if err != nil { - return vm.CallResult{}, err + for _, target := range op.targets { + if err := op.writeTarget(proc, target, input.Batch); err != nil { + return vm.CallResult{}, err + } } return input, nil } @@ -250,74 +241,214 @@ func (op *PartitionMultiUpdate) writeS3( continue } - pos := int32(-1) - if len(op.raw.MultiUpdateCtx[0].PartitionCols) > 0 { - pos = int32(op.raw.MultiUpdateCtx[0].PartitionCols[0]) + for _, target := range op.targets { + if err := op.writeTarget(proc, target, input.Batch); err != nil { + return vm.CallResult{}, err + } } - res, err := partitionprune.Prune(proc, input.Batch, op.meta, pos) - if err != nil { - return vm.CallResult{}, err + } +} + +func (op *PartitionMultiUpdate) writeTarget( + proc *process.Process, + target *partitionUpdateTarget, + input *batch.Batch, +) error { + if !features.IsPartitioned(target.contexts[0].TableDef.FeatureFlag) { + return op.callRawTarget(proc, target, target.contexts, target.tableID, input) + } + if len(target.contexts[0].PartitionCols) > 1 { + return op.writePartitionKeyUpdate(proc, target, input) + } + + pos := int32(-1) + if len(target.contexts[0].PartitionCols) > 0 { + pos = int32(target.contexts[0].PartitionCols[0]) + } + res, err := partitionprune.Prune(proc, input, target.meta, pos) + if err != nil { + return err + } + defer res.Close() + if res.Empty() { + panic("Prune result is empty") + } + + res.Iter(func(p partition.Partition, bat *batch.Batch) bool { + contexts, resolveErr := op.resolvePartitionContexts(proc, target, target.contexts, p) + if resolveErr != nil { + err = resolveErr + return false } - if res.Empty() { - panic("Prune result is empty") + err = op.callRawTarget(proc, target, contexts, p.PartitionID, bat) + return err == nil + }) + return err +} + +func (op *PartitionMultiUpdate) resolvePartitionContexts( + proc *process.Process, + target *partitionUpdateTarget, + contexts []*MultiUpdateCtx, + p partition.Partition, +) ([]*MultiUpdateCtx, error) { + _, _, rel, err := op.raw.Engine.GetRelationById( + proc.Ctx, + proc.GetTxnOperator(), + p.PartitionID, + ) + if err != nil { + return nil, err + } + + resolved := make([]*MultiUpdateCtx, len(contexts)) + for i, ctx := range contexts { + r := rel + if features.IsIndexTable(ctx.TableDef.FeatureFlag) { + r, err = op.getPartitionIndex( + proc, + target, + ctx.TableDef.TblId, + p.PartitionID, + rel, + ) + if err != nil { + return nil, err + } } + resolved[i] = ctx.clone() + resolved[i].ObjRef.ObjName = r.GetTableName() + resolved[i].TableDef = r.GetTableDef(proc.Ctx) + } + return resolved, nil +} - var rel engine.Relation - res.Iter( - func( - partition partition.Partition, - bat *batch.Batch, - ) bool { - _, _, rel, err = op.raw.Engine.GetRelationById( - proc.Ctx, - proc.GetTxnOperator(), - partition.PartitionID, - ) - if err != nil { - return false - } +func (op *PartitionMultiUpdate) writePartitionKeyUpdate( + proc *process.Process, + target *partitionUpdateTarget, + input *batch.Batch, +) error { + mainCtx := target.contexts[0] + filtered, owned, duplicateRows, err := filterTargetRows( + proc, + mainCtx, + input, + op.raw.ctr.seenTargetRows[targetTableID(mainCtx)], + ) + if err != nil { + return err + } + if owned { + defer filtered.Clean(proc.Mp()) + } + op.raw.addAffectedRowsFunc(duplicateRows) + if filtered.RowCount() == 0 { + return nil + } - old := op.raw.MultiUpdateCtx - new := make([]*MultiUpdateCtx, 0, len(old)) - - // mapping all main table and index table to partition's. - for i, c := range op.raw.MultiUpdateCtx { - r := rel - if features.IsIndexTable(op.rawTableFlags[i]) { - r, err = op.getPartitionIndex( - proc, - op.rawTableIDs[i], - partition.PartitionID, - rel, - ) - if err != nil { - return false - } - } - - newC := c.clone() - newC.ObjRef.ObjName = r.GetTableName() - newC.TableDef = r.GetTableDef(proc.Ctx) - new = append(new, newC) - } - op.raw.MultiUpdateCtx = new + deleteContexts := clonePartitionPhaseContexts(target.contexts, true) + if err = op.writePartitionPhase( + proc, target, deleteContexts, mainCtx.PartitionCols[0], filtered, + ); err != nil { + return err + } + insertContexts := clonePartitionPhaseContexts(target.contexts, false) + return op.writePartitionPhase( + proc, target, insertContexts, mainCtx.PartitionCols[1], filtered, + ) +} - op.raw.resetMultiUpdateCtxs() - if err = op.raw.resetMultiSources(proc); err != nil { - return false - } - op.raw.mainTable = partition.PartitionID - op.raw.input = vm.CallResult{Batch: bat} +func clonePartitionPhaseContexts( + contexts []*MultiUpdateCtx, + deletePhase bool, +) []*MultiUpdateCtx { + cloned := make([]*MultiUpdateCtx, len(contexts)) + for i, ctx := range contexts { + cloned[i] = ctx.clone() + cloned[i].DedupByTargetRowID = false + if deletePhase { + cloned[i].InsertCols = nil + } else { + cloned[i].DeleteCols = nil + } + } + return cloned +} - _, err = op.raw.Call(proc) - return err == nil - }, - ) - res.Close() - if err != nil { - return vm.CallResult{}, err +func (op *PartitionMultiUpdate) writePartitionPhase( + proc *process.Process, + target *partitionUpdateTarget, + contexts []*MultiUpdateCtx, + partitionCol int, + input *batch.Batch, +) error { + res, err := partitionprune.Prune(proc, input, target.meta, int32(partitionCol)) + if err != nil { + return err + } + defer res.Close() + if res.Empty() { + return nil + } + + res.Iter(func(p partition.Partition, bat *batch.Batch) bool { + partitionContexts, resolveErr := op.resolvePartitionContexts(proc, target, contexts, p) + if resolveErr != nil { + err = resolveErr + return false } + err = op.callRawTarget(proc, target, partitionContexts, p.PartitionID, bat) + return err == nil + }) + return err +} + +func (op *PartitionMultiUpdate) callRawTarget( + proc *process.Process, + target *partitionUpdateTarget, + contexts []*MultiUpdateCtx, + mainTable uint64, + input *batch.Batch, +) error { + op.raw.MultiUpdateCtx = contexts + if op.raw.Action == UpdateWriteTable { + op.raw.cleanTargetBuffers(proc) + } + op.raw.resetMultiUpdateCtxs() + if err := op.raw.resetMultiSources(proc); err != nil { + return err + } + op.raw.mainTable = mainTable + if op.raw.Action == UpdateWriteS3 { + op.raw.mainTable = op.writerID(target, mainTable) + } + op.raw.input = vm.CallResult{Batch: input} + _, err := op.raw.Call(proc) + return err +} + +func (update *MultiUpdate) cleanTargetBuffers(proc *process.Process) { + for _, buf := range update.ctr.insertBuf { + if buf != nil { + buf.Clean(proc.Mp()) + } + } + update.ctr.insertBuf = make([]*batch.Batch, len(update.MultiUpdateCtx)) + for _, buf := range update.ctr.deleteBuf { + if buf != nil { + buf.Clean(proc.Mp()) + } + } + update.ctr.deleteBuf = make([]*batch.Batch, len(update.MultiUpdateCtx)) +} + +func (op *PartitionMultiUpdate) writerID(target *partitionUpdateTarget, physicalTableID uint64) uint64 { + if id, ok := target.writerIDs[physicalTableID]; ok { + return id } + op.nextWriterID++ + target.writerIDs[physicalTableID] = op.nextWriterID + return op.nextWriterID } func (op *PartitionMultiUpdate) ExecProjection( @@ -334,8 +465,11 @@ func (op *PartitionMultiUpdate) Free( ) { op.raw.Free(proc, pipelineFailed, err) + for _, w := range op.writers { + _ = w.free(proc) + } for _, w := range op.freeWriters { - w.free(proc) + _ = w.free(proc) } } @@ -348,7 +482,17 @@ func (op *PartitionMultiUpdate) Reset( pipelineFailed bool, err error, ) { + op.raw.MultiUpdateCtx = op.rawContexts + op.raw.resetMultiUpdateCtxs() op.raw.Reset(proc, pipelineFailed, err) + for _, writer := range op.freeWriters { + _ = writer.reset(proc) + } + for id, writer := range op.writers { + _ = writer.reset(proc) + op.freeWriters = append(op.freeWriters, writer) + delete(op.writers, id) + } } func (op *PartitionMultiUpdate) GetOperatorBase() *vm.OperatorBase { @@ -367,18 +511,19 @@ func (op *PartitionMultiUpdate) SetRejectZeroTemporal(reject bool) { func (op *PartitionMultiUpdate) getPartitionIndex( proc *process.Process, + target *partitionUpdateTarget, tableID uint64, partitionID uint64, partitionRel engine.Relation, ) (engine.Relation, error) { - for i, id := range op.mainIndexes { + for i, id := range target.mainIndexes { if id == tableID { - indexes, ok := op.partitionIndexes[partitionID] + indexes, ok := target.partitionIndexes[partitionID] if ok { return indexes[i], nil } - relations := make([]engine.Relation, 0, len(op.meta.Partitions)) + relations := make([]engine.Relation, 0, len(target.meta.Partitions)) for _, index := range partitionRel.GetExtraInfo().IndexTables { _, _, rel, err := op.raw.Engine.GetRelationById( proc.Ctx, @@ -390,7 +535,7 @@ func (op *PartitionMultiUpdate) getPartitionIndex( } relations = append(relations, rel) } - op.partitionIndexes[partitionID] = relations + target.partitionIndexes[partitionID] = relations return relations[i], nil } @@ -444,6 +589,9 @@ func (ctx *MultiUpdateCtx) clone() *MultiUpdateCtx { SkipInsertOnNullPk: ctx.SkipInsertOnNullPk, InsertPkColIdx: ctx.InsertPkColIdx, IgnoreAffectedRows: ctx.IgnoreAffectedRows, + DedupByTargetRowID: ctx.DedupByTargetRowID, + TargetUpdateCtxIdx: ctx.TargetUpdateCtxIdx, + TargetTableID: ctx.TargetTableID, } objRef := *ctx.ObjRef def := *ctx.TableDef diff --git a/pkg/sql/colexec/multi_update/multi_update_partition_test.go b/pkg/sql/colexec/multi_update/multi_update_partition_test.go index 6e06f227e5190..c46b355ea7c5e 100644 --- a/pkg/sql/colexec/multi_update/multi_update_partition_test.go +++ b/pkg/sql/colexec/multi_update/multi_update_partition_test.go @@ -19,10 +19,49 @@ import ( "testing" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/pb/plan" + "github.com/matrixorigin/matrixone/pkg/sql/features" + "github.com/matrixorigin/matrixone/pkg/testutil" "github.com/stretchr/testify/require" ) +func TestPartitionMultiUpdateForwardsAllocationAccountLifecycle(t *testing.T) { + registry, err := mpool.NewAllocationAccountRegistry(1, 16) + require.NoError(t, err) + account, err := registry.Open(1 << 20) + require.NoError(t, err) + + raw := &MultiUpdate{} + op := &PartitionMultiUpdate{raw: raw} + require.False(t, op.ActivatesAllocationAccountLifecycle()) + require.NoError(t, op.SetAllocationAccount(account)) + require.Same(t, account, raw.allocationAccount) + require.NoError(t, op.ClearAllocationAccount(account)) + require.Nil(t, raw.allocationAccount) +} + +func TestClonePartitionPhaseContextsSeparatesDeleteAndInsert(t *testing.T) { + contexts := []*MultiUpdateCtx{{ + ObjRef: &plan.ObjectRef{}, + TableDef: &plan.TableDef{}, + InsertCols: []int{1, 2}, + DeleteCols: []int{3, 4}, + DedupByTargetRowID: true, + }} + deleteContexts := clonePartitionPhaseContexts(contexts, true) + insertContexts := clonePartitionPhaseContexts(contexts, false) + + require.Empty(t, deleteContexts[0].InsertCols) + require.Equal(t, []int{3, 4}, deleteContexts[0].DeleteCols) + require.Empty(t, insertContexts[0].DeleteCols) + require.Equal(t, []int{1, 2}, insertContexts[0].InsertCols) + require.False(t, deleteContexts[0].DedupByTargetRowID) + require.False(t, insertContexts[0].DedupByTargetRowID) + require.Equal(t, []int{1, 2}, contexts[0].InsertCols) + require.Equal(t, []int{3, 4}, contexts[0].DeleteCols) +} + func TestResetMultiUpdateCtxsClassifiesTemporaryIndexTables(t *testing.T) { uniqueName := "__mo_tmp_018f1f767b9d7f35b2d99b8d7774bde8_db_" + catalog.UniqueIndexTableNamePrefix + "0198fa2b-7cc8-7ed1-b7ae-a3d9c29e75fd" @@ -48,10 +87,58 @@ func TestPartitionMultiUpdateString(t *testing.T) { require.Equal(t, "MultiUpdate: partition_multi_update", buf.String()) } +func TestBuildPartitionUpdateTargetsKeepsPhysicalTargetsIndependent(t *testing.T) { + contexts := []*MultiUpdateCtx{ + { + ObjRef: &plan.ObjectRef{}, + TableDef: &plan.TableDef{TblId: 10, Name: "plain"}, + TargetUpdateCtxIdx: 0, + }, + { + ObjRef: &plan.ObjectRef{}, + TableDef: &plan.TableDef{ + TblId: 20, + Name: "partitioned", + FeatureFlag: features.Partitioned, + }, + TargetUpdateCtxIdx: 1, + }, + { + ObjRef: &plan.ObjectRef{}, + TableDef: &plan.TableDef{ + TblId: 21, + Name: "partition_index", + FeatureFlag: features.IndexTable, + }, + TargetUpdateCtxIdx: 1, + }, + } + + targets := buildPartitionUpdateTargets(contexts) + + require.Len(t, targets, 2) + require.Equal(t, uint64(10), targets[0].tableID) + require.Len(t, targets[0].contexts, 1) + require.Equal(t, uint64(20), targets[1].tableID) + require.Len(t, targets[1].contexts, 2) + require.Equal(t, 0, targets[1].contexts[1].TargetUpdateCtxIdx) + require.NotSame(t, contexts[1].TableDef, targets[1].contexts[0].TableDef) + require.NotSame(t, contexts[1], targets[1].contexts[0]) +} + +func TestPartitionWriterIDsSeparateAliasesOfSamePhysicalTable(t *testing.T) { + first := &partitionUpdateTarget{writerIDs: make(map[uint64]uint64)} + second := &partitionUpdateTarget{writerIDs: make(map[uint64]uint64)} + op := &PartitionMultiUpdate{} + + firstID := op.writerID(first, 100) + require.Equal(t, firstID, op.writerID(first, 100)) + require.NotEqual(t, firstID, op.writerID(second, 100)) +} + func TestNewPartitionMultiUpdateFrom(t *testing.T) { ps := &PartitionMultiUpdate{ - raw: &MultiUpdate{RejectZeroTemporal: true}, - tableID: 1, + raw: &MultiUpdate{RejectZeroTemporal: true}, } op := NewPartitionMultiUpdateFrom(ps) require.Equal(t, ps.raw.MultiUpdateCtx, op.(*PartitionMultiUpdate).raw.MultiUpdateCtx) @@ -59,7 +146,6 @@ func TestNewPartitionMultiUpdateFrom(t *testing.T) { require.Equal(t, ps.raw.IsOnduplicateKeyUpdate, op.(*PartitionMultiUpdate).raw.IsOnduplicateKeyUpdate) require.Equal(t, ps.raw.Engine, op.(*PartitionMultiUpdate).raw.Engine) require.Equal(t, ps.raw.RejectZeroTemporal, op.(*PartitionMultiUpdate).raw.RejectZeroTemporal) - require.Equal(t, ps.tableID, op.(*PartitionMultiUpdate).tableID) } func TestPartitionMultiUpdateSetRejectZeroTemporalUpdatesWriters(t *testing.T) { @@ -77,6 +163,27 @@ func TestPartitionMultiUpdateSetRejectZeroTemporalUpdatesWriters(t *testing.T) { require.True(t, free.rejectZeroTemporal) } +func TestPartitionMultiUpdateResetRebuildsRawContextMetadata(t *testing.T) { + proc := testutil.NewProcess(t) + original := &MultiUpdateCtx{TableDef: &plan.TableDef{Name: "logical"}} + raw := &MultiUpdate{ + MultiUpdateCtx: []*MultiUpdateCtx{original}, + ctr: container{updateCtxInfos: map[string]*updateCtxInfo{ + "physical_partition": {}, + }}, + } + op := &PartitionMultiUpdate{ + raw: raw, + rawContexts: []*MultiUpdateCtx{original}, + } + + op.Reset(proc, false, nil) + + require.Same(t, original, raw.MultiUpdateCtx[0]) + require.Contains(t, raw.ctr.updateCtxInfos, "logical") + require.NotContains(t, raw.ctr.updateCtxInfos, "physical_partition") +} + func TestAddInsertAffectRows(t *testing.T) { tests := []struct { name string @@ -252,11 +359,13 @@ func TestDeleteAffectedRows(t *testing.T) { // PartitionCols and keeps nested objects independent. func TestMultiUpdateCtxClonePartitionCols(t *testing.T) { original := &MultiUpdateCtx{ - InsertCols: []int{1, 2, 3}, - DeleteCols: []int{4, 5}, - PartitionCols: []int{6, 7, 8, 9}, - ObjRef: &plan.ObjectRef{SchemaName: "test", ObjName: "t1"}, - TableDef: &plan.TableDef{Name: "t1"}, + InsertCols: []int{1, 2, 3}, + DeleteCols: []int{4, 5}, + PartitionCols: []int{6, 7, 8, 9}, + DedupByTargetRowID: true, + TargetUpdateCtxIdx: 10, + ObjRef: &plan.ObjectRef{SchemaName: "test", ObjName: "t1"}, + TableDef: &plan.TableDef{Name: "t1"}, } cloned := original.clone() @@ -267,6 +376,8 @@ func TestMultiUpdateCtxClonePartitionCols(t *testing.T) { "PartitionCols should not be DeleteCols") require.Equal(t, original.InsertCols, cloned.InsertCols) require.Equal(t, original.DeleteCols, cloned.DeleteCols) + require.True(t, cloned.DedupByTargetRowID) + require.Equal(t, original.TargetUpdateCtxIdx, cloned.TargetUpdateCtxIdx) require.Equal(t, original.ObjRef.SchemaName, cloned.ObjRef.SchemaName) require.Equal(t, original.TableDef.Name, cloned.TableDef.Name) require.NotSame(t, original.ObjRef, cloned.ObjRef) diff --git a/pkg/sql/colexec/multi_update/s3writer_delegate.go b/pkg/sql/colexec/multi_update/s3writer_delegate.go index 91d6a534776fa..fbfd6785ec6cd 100644 --- a/pkg/sql/colexec/multi_update/s3writer_delegate.go +++ b/pkg/sql/colexec/multi_update/s3writer_delegate.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/hashmap" "github.com/matrixorigin/matrixone/pkg/common/moerr" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" @@ -113,8 +114,11 @@ type s3WriterDelegate struct { batchSize uint64 flushThreshold uint64 - checkSizeCols []int - buf bytes.Buffer + checkSizeCols []int + buf bytes.Buffer + addAffectedRows func(uint64) + seenTargetRows map[uint64]*hashmap.StrHashMap + admitSeenGrowth func(int64) error memController struct { grantedSize int64 @@ -145,6 +149,9 @@ func newS3Writer( insertFreeLists: make([]*containers.BatchFreeList, tableCount), isRemote: update.IsRemote, rejectZeroTemporal: update.RejectZeroTemporal, + addAffectedRows: update.addAffectedRowsFunc, + seenTargetRows: update.ctr.seenTargetRows, + admitSeenGrowth: update.admitSeenTargetRowsGrowth, } for i := range writer.insertFreeLists { writer.insertFreeLists[i] = containers.NewBatchFreeList(nil, nil, true) @@ -158,12 +165,7 @@ func newS3Writer( faultInjected := false - mainIdx := 0 - for i, updateCtx := range update.MultiUpdateCtx { - if update.ctr.updateCtxInfos[updateCtx.TableDef.Name].tableType == UpdateMainTable { - mainIdx = i - } - + for _, updateCtx := range update.MultiUpdateCtx { if !faultInjected { faultInjected, _ = objectio.LogCNFlushSmallObjsInjected( updateCtx.TableDef.DbName, updateCtx.TableDef.Name, @@ -180,28 +182,47 @@ func newS3Writer( threshold = colexec.FaultInjectedS3Threshold } - upCtx := writer.updateCtxs[mainIdx] - if len(upCtx.DeleteCols) > 0 && len(upCtx.InsertCols) > 0 { - //update - writer.action = actionUpdate - writer.flushThreshold = threshold - writer.checkSizeCols = append(writer.checkSizeCols, upCtx.InsertCols...) - writer.checkSizeCols = append(writer.checkSizeCols, upCtx.DeleteCols...) - } else if len(upCtx.InsertCols) > 0 { - //insert - writer.action = actionInsert - writer.flushThreshold = threshold - writer.checkSizeCols = append(writer.checkSizeCols, upCtx.InsertCols...) - } else { - //delete - writer.action = actionDelete + writer.action = s3WriterAction(writer.updateCtxs) + if writer.action == actionDelete { writer.flushThreshold = DeleteWriteS3Threshold - writer.checkSizeCols = append(writer.checkSizeCols, upCtx.DeleteCols...) + } else { + writer.flushThreshold = threshold } + writer.checkSizeCols = retainedS3InputCols(writer.updateCtxs, writer.action) return writer, nil } +func s3WriterAction(updateCtxs []*MultiUpdateCtx) actionType { + hasInsert := false + hasDelete := false + for _, updateCtx := range updateCtxs { + hasInsert = hasInsert || len(updateCtx.InsertCols) > 0 + hasDelete = hasDelete || len(updateCtx.DeleteCols) > 0 + } + if hasInsert && hasDelete { + return actionUpdate + } + if hasInsert { + return actionInsert + } + return actionDelete +} + +func retainedS3InputCols(updateCtxs []*MultiUpdateCtx, action actionType) []int { + var cols []int + for _, updateCtx := range updateCtxs { + if action != actionDelete { + cols = append(cols, updateCtx.InsertCols...) + } + if action != actionInsert && len(updateCtx.DeleteCols) > 0 { + deleteColCount := min(2, len(updateCtx.DeleteCols)) + cols = append(cols, updateCtx.DeleteCols[:deleteColCount]...) + } + } + return cols +} + // ensureInsertSinkers lazily creates persistent per-table insert sinkers // on first call. Requires proc for Mp() and fileservice. func (writer *s3WriterDelegate) ensureInsertSinkers(proc *process.Process) error { @@ -260,6 +281,42 @@ func (writer *s3WriterDelegate) append( } mp := proc.Mp() + seenSizeBefore := writer.seenTargetRowsSize() + targetBatches := make(map[int]*batch.Batch) + defer func() { + for _, targetBatch := range targetBatches { + if targetBatch != inBatch { + targetBatch.Clean(mp) + } + } + }() + contextBatches := make([]*batch.Batch, len(writer.updateCtxs)) + for i, updateCtx := range writer.updateCtxs { + targetIdx := updateCtx.TargetUpdateCtxIdx + if targetIdx < 0 || targetIdx >= len(writer.updateCtxs) { + return moerr.NewInternalError(proc.Ctx, "invalid multi-target update context index") + } + targetBatch, ok := targetBatches[targetIdx] + if !ok { + var duplicateRows uint64 + targetBatch, _, duplicateRows, err = filterTargetRows( + proc, + writer.updateCtxs[targetIdx], + inBatch, + writer.seenTargetRows[targetTableID(writer.updateCtxs[targetIdx])], + ) + if err != nil { + return err + } + writer.addAffectedRows(duplicateRows) + targetBatches[targetIdx] = targetBatch + } + contextBatches[i] = targetBatch + } + seenIncrement := writer.seenTargetRowsSize() - seenSizeBefore + if err = writer.admitSeenGrowth(seenIncrement); err != nil { + return err + } // Route insert columns directly to per-table sinkers (no clone). // Auto-spill S3 writes during Write use proc.Ctx; perfcounter tracking @@ -268,8 +325,12 @@ func (writer *s3WriterDelegate) append( if len(updateCtx.InsertCols) == 0 || writer.insertSinkers[i] == nil { continue } + contextBatch := contextBatches[i] + if contextBatch.RowCount() == 0 { + continue + } insertAttrs := writer.updateCtxInfos[updateCtx.TableDef.Name].insertAttrs - projBat := inBatch.SelectColumns(updateCtx.InsertCols, insertAttrs) + projBat := contextBatch.SelectColumns(updateCtx.InsertCols, insertAttrs) tableType := writer.updateCtxInfos[updateCtx.TableDef.Name].tableType @@ -303,7 +364,7 @@ func (writer *s3WriterDelegate) append( for insertIdx, inputIdx := range updateCtx.InsertCols { col := updateCtx.TableDef.Cols[insertIdx] if col.Default != nil && !col.Default.NullAbility && !strings.HasPrefix(col.Name, catalog.PrefixCBColName) { - if inBatch.Vecs[inputIdx].HasNull() { + if contextBatch.Vecs[inputIdx].HasNull() { return moerr.NewConstraintViolation(proc.Ctx, fmt.Sprintf("Column '%s' cannot be null", col.Name)) } } @@ -367,10 +428,14 @@ func (writer *s3WriterDelegate) append( if len(updateCtx.DeleteCols) == 0 { continue } + contextBatch := contextBatches[i] + if contextBatch.RowCount() == 0 { + continue + } if writer.deleteBatches[i] == nil { writer.deleteBatches[i] = batch.NewBatchSet(objectio.BlockMaxRows) } - projBat := inBatch.SelectColumns(updateCtx.DeleteCols, DeleteBatchAttrs) + projBat := contextBatch.SelectColumns(updateCtx.DeleteCols[:2], DeleteBatchAttrs) if _, err = writer.deleteBatches[i].Extend(mp, projBat, nil); err != nil { return } @@ -403,6 +468,14 @@ func (writer *s3WriterDelegate) append( return } +func (writer *s3WriterDelegate) seenTargetRowsSize() int64 { + var size int64 + for _, seen := range writer.seenTargetRows { + size += seen.Size() + } + return size +} + func checkMainTableNotNull(proc *process.Process, updateCtx *MultiUpdateCtx, bat *batch.Batch) error { for insertIdx := range updateCtx.InsertCols { col := updateCtx.TableDef.Cols[insertIdx] diff --git a/pkg/sql/colexec/multi_update/types.go b/pkg/sql/colexec/multi_update/types.go index 9828987e9a784..1f319916792eb 100644 --- a/pkg/sql/colexec/multi_update/types.go +++ b/pkg/sql/colexec/multi_update/types.go @@ -15,8 +15,12 @@ package multi_update import ( + "github.com/matrixorigin/matrixone/pkg/common/hashmap" + "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/common/reuse" + "github.com/matrixorigin/matrixone/pkg/common/rscthrottler" "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/hashtable" "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/vm" "github.com/matrixorigin/matrixone/pkg/vm/engine" @@ -27,6 +31,14 @@ var _ vm.Operator = new(MultiUpdate) const opName = "MultiUpdate" +const multiUpdateAllocationOwner mpool.AllocationOwner = 1 + +const ( + multiUpdateAllocationSiteHashCell mpool.AllocationSite = iota + 1 + multiUpdateAllocationSiteHashDescriptor + multiUpdateAllocationSiteHashIterator +) + type UpdateAction int const ( @@ -82,9 +94,70 @@ type MultiUpdate struct { getFlushableS3WriterFunc func() *s3WriterDelegate addAffectedRowsFunc func(uint64) + allocationAccount *mpool.AllocationAccount + mapAllocation *hashtable.AllocationAccountSelection + iteratorAllocation *hashmap.IteratorAllocation + vm.OperatorBase } +func (update *MultiUpdate) SetAllocationAccount(account *mpool.AllocationAccount) error { + if account == nil { + return mpool.ErrAllocationAccountInvalid + } + if update.allocationAccount != nil { + if update.allocationAccount == account { + return nil + } + return mpool.ErrAllocationAccountMismatch + } + selection, err := hashtable.NewAllocationAccountSelection( + account, + multiUpdateAllocationOwner, + multiUpdateAllocationSiteHashCell, + multiUpdateAllocationSiteHashDescriptor, + ) + if err != nil { + return err + } + iteratorAllocation, err := hashmap.NewIteratorAllocation( + account, + multiUpdateAllocationOwner, + multiUpdateAllocationSiteHashIterator, + ) + if err != nil { + return err + } + update.allocationAccount = account + update.mapAllocation = selection + update.iteratorAllocation = iteratorAllocation + return nil +} + +func (update *MultiUpdate) ClearAllocationAccount(account *mpool.AllocationAccount) error { + if update.allocationAccount == nil { + return nil + } + if update.allocationAccount != account { + return mpool.ErrAllocationAccountMismatch + } + if len(update.ctr.seenTargetRows) != 0 { + return mpool.ErrAllocationAccountInvariant + } + update.allocationAccount = nil + update.mapAllocation = nil + update.iteratorAllocation = nil + return nil +} + +// MultiUpdate participates in an allocation generation when another operator +// (normally the join feeding a multi-target UPDATE) activates it. It must not +// activate the statement-wide lifecycle by itself because ordinary single- +// table writes do not need the physical-target deduplication map. +func (update *MultiUpdate) ActivatesAllocationAccountLifecycle() bool { + return false +} + type updateCtxInfo struct { Source engine.Relation tableType UpdateTableType @@ -105,6 +178,10 @@ type container struct { insertBuf []*batch.Batch deleteBuf []*batch.Batch + + seenTargetRows map[uint64]*hashmap.StrHashMap + seenRowsGrant int64 + seenRowsRSC rscthrottler.RSCThrottler } type MultiUpdateCtx struct { @@ -118,6 +195,14 @@ type MultiUpdateCtx struct { // used with SkipInsertOnNullPk for REPLACE delete-only rows. InsertPkColIdx int IgnoreAffectedRows bool + // DedupByTargetRowID makes this context consume only the whole input row + // selected for its physical target row. The planner supplies an independent + // row_number() partition for every updated target table. + DedupByTargetRowID bool + TargetUpdateCtxIdx int + // TargetTableID stays logical when a partition wrapper replaces TableDef + // with a physical partition definition. + TargetTableID uint64 } func (update MultiUpdate) TypeName() string { @@ -160,7 +245,7 @@ func (update *MultiUpdate) Reset(proc *process.Process, pipelineFailed bool, err if update.ctr.s3Writer != nil { update.ctr.s3Writer.reset(proc) } - + update.freeSeenTargetRows() update.ctr.state = vm.Build } @@ -184,11 +269,24 @@ func (update *MultiUpdate) Free(proc *process.Process, pipelineFailed bool, err update.ctr.s3Writer.free(proc) update.ctr.s3Writer = nil } + update.freeSeenTargetRows() update.ctr.updateCtxInfos = nil update.ctr.sources = nil } +func (update *MultiUpdate) freeSeenTargetRows() { + if update.ctr.seenRowsGrant > 0 { + update.ctr.seenRowsRSC.Release(update.ctr.seenRowsGrant) + update.ctr.seenRowsGrant = 0 + } + update.ctr.seenRowsRSC = nil + for _, seen := range update.ctr.seenTargetRows { + seen.Free() + } + update.ctr.seenTargetRows = nil +} + func (update *MultiUpdate) ExecProjection(proc *process.Process, input *batch.Batch) (*batch.Batch, error) { return input, nil } diff --git a/pkg/sql/colexec/multi_update/update_test.go b/pkg/sql/colexec/multi_update/update_test.go index 6451b1954dd9f..be874ca5f9bf3 100644 --- a/pkg/sql/colexec/multi_update/update_test.go +++ b/pkg/sql/colexec/multi_update/update_test.go @@ -20,8 +20,10 @@ import ( "testing" "github.com/matrixorigin/matrixone/pkg/catalog" + "github.com/matrixorigin/matrixone/pkg/common/hashmap" "github.com/matrixorigin/matrixone/pkg/common/mpool" "github.com/matrixorigin/matrixone/pkg/container/batch" + "github.com/matrixorigin/matrixone/pkg/container/hashtable" "github.com/matrixorigin/matrixone/pkg/container/types" "github.com/matrixorigin/matrixone/pkg/container/vector" "github.com/matrixorigin/matrixone/pkg/sql/colexec" @@ -64,6 +66,390 @@ func TestUpdateTableWithUniqueKey(t *testing.T) { runTestCases(t, proc, []*testCase{case1}) } +func TestFilterTargetRowsKeepsIndependentWholeRows(t *testing.T) { + proc := testutil.NewProcess(t) + mp := proc.Mp() + + bat := batch.NewWithSize(5) + bat.Vecs[0] = testutil.MakeRowIdVector( + []types.Rowid{ + types.BuildTestRowid(1, 1), + types.BuildTestRowid(1, 1), + types.BuildTestRowid(1, 2), + types.BuildTestRowid(1, 3), + }, + []uint64{3}, + mp, + ) + bat.Vecs[1] = testutil.NewInt64Vector( + 4, + types.T_int64.ToType(), + mp, + false, + nil, + []int64{1, 2, 1, 1}, + ) + bat.Vecs[2] = testutil.MakeRowIdVector( + []types.Rowid{ + types.BuildTestRowid(2, 1), + types.BuildTestRowid(2, 2), + types.BuildTestRowid(2, 2), + types.BuildTestRowid(2, 3), + }, + nil, + mp, + ) + bat.Vecs[3] = testutil.NewInt64Vector( + 4, + types.T_int64.ToType(), + mp, + false, + nil, + []int64{1, 1, 2, 1}, + ) + bat.Vecs[4] = testutil.NewInt32Vector( + 4, + types.T_int32.ToType(), + mp, + false, + nil, + []int32{10, 20, 30, 40}, + ) + bat.SetRowCount(4) + defer bat.Clean(mp) + + first, clean, duplicateRows, err := filterTargetRows(proc, &MultiUpdateCtx{ + TableDef: &plan.TableDef{TblId: 1}, + DedupByTargetRowID: true, + DeleteCols: []int{0, 4, 1}, + }, bat, nil) + require.NoError(t, err) + require.True(t, clean) + require.Zero(t, duplicateRows) + defer first.Clean(mp) + require.Equal(t, []int32{10, 30}, vector.MustFixedColWithTypeCheck[int32](first.Vecs[4])) + + second, clean, duplicateRows, err := filterTargetRows(proc, &MultiUpdateCtx{ + TableDef: &plan.TableDef{TblId: 2}, + DedupByTargetRowID: true, + DeleteCols: []int{2, 4, 3}, + }, bat, nil) + require.NoError(t, err) + require.True(t, clean) + require.Zero(t, duplicateRows) + defer second.Clean(mp) + require.Equal(t, []int32{10, 20, 40}, vector.MustFixedColWithTypeCheck[int32](second.Vecs[4])) +} + +func TestFilterTargetRowsDedupsAliasesAcrossBatchesWithAccountedHashMap(t *testing.T) { + proc := testutil.NewProcess(t) + mp := proc.Mp() + rowID1 := types.BuildTestRowid(1, 1) + rowID2 := types.BuildTestRowid(1, 2) + makeBatch := func() *batch.Batch { + bat := batch.NewWithSize(3) + bat.Vecs[0] = testutil.MakeRowIdVector([]types.Rowid{rowID1, rowID2}, nil, mp) + bat.Vecs[1] = testutil.NewInt64Vector( + 2, + types.T_int64.ToType(), + mp, + false, + nil, + []int64{1, 1}, + ) + bat.Vecs[2] = testutil.NewInt32Vector( + 2, + types.T_int32.ToType(), + mp, + false, + nil, + []int32{10, 20}, + ) + bat.SetRowCount(2) + return bat + } + updateCtx := &MultiUpdateCtx{ + TableDef: &plan.TableDef{TblId: 42}, + DedupByTargetRowID: true, + DeleteCols: []int{0, 2, 1}, + } + registry, err := mpool.NewAllocationAccountRegistry(1, 16) + require.NoError(t, err) + account, err := registry.Open(1 << 20) + require.NoError(t, err) + selection, err := hashtable.NewAllocationAccountSelection( + account, + multiUpdateAllocationOwner, + multiUpdateAllocationSiteHashCell, + multiUpdateAllocationSiteHashDescriptor, + ) + require.NoError(t, err) + iteratorAllocation, err := hashmap.NewIteratorAllocation( + account, + multiUpdateAllocationOwner, + multiUpdateAllocationSiteHashIterator, + ) + require.NoError(t, err) + seen, err := hashmap.NewStrHashMapWithAllocations( + false, + mp, + selection, + iteratorAllocation, + ) + require.NoError(t, err) + defer seen.Free() + + firstInput := makeBatch() + defer firstInput.Clean(mp) + first, clean, duplicateRows, err := filterTargetRows(proc, updateCtx, firstInput, seen) + require.NoError(t, err) + require.True(t, clean) + defer first.Clean(mp) + require.Equal(t, 2, first.RowCount()) + require.Zero(t, duplicateRows) + + secondInput := makeBatch() + defer secondInput.Clean(mp) + second, clean, duplicateRows, err := filterTargetRows(proc, updateCtx, secondInput, seen) + require.NoError(t, err) + require.True(t, clean) + defer second.Clean(mp) + require.Zero(t, second.RowCount()) + require.Equal(t, uint64(2), duplicateRows) + require.Positive(t, seen.Size()) +} + +func TestFilterTargetRowsSkipsInactivePhysicalTargetBranch(t *testing.T) { + proc := testutil.NewProcess(t) + mp := proc.Mp() + + bat := batch.NewWithSize(4) + bat.Vecs[0] = testutil.MakeRowIdVector( + []types.Rowid{ + types.BuildTestRowid(1, 1), + types.BuildTestRowid(1, 2), + types.BuildTestRowid(1, 3), + }, + nil, + mp, + ) + bat.Vecs[1] = testutil.NewInt64Vector( + 3, + types.T_int64.ToType(), + mp, + false, + nil, + []int64{1, 1, 2}, + ) + bat.Vecs[2] = testutil.NewBoolVector( + 3, + types.T_bool.ToType(), + mp, + false, + nil, + []bool{false, true, true}, + ) + bat.Vecs[3] = testutil.NewInt32Vector( + 3, + types.T_int32.ToType(), + mp, + false, + nil, + []int32{10, 20, 30}, + ) + bat.SetRowCount(3) + defer bat.Clean(mp) + + filtered, clean, duplicateRows, err := filterTargetRows(proc, &MultiUpdateCtx{ + TableDef: &plan.TableDef{TblId: 42}, + DedupByTargetRowID: true, + DeleteCols: []int{0, 3, 1, 2}, + }, bat, nil) + require.NoError(t, err) + require.True(t, clean) + require.Zero(t, duplicateRows) + defer filtered.Clean(mp) + require.Equal(t, []int32{20}, vector.MustFixedColWithTypeCheck[int32](filtered.Vecs[3])) +} + +func TestFilterTargetRowsReadsConstantActiveSelectorLogically(t *testing.T) { + proc := testutil.NewProcess(t) + mp := proc.Mp() + + bat := batch.NewWithSize(4) + bat.Vecs[0] = testutil.MakeRowIdVector( + []types.Rowid{ + types.BuildTestRowid(1, 1), + types.BuildTestRowid(1, 2), + types.BuildTestRowid(1, 3), + }, + nil, + mp, + ) + bat.Vecs[1] = testutil.NewInt64Vector( + 3, + types.T_int64.ToType(), + mp, + false, + nil, + []int64{1, 1, 1}, + ) + active, err := vector.NewConstFixed(types.T_bool.ToType(), true, 3, mp) + require.NoError(t, err) + bat.Vecs[2] = active + bat.Vecs[3] = testutil.NewInt32Vector( + 3, + types.T_int32.ToType(), + mp, + false, + nil, + []int32{10, 20, 30}, + ) + bat.SetRowCount(3) + defer bat.Clean(mp) + + filtered, clean, duplicateRows, err := filterTargetRows(proc, &MultiUpdateCtx{ + TableDef: &plan.TableDef{TblId: 42}, + DedupByTargetRowID: true, + DeleteCols: []int{0, 3, 1, 2}, + }, bat, nil) + require.NoError(t, err) + require.True(t, clean) + require.Zero(t, duplicateRows) + defer filtered.Clean(mp) + require.Equal(t, []int32{10, 20, 30}, vector.MustFixedColWithTypeCheck[int32](filtered.Vecs[3])) +} + +type testSeenRowsThrottler struct { + available int64 + acquired int64 + released int64 +} + +func (m *testSeenRowsThrottler) Refresh() {} +func (m *testSeenRowsThrottler) PrintUsage() {} +func (m *testSeenRowsThrottler) Available() int64 { + return m.available +} +func (m *testSeenRowsThrottler) Acquire(size int64) (int64, bool) { + if size > m.available { + return m.available, false + } + m.available -= size + m.acquired += size + return m.available, true +} +func (m *testSeenRowsThrottler) Release(size int64) int64 { + m.available += size + m.released += size + return m.available +} + +func TestSeenTargetRowsGrowthUsesS3MemoryAdmission(t *testing.T) { + throttler := &testSeenRowsThrottler{available: 128} + update := &MultiUpdate{} + update.ctr.seenRowsRSC = throttler + + require.NoError(t, update.admitSeenTargetRowsGrowth(96)) + require.Equal(t, int64(96), update.ctr.seenRowsGrant) + require.Equal(t, int64(96), throttler.acquired) + require.Error(t, update.admitSeenTargetRowsGrowth(64)) + require.Equal(t, int64(96), update.ctr.seenRowsGrant) + + update.freeSeenTargetRows() + require.Equal(t, int64(96), throttler.released) + require.Zero(t, update.ctr.seenRowsGrant) + require.Nil(t, update.ctr.seenRowsRSC) +} + +func TestRetainedS3InputColsCountsEveryContextCopy(t *testing.T) { + updateCtxs := []*MultiUpdateCtx{ + { + InsertCols: []int{0, 1, 2}, + DeleteCols: []int{3, 4, 9}, + }, + { + InsertCols: []int{0, 5}, + DeleteCols: []int{6, 7}, + }, + { + InsertCols: []int{8, 2}, + DeleteCols: []int{10, 11}, + }, + } + + require.Equal( + t, + []int{0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 2, 10, 11}, + retainedS3InputCols(updateCtxs, actionUpdate), + ) + require.Equal( + t, + []int{0, 1, 2, 0, 5, 8, 2}, + retainedS3InputCols(updateCtxs, actionInsert), + ) + require.Equal( + t, + []int{3, 4, 6, 7, 10, 11}, + retainedS3InputCols(updateCtxs, actionDelete), + ) +} + +func TestS3WriterActionDoesNotRequireMainTableContext(t *testing.T) { + tests := []struct { + name string + updateCtxs []*MultiUpdateCtx + want actionType + }{ + { + name: "index backfill insert", + updateCtxs: []*MultiUpdateCtx{ + {InsertCols: []int{0, 1}}, + {InsertCols: []int{2, 3}}, + }, + want: actionInsert, + }, + { + name: "delete only", + updateCtxs: []*MultiUpdateCtx{{DeleteCols: []int{0, 1}}}, + want: actionDelete, + }, + { + name: "mixed contexts", + updateCtxs: []*MultiUpdateCtx{ + {InsertCols: []int{0, 1}}, + {DeleteCols: []int{2, 3}}, + }, + want: actionUpdate, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require.Equal(t, test.want, s3WriterAction(test.updateCtxs)) + }) + } +} + +func TestNewS3WriterAllowsIndexOnlyContext(t *testing.T) { + _, _, proc := prepareTestCtx(t, false) + objRef, tableDef := getTestSecondaryIndexTable("index_backfill") + updateCtx := &MultiUpdateCtx{ + ObjRef: objRef, + TableDef: tableDef, + InsertCols: []int{0, 1}, + } + update := &MultiUpdate{MultiUpdateCtx: []*MultiUpdateCtx{updateCtx}} + update.resetMultiUpdateCtxs() + + writer, err := newS3Writer(proc.GetService(), update) + require.NoError(t, err) + require.Equal(t, actionInsert, writer.action) + require.Equal(t, InsertWriteS3Threshold, writer.flushThreshold) + require.Equal(t, []int{0, 1}, writer.checkSizeCols) + require.NoError(t, writer.free(proc)) +} + // update table s3 func TestUpdateS3SingleTable(t *testing.T) { hasUniqueKey := false diff --git a/pkg/sql/compile/operator.go b/pkg/sql/compile/operator.go index d5bc668b125fd..701c28df401e1 100644 --- a/pkg/sql/compile/operator.go +++ b/pkg/sql/compile/operator.go @@ -917,19 +917,32 @@ func constructMultiUpdate( SkipInsertOnNullPk: updateCtx.SkipInsertOnNullPk, InsertPkColIdx: int(updateCtx.InsertPkColIdx), IgnoreAffectedRows: updateCtx.IgnoreAffectedRows, + DedupByTargetRowID: updateCtx.DedupByTargetRowId, + TargetUpdateCtxIdx: int(updateCtx.TargetUpdateCtxIdx), + TargetTableID: updateCtx.TableDef.TblId, } } arg.Action = action ps := proc.GetPartitionService() - if !ps.Enabled() || !features.IsPartitioned(node.UpdateCtxList[0].TableDef.FeatureFlag) { + if !ps.Enabled() { return arg, nil } + if !hasPartitionedUpdateTarget(node.UpdateCtxList) { + return arg, nil + } + + return multi_update.NewPartitionMultiUpdate(arg), nil +} - return multi_update.NewPartitionMultiUpdate( - arg, - node.UpdateCtxList[0].TableDef.TblId, - ), nil +func hasPartitionedUpdateTarget(contexts []*plan.UpdateCtx) bool { + for _, updateCtx := range contexts { + if !features.IsIndexTable(updateCtx.TableDef.FeatureFlag) && + features.IsPartitioned(updateCtx.TableDef.FeatureFlag) { + return true + } + } + return false } func constructInsert( diff --git a/pkg/sql/compile/operator_test.go b/pkg/sql/compile/operator_test.go index c7603e5666729..1817bf8ab1d01 100644 --- a/pkg/sql/compile/operator_test.go +++ b/pkg/sql/compile/operator_test.go @@ -41,6 +41,7 @@ import ( "github.com/matrixorigin/matrixone/pkg/sql/colexec/rightdedupjoin" "github.com/matrixorigin/matrixone/pkg/sql/colexec/shuffle" "github.com/matrixorigin/matrixone/pkg/sql/colexec/table_function" + "github.com/matrixorigin/matrixone/pkg/sql/features" sqlmongodb "github.com/matrixorigin/matrixone/pkg/sql/mongodb" plan2 "github.com/matrixorigin/matrixone/pkg/sql/plan" "github.com/matrixorigin/matrixone/pkg/sql/plan/function" @@ -261,13 +262,26 @@ func TestDupOperatorMergeOrder(t *testing.T) { func TestDupOperatorPartitionMultiUpdate(t *testing.T) { innerOp := multi_update.NewArgument() - op := multi_update.NewPartitionMultiUpdate(innerOp, 1) + op := multi_update.NewPartitionMultiUpdate(innerOp) result := dupOperator(op, 0, 1) if result == nil { t.Fatal("dupOperator returned nil for PartitionMultiUpdate") } } +func TestHasPartitionedUpdateTargetChecksEveryMainContext(t *testing.T) { + contexts := []*plan.UpdateCtx{ + {TableDef: &plan.TableDef{TblId: 1}}, + {TableDef: &plan.TableDef{TblId: 2, FeatureFlag: features.Partitioned}}, + {TableDef: &plan.TableDef{TblId: 3, FeatureFlag: features.IndexTable}}, + } + require.True(t, hasPartitionedUpdateTarget(contexts)) + + contexts[1].TableDef.FeatureFlag = 0 + contexts[2].TableDef.FeatureFlag = features.Partitioned | features.IndexTable + require.False(t, hasPartitionedUpdateTarget(contexts)) +} + func TestDupOperatorMultiUpdateCountDeleteAffectRows(t *testing.T) { op := multi_update.NewArgument() op.Action = multi_update.UpdateWriteTable diff --git a/pkg/sql/compile/remoterun.go b/pkg/sql/compile/remoterun.go index 93b9cc0a99738..8ee87e24a19f5 100644 --- a/pkg/sql/compile/remoterun.go +++ b/pkg/sql/compile/remoterun.go @@ -881,6 +881,8 @@ func convertToPipelineInstruction(op vm.Operator, proc *process.Process, ctx *sc InsertPkColIdx: int32(muCtx.InsertPkColIdx), IgnoreAffectedRows: muCtx.IgnoreAffectedRows, CountDeleteAffectRows: t.CountDeleteAffectRows, + DedupByTargetRowId: muCtx.DedupByTargetRowID, + TargetUpdateCtxIdx: int32(muCtx.TargetUpdateCtxIdx), } updateCtxList[i].InsertCols = make([]plan.ColRef, len(muCtx.InsertCols)) @@ -1393,6 +1395,9 @@ func convertToVmOperator(opr *pipeline.Instruction, ctx *scopeContext, eng engin SkipInsertOnNullPk: muCtx.SkipInsertOnNullPk, InsertPkColIdx: int(muCtx.InsertPkColIdx), IgnoreAffectedRows: muCtx.IgnoreAffectedRows, + DedupByTargetRowID: muCtx.DedupByTargetRowId, + TargetUpdateCtxIdx: int(muCtx.TargetUpdateCtxIdx), + TargetTableID: muCtx.TableDef.TblId, } arg.MultiUpdateCtx[i].InsertCols = make([]int, len(muCtx.InsertCols)) diff --git a/pkg/sql/compile/remoterun_test.go b/pkg/sql/compile/remoterun_test.go index b862136d55ffc..bdeeb064f6a81 100644 --- a/pkg/sql/compile/remoterun_test.go +++ b/pkg/sql/compile/remoterun_test.go @@ -910,12 +910,14 @@ func Test_DMLOperatorSerializationRoundtrip(t *testing.T) { op := &multi_update.MultiUpdate{ MultiUpdateCtx: []*multi_update.MultiUpdateCtx{ { - ObjRef: &plan.ObjectRef{ObjName: "t1"}, - TableDef: &plan.TableDef{Name: "t1"}, - InsertCols: []int{0, 1, 2}, - DeleteCols: []int{3, 4}, - PartitionCols: []int{5, 6}, - InsertPkColIdx: 1, + ObjRef: &plan.ObjectRef{ObjName: "t1"}, + TableDef: &plan.TableDef{Name: "t1"}, + InsertCols: []int{0, 1, 2}, + DeleteCols: []int{3, 4, 8}, + PartitionCols: []int{5, 6}, + InsertPkColIdx: 1, + DedupByTargetRowID: true, + TargetUpdateCtxIdx: 0, }, }, Action: multi_update.UpdateWriteTable, @@ -929,8 +931,10 @@ func Test_DMLOperatorSerializationRoundtrip(t *testing.T) { restoredOp := restored.(*multi_update.MultiUpdate) require.Equal(t, []int{5, 6}, restoredOp.MultiUpdateCtx[0].PartitionCols) require.Equal(t, []int{0, 1, 2}, restoredOp.MultiUpdateCtx[0].InsertCols) - require.Equal(t, []int{3, 4}, restoredOp.MultiUpdateCtx[0].DeleteCols) + require.Equal(t, []int{3, 4, 8}, restoredOp.MultiUpdateCtx[0].DeleteCols) require.Equal(t, 1, restoredOp.MultiUpdateCtx[0].InsertPkColIdx) + require.True(t, restoredOp.MultiUpdateCtx[0].DedupByTargetRowID) + require.Equal(t, 0, restoredOp.MultiUpdateCtx[0].TargetUpdateCtxIdx) require.True(t, restoredOp.IsRemote) require.False(t, restoredOp.CountDeleteAffectRows, "CountDeleteAffectRows must stay false when the source op did not set it") diff --git a/pkg/sql/plan/bind_insert.go b/pkg/sql/plan/bind_insert.go index 00da6ecec2804..ec8d23af08090 100644 --- a/pkg/sql/plan/bind_insert.go +++ b/pkg/sql/plan/bind_insert.go @@ -858,10 +858,23 @@ func (builder *QueryBuilder) buildIrregularMasterDeleteByPk(bindCtx *BindContext // path uses (reduceSinkSinkScanNodes + tempOptimizeForDML). It is a no-op when the // table has no irregular indexes. Shared by the modern INSERT and LOAD paths. func (builder *QueryBuilder) finishIrregularIndexMaintenance(query *plan.Query, bindCtx *BindContext) error { - if len(builder.irregularMaintIndexes) == 0 { + if len(builder.irregularMaintIndexes) == 0 && len(builder.irregularUpdateMaints) == 0 { return nil } - if len(builder.irregularMaintIndexes) > 0 { + if len(builder.irregularUpdateMaints) > 0 { + for _, maint := range builder.irregularUpdateMaints { + builder.irregularMaintSourceStep = maint.sourceStep + builder.irregularMaintDeleteStep = maint.deleteStep + builder.irregularMaintDeletePkPos = maint.deletePkPos + builder.irregularMaintDeletePkTyp = maint.deletePkTyp + builder.irregularMaintIndexes = maint.indexes + builder.irregularMaintTableDef = maint.tableDef + builder.irregularMaintObjRef = maint.objRef + if err := builder.buildIrregularIndexMaintenance(bindCtx); err != nil { + return err + } + } + } else if len(builder.irregularMaintIndexes) > 0 { if err := builder.buildIrregularIndexMaintenance(bindCtx); err != nil { return err } diff --git a/pkg/sql/plan/bind_update.go b/pkg/sql/plan/bind_update.go index 931b4a7a962e8..89d6d3721a244 100644 --- a/pkg/sql/plan/bind_update.go +++ b/pkg/sql/plan/bind_update.go @@ -17,6 +17,7 @@ package plan import ( "context" "fmt" + "sort" "strings" "github.com/matrixorigin/matrixone/pkg/catalog" @@ -96,6 +97,18 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) ); err != nil { return 0, err } + updatedTargetCount := 0 + for i := range dmlCtx.aliases { + if len(dmlCtx.updateCol2Expr[i]) > 0 { + updatedTargetCount++ + } + } + routeUnsupported := func(reason updatePlannerRouteReason, routeErr error) error { + if updatedTargetCount > 1 { + return newUpdatePlannerRouteError(updatePlannerRejected, reason, routeErr) + } + return newLegacyUpdatePlannerRouteError(reason, routeErr) + } if stmt.HasReturning() { if len(dmlCtx.tableDefs) != 1 { return 0, returningNotSupported(builder, "multi-table UPDATE") @@ -147,7 +160,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) return 0, err } if legacyIrregularRoute { - return 0, newLegacyUpdatePlannerRouteError( + return 0, routeUnsupported( updateRouteReasonIrregularIndex, moerr.NewUnsupportedDML(builder.GetContext(), "update vector/full-text index"), ) @@ -248,6 +261,27 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) selectNode := builder.qry.Nodes[lastNodeID] selectNodeTag := selectNode.BindingTags[0] + isMultiTargetUpdate := updatedTargetCount > 1 + targetBranchActivePos := make([]int32, len(dmlCtx.aliases)) + for i := range targetBranchActivePos { + targetBranchActivePos[i] = -1 + } + if isMultiTargetUpdate { + for i := range dmlCtx.aliases { + if len(dmlCtx.updateCol2Expr[i]) == 0 { + continue + } + targetBranchActivePos[i] = int32(len(selectNode.ProjectList)) + selectNode.ProjectList = append( + selectNode.ProjectList, + makePlan2BoolConstExprWithType(true), + ) + } + } + targetRowNumberPos := make([]int32, len(dmlCtx.aliases)) + for i := range targetRowNumberPos { + targetRowNumberPos[i] = -1 + } for i, alias := range dmlCtx.aliases { if len(dmlCtx.updateCol2Expr[i]) == 0 { @@ -324,7 +358,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) oldPos := oldColName2Idx[alias+"."+col.Name] newColName2Idx[alias+"."+col.Name] = oldPos - oldColName2Idx[alias+"."+col.Name] = int32(len(selectList)) + oldColName2Idx[alias+"."+col.Name] = int32(len(selectNode.ProjectList)) selectNode.ProjectList = append(selectNode.ProjectList, selectNode.ProjectList[oldPos]) selectNode.ProjectList[oldPos] = newDefExpr } @@ -350,7 +384,47 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } - if stmt.From != nil && len(stmt.From.Tables) > 0 { + lastNodeID, selectNode, selectNodeTag, err = builder.mergeSamePhysicalTargetAssignments( + bindCtx, + lastNodeID, + selectNode, + selectNodeTag, + dmlCtx, + oldColName2Idx, + newColName2Idx, + targetBranchActivePos, + ) + if err != nil { + return 0, err + } + + if isMultiTargetUpdate { + for i, alias := range dmlCtx.aliases { + if len(dmlCtx.updateCol2Expr[i]) == 0 { + continue + } + rowIDPos, ok := oldColName2Idx[alias+"."+catalog.Row_ID] + if !ok { + return 0, moerr.NewInternalErrorf( + builder.GetContext(), + "bind update err, can not find row_id for target %s", + alias, + ) + } + lastNodeID, selectNode, selectNodeTag, targetRowNumberPos[i], err = + builder.appendTargetRowNumberNode( + bindCtx, + lastNodeID, + selectNode, + selectNodeTag, + rowIDPos, + targetBranchActivePos[i], + ) + if err != nil { + return 0, err + } + } + } else if updateHasMultipleSourceTables(stmt) { lastNodeID, selectNode, selectNodeTag, err = builder.appendUpdateFromDedupNode( bindCtx, lastNodeID, selectNode, selectNodeTag, dmlCtx, oldColName2Idx, newColName2Idx) if err != nil { @@ -385,10 +459,6 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } } - fkChecksEnabled, err := IsForeignKeyChecksEnabled(builder.compCtx) - if err != nil { - return 0, err - } mayDependOnForeignKeys, err := builder.updateMayDependOnForeignKeys( bindCtx, dmlCtx, newColName2Idx) if err != nil { @@ -400,21 +470,6 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) // and generic plan caches rebuild after either session-state transition. builder.qry.HasForeignKeyAction = true } - if fkChecksEnabled { - for i, tableDef := range dmlCtx.tableDefs { - if updateAutoIncrCols[i] && - len(affectedUpdateChildFks(tableDef, dmlCtx.aliases[i], newColName2Idx)) > 0 { - return 0, newLegacyUpdatePlannerRouteError( - updateRouteReasonAutoIncrementFK, - moerr.NewUnsupportedDML( - builder.compCtx.GetContext(), - "auto_increment foreign key update", - ), - ) - } - } - } - for i, tableDef := range dmlCtx.tableDefs { if updateAutoIncrCols[i] { lastNodeID = builder.appendNode(&plan.Node{ @@ -538,6 +593,41 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } return builder.makeIndexPartExprFromInputExpr(inputExpr, partName, prefixLengths) } + guardTargetDedupExpr := func(targetIdx int, expr *plan.Expr) (*plan.Expr, error) { + rowNumberExpr := &plan.Expr{ + Typ: selectNode.ProjectList[targetRowNumberPos[targetIdx]].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: targetRowNumberPos[targetIdx], + }, + }, + } + isSelectedExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "=", + []*plan.Expr{rowNumberExpr, MakePlan2Int64ConstExprWithType(1)}, + ) + if err != nil { + return nil, err + } + nullExpr := &plan.Expr{ + Typ: expr.Typ, + Expr: &plan.Expr_Lit{ + Lit: &plan.Literal{Isnull: true}, + }, + } + guardedExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "if", + []*plan.Expr{isSelectedExpr, expr, nullExpr}, + ) + if err != nil { + return nil, err + } + return guardedExpr, nil + } + dedupKeyPos := make(map[string]int32) for i, tableDef := range dmlCtx.tableDefs { if len(dmlCtx.updateCol2Expr[i]) == 0 { @@ -569,7 +659,30 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } newPkExpr, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "serial", args) + if isMultiTargetUpdate { + newPkExpr, err = guardTargetDedupExpr(i, newPkExpr) + if err != nil { + return 0, err + } + dedupKeyPos[alias+"."+tableDef.Pkey.PkeyColName] = + int32(len(newProjNode.ProjectList)) + } newProjNode.ProjectList = append(newProjNode.ProjectList, newPkExpr) + } else if isMultiTargetUpdate { + key := alias + "." + tableDef.Pkey.PkeyColName + colPos := newColName2Idx[key] + pkExpr := &plan.Expr{ + Typ: selectNode.ProjectList[colPos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: selectNodeTag, ColPos: colPos}, + }, + } + pkExpr, err = guardTargetDedupExpr(i, pkExpr) + if err != nil { + return 0, err + } + dedupKeyPos[key] = int32(len(newProjNode.ProjectList)) + newProjNode.ProjectList = append(newProjNode.ProjectList, pkExpr) } scanTag := builder.genNewBindTag() @@ -593,16 +706,17 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) }, } + key := alias + "." + tableDef.Pkey.PkeyColName + newPkPos := newColName2Idx[key] + if pos, ok := dedupKeyPos[key]; ok { + newPkPos = pos + } rightExpr := &plan.Expr{ Typ: pkTyp, Expr: &plan.Expr_Col{ - Col: &plan.ColRef{ - RelPos: newProjTag, - ColPos: newColName2Idx[alias+"."+tableDef.Pkey.PkeyColName], - }, + Col: &plan.ColRef{RelPos: newProjTag, ColPos: newPkPos}, }, } - joinCond, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*plan.Expr{ leftExpr, rightExpr, @@ -709,6 +823,14 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } newUkExpr, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "serial", newArgs) + if isMultiTargetUpdate { + newUkExpr, err = guardTargetDedupExpr(i, newUkExpr) + if err != nil { + return 0, err + } + dedupKeyPos[idxTableDef.Name+"."+catalog.IndexTableIndexColName] = + int32(len(newProjNode.ProjectList)) + } newProjNode.ProjectList = append(newProjNode.ProjectList, newUkExpr) } else { partName := catalog.ResolveAlias(idxDef.Parts[0]) @@ -733,10 +855,34 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) if err != nil { return 0, err } + if isMultiTargetUpdate { + newPartExpr, err = guardTargetDedupExpr(i, newPartExpr) + if err != nil { + return 0, err + } + dedupKeyPos[idxTableDef.Name+"."+catalog.IndexTableIndexColName] = + int32(len(newProjNode.ProjectList)) + } newProjNode.ProjectList = append(newProjNode.ProjectList, newPartExpr) } else { oldColName2Idx[idxTableDef.Name+"."+catalog.IndexTableIndexColName] = oldColName2Idx[alias+"."+partName] newColName2Idx[idxTableDef.Name+"."+catalog.IndexTableIndexColName] = newColName2Idx[alias+"."+partName] + if isMultiTargetUpdate { + key := idxTableDef.Name + "." + catalog.IndexTableIndexColName + colPos := newColName2Idx[key] + newPartExpr := &plan.Expr{ + Typ: selectNode.ProjectList[colPos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: selectNodeTag, ColPos: colPos}, + }, + } + newPartExpr, err = guardTargetDedupExpr(i, newPartExpr) + if err != nil { + return 0, err + } + dedupKeyPos[key] = int32(len(newProjNode.ProjectList)) + newProjNode.ProjectList = append(newProjNode.ProjectList, newPartExpr) + } } } @@ -753,16 +899,17 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) }, } + key := idxTableDef.Name + "." + catalog.IndexTableIndexColName + newIdxPos := newColName2Idx[key] + if pos, ok := dedupKeyPos[key]; ok { + newIdxPos = pos + } rightExpr := &plan.Expr{ Typ: pkTyp, Expr: &plan.Expr_Col{ - Col: &plan.ColRef{ - RelPos: newProjTag, - ColPos: newColName2Idx[idxTableDef.Name+"."+catalog.IndexTableIndexColName], - }, + Col: &plan.ColRef{RelPos: newProjTag, ColPos: newIdxPos}, }, } - joinCond, _ := BindFuncExprImplByPlanExpr(builder.GetContext(), "=", []*plan.Expr{ leftExpr, rightExpr, @@ -910,7 +1057,7 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) }) joinType := plan.Node_LEFT - if !idxDef.Unique && !isSpatialIndexDef(idxDef) { + if !isMultiTargetUpdate && !idxDef.Unique && !isSpatialIndexDef(idxDef) { joinType = plan.Node_INNER } lastNodeID = builder.appendNode(&plan.Node{ @@ -928,6 +1075,8 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) finalProjTag := builder.genNewBindTag() finalColName2Idx := make(map[string]int32) var finalProjList []*plan.Expr + targetRowNumberFinalPos := make([]int32, len(dmlCtx.aliases)) + targetUpdateCtxIdx := make([]int32, len(dmlCtx.aliases)) finalProjNode := &plan.Node{ NodeType: plan.Node_PROJECT, @@ -981,7 +1130,6 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) }, } } - finalColName2Idx[alias+"."+col.Name] = int32(finalColIdx) finalProjList = append(finalProjList, finalExpr) } @@ -1000,8 +1148,30 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) }, }) } + if isMultiTargetUpdate { + targetRowNumberFinalPos[i] = int32(len(finalProjList)) + rowNumberPos := targetRowNumberPos[i] + finalProjList = append(finalProjList, &plan.Expr{ + Typ: selectNode.ProjectList[rowNumberPos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: rowNumberPos, + }, + }, + }) + finalProjList = append(finalProjList, &plan.Expr{ + Typ: selectNode.ProjectList[targetBranchActivePos[i]].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: targetBranchActivePos[i], + }, + }, + }) + } - updateCtxList = append(updateCtxList, &plan.UpdateCtx{ + updateCtx := &plan.UpdateCtx{ ObjRef: dmlCtx.objRefs[i], TableDef: tableDef, InsertCols: insertCols, @@ -1015,7 +1185,52 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) ColPos: oldPkPos, }, }, - }) + } + if tableDef.Partition != nil && len(tableDef.Partition.PartitionDefs) > 0 { + partitionColName := getPartitionColName(tableDef.Partition.PartitionDefs[0].Def) + if partitionColPos, ok := finalColName2Idx[alias+"."+partitionColName]; ok { + oldPartitionColPos := partitionColPos + if _, updated := newColName2Idx[alias+"."+partitionColName]; updated { + if partitionColName == tableDef.Pkey.PkeyColName { + oldPartitionColPos = oldPkPos + } else { + oldPartitionColPos = int32(len(finalProjList)) + oldSelectPos := oldColName2Idx[alias+"."+partitionColName] + finalProjList = append(finalProjList, &plan.Expr{ + Typ: selectNode.ProjectList[oldSelectPos].Typ, + Expr: &plan.Expr_Col{Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: oldSelectPos, + }}, + }) + } + } + updateCtx.PartitionCols = []plan.ColRef{{ + RelPos: finalProjTag, + ColPos: oldPartitionColPos, + }} + if oldPartitionColPos != partitionColPos { + updateCtx.PartitionCols = append(updateCtx.PartitionCols, plan.ColRef{ + RelPos: finalProjTag, + ColPos: partitionColPos, + }) + } + } + } + if isMultiTargetUpdate { + updateCtx.DedupByTargetRowId = true + targetUpdateCtxIdx[i] = int32(len(updateCtxList)) + updateCtx.TargetUpdateCtxIdx = targetUpdateCtxIdx[i] + updateCtx.DeleteCols = append(updateCtx.DeleteCols, plan.ColRef{ + RelPos: finalProjTag, + ColPos: targetRowNumberFinalPos[i], + }) + updateCtx.DeleteCols = append(updateCtx.DeleteCols, plan.ColRef{ + RelPos: finalProjTag, + ColPos: int32(len(finalProjList) - 1), + }) + } + updateCtxList = append(updateCtxList, updateCtx) lockTargets = append(lockTargets, &plan.LockTarget{ TableId: tableDef.TblId, @@ -1160,12 +1375,16 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) insertCols[1].RelPos = finalProjTag insertCols[1].ColPos = finalColName2Idx[alias+"."+tableDef.Pkey.PkeyColName] - updateCtxList = append(updateCtxList, &plan.UpdateCtx{ + updateCtx := &plan.UpdateCtx{ ObjRef: idxNode.ObjRef, TableDef: idxNode.TableDef, InsertCols: insertCols, DeleteCols: deleteCols, - }) + } + if isMultiTargetUpdate { + updateCtx.TargetUpdateCtxIdx = targetUpdateCtxIdx[i] + } + updateCtxList = append(updateCtxList, updateCtx) if idxDef.Unique { lockTargets = append(lockTargets, &plan.LockTarget{ @@ -1189,6 +1408,12 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) } finalProjNode.ProjectList = finalProjList + sort.SliceStable(lockTargets, func(i, j int) bool { + if lockTargets[i].TableId != lockTargets[j].TableId { + return lockTargets[i].TableId < lockTargets[j].TableId + } + return lockTargets[i].PrimaryColIdxInBat < lockTargets[j].PrimaryColIdxInBat + }) // Synchronous irregular indexes share the exact final row image with the // base-table MULTI_UPDATE. Their stale entries are deleted by the immutable @@ -1210,9 +1435,18 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) dmlCtx.tableDefs[i], dmlCtx.objRefs[i], ) - // Multi-target UPDATE is routed to the legacy planner before this point, - // so at most one target can require inline irregular maintenance here. - break + builder.irregularUpdateMaints = append( + builder.irregularUpdateMaints, + irregularUpdateMaintenance{ + sourceStep: builder.irregularMaintSourceStep, + deleteStep: builder.irregularMaintDeleteStep, + deletePkPos: builder.irregularMaintDeletePkPos, + deletePkTyp: builder.irregularMaintDeletePkTyp, + indexes: builder.irregularMaintIndexes, + tableDef: builder.irregularMaintTableDef, + objRef: builder.irregularMaintObjRef, + }, + ) } dmlNode := &plan.Node{ @@ -1236,6 +1470,624 @@ func (builder *QueryBuilder) bindUpdate(stmt *tree.Update, bindCtx *BindContext) return lastNodeID, err } +func (builder *QueryBuilder) mergeSamePhysicalTargetAssignments( + bindCtx *BindContext, + lastNodeID int32, + selectNode *plan.Node, + selectNodeTag int32, + dmlCtx *DMLContext, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, + targetBranchActivePos []int32, +) (int32, *plan.Node, int32, error) { + targetsByTableID := make(map[uint64][]int) + var tableIDs []uint64 + for i, updateCols := range dmlCtx.updateCol2Expr { + if len(updateCols) > 0 { + tableID := dmlCtx.tableDefs[i].TblId + if len(targetsByTableID[tableID]) == 0 { + tableIDs = append(tableIDs, tableID) + } + targetsByTableID[tableID] = append(targetsByTableID[tableID], i) + } + } + + hasRepeatedPhysicalTarget := false + for _, targets := range targetsByTableID { + if len(targets) > 1 { + hasRepeatedPhysicalTarget = true + break + } + } + if !hasRepeatedPhysicalTarget { + return lastNodeID, selectNode, selectNodeTag, nil + } + + // Reserve the final-row positions needed by every alias before branching. + // Every physical-target branch must expose exactly the same schema to the + // outer UNION ALL, including columns assigned through a sibling alias. + for _, tableID := range tableIDs { + targets := targetsByTableID[tableID] + if len(targets) < 2 { + continue + } + updatedCols := make(map[string]struct{}) + for _, targetIdx := range targets { + for colName := range dmlCtx.updateCol2Expr[targetIdx] { + updatedCols[colName] = struct{}{} + } + } + for _, targetIdx := range targets { + alias := dmlCtx.aliases[targetIdx] + for colName := range updatedCols { + key := alias + "." + colName + if _, exists := newColName2Idx[key]; exists { + continue + } + oldPos := oldColName2Idx[key] + newColName2Idx[key] = oldPos + oldColName2Idx[key] = int32(len(selectNode.ProjectList)) + selectNode.ProjectList = append( + selectNode.ProjectList, + DeepCopyExpr(selectNode.ProjectList[oldPos]), + ) + } + } + } + + sourceSinkID := appendSinkNode(builder, bindCtx, lastNodeID) + if builder.preserveSinkProjection == nil { + builder.preserveSinkProjection = make(map[int32]struct{}) + } + builder.preserveSinkProjection[sourceSinkID] = struct{}{} + sourceStep := builder.appendStep(sourceSinkID) + + sort.SliceStable(tableIDs, func(i, j int) bool { + return len(targetsByTableID[tableIDs[i]]) < len(targetsByTableID[tableIDs[j]]) + }) + branchIDs := make([]int32, 0, len(tableIDs)) + branchNodes := make([]*plan.Node, 0, len(tableIDs)) + for _, tableID := range tableIDs { + targets := targetsByTableID[tableID] + var branchID int32 + var branchNode *plan.Node + var err error + if len(targets) > 1 { + branchID, branchNode, err = builder.mergeSamePhysicalTargetAssignmentsAcrossTuples( + bindCtx, + sourceStep, + selectNode, + dmlCtx, + targets, + oldColName2Idx, + newColName2Idx, + targetBranchActivePos, + ) + } else { + branchID, branchNode, err = builder.projectPhysicalTargetSource( + bindCtx, + sourceStep, + selectNode, + dmlCtx, + targets[0], + oldColName2Idx, + newColName2Idx, + targetBranchActivePos, + ) + } + if err != nil { + return 0, nil, 0, err + } + branchIDs = append(branchIDs, branchID) + branchNodes = append(branchNodes, branchNode) + } + + if len(branchIDs) > 1 { + for i := range branchIDs { + branchSinkID := appendSinkNode(builder, bindCtx, branchIDs[i]) + if builder.preserveSinkProjection == nil { + builder.preserveSinkProjection = make(map[int32]struct{}) + } + builder.preserveSinkProjection[branchSinkID] = struct{}{} + branchStep := builder.appendStep(branchSinkID) + branchScanID := builder.appendPositionalSinkScan(bindCtx, branchStep) + branchTag := builder.genNewBindTag() + branchProject := make([]*plan.Expr, len(branchNodes[i].ProjectList)) + for pos, expr := range branchNodes[i].ProjectList { + branchProject[pos] = &plan.Expr{ + Typ: expr.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: 0, ColPos: int32(pos)}, + }, + } + } + materializedNode := &plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{branchScanID}, + ProjectList: branchProject, + BindingTags: []int32{branchTag}, + } + branchIDs[i] = builder.appendNode(materializedNode, bindCtx) + branchNodes[i] = materializedNode + } + } + + unionID := branchIDs[0] + unionNode := branchNodes[0] + unionInputTag := unionNode.BindingTags[0] + for branchIdx := 1; branchIdx < len(branchIDs); branchIdx++ { + unionProject := make([]*plan.Expr, len(unionNode.ProjectList)) + for pos, expr := range unionNode.ProjectList { + unionProject[pos] = &plan.Expr{ + Typ: expr.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: unionInputTag, ColPos: int32(pos)}, + }, + } + } + unionTag := builder.genNewBindTag() + unionNode = &plan.Node{ + NodeType: plan.Node_UNION_ALL, + Children: []int32{unionID, branchIDs[branchIdx]}, + ProjectList: unionProject, + BindingTags: []int32{unionTag}, + } + unionID = builder.appendNode(unionNode, bindCtx) + unionInputTag = unionTag + } + return unionID, unionNode, unionInputTag, nil +} + +func (builder *QueryBuilder) appendPositionalSinkScan(bindCtx *BindContext, sourceStep int32) int32 { + scanID := appendSinkScanNode(builder, bindCtx, sourceStep) + if builder.preserveScanProjection == nil { + builder.preserveScanProjection = make(map[int32]struct{}) + } + builder.preserveScanProjection[scanID] = struct{}{} + if builder.positionalSinkScans == nil { + builder.positionalSinkScans = make(map[int32]struct{}) + } + builder.positionalSinkScans[scanID] = struct{}{} + return scanID +} + +func nullUpdateProjectionExpr(typ plan.Type) *plan.Expr { + expr := makePlan2NullConstExprWithType() + expr.Typ = typ + expr.Typ.NotNullable = false + return expr +} + +// projectPhysicalTargetSource isolates one physical target from the shared join +// stream. Other targets are NULL so their independent selectors ignore this +// branch after all physical-target streams are combined with UNION ALL. +func (builder *QueryBuilder) projectPhysicalTargetSource( + bindCtx *BindContext, + sourceStep int32, + selectNode *plan.Node, + dmlCtx *DMLContext, + targetIdx int, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, + targetBranchActivePos []int32, +) (int32, *plan.Node, error) { + scanID := builder.appendPositionalSinkScan(bindCtx, sourceStep) + project := make([]*plan.Expr, len(selectNode.ProjectList)) + for pos, expr := range selectNode.ProjectList { + project[pos] = &plan.Expr{ + Typ: expr.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: 0, ColPos: int32(pos)}, + }, + } + } + copyPos := func(pos int32) { + project[pos] = &plan.Expr{ + Typ: selectNode.ProjectList[pos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: 0, ColPos: pos}, + }, + } + } + alias := dmlCtx.aliases[targetIdx] + for _, col := range dmlCtx.tableDefs[targetIdx].Cols { + copyPos(oldColName2Idx[alias+"."+col.Name]) + if pos, ok := newColName2Idx[alias+"."+col.Name]; ok { + copyPos(pos) + } + } + targetRowIDPos := oldColName2Idx[alias+"."+catalog.Row_ID] + targetRowIDExpr := DeepCopyExpr(project[targetRowIDPos]) + for otherIdx, activePos := range targetBranchActivePos { + if activePos < 0 { + continue + } + operator := "isnull" + if otherIdx == targetIdx { + operator = "isnotnull" + } + activeExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + operator, + []*plan.Expr{DeepCopyExpr(targetRowIDExpr)}, + ) + if err != nil { + return 0, nil, err + } + project[activePos] = activeExpr + } + tag := builder.genNewBindTag() + node := &plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{scanID}, + ProjectList: project, + BindingTags: []int32{tag}, + } + return builder.appendNode(node, bindCtx), node, nil +} + +type physicalTargetContribution struct { + targetIdx int + colName string + valuePos int32 + markerPos int32 +} + +type physicalTargetFiller struct { + sourcePos int32 + canonicalPos int32 + outputPos []int32 +} + +// mergeSamePhysicalTargetAssignmentsAcrossTuples first selects one complete +// source tuple per alias and target Rowid. Only then does it combine assignments +// made through different aliases, so multiple SET expressions from one alias +// can never be assembled from different source tuples. +func (builder *QueryBuilder) mergeSamePhysicalTargetAssignmentsAcrossTuples( + bindCtx *BindContext, + sourceStep int32, + selectNode *plan.Node, + dmlCtx *DMLContext, + targets []int, + oldColName2Idx map[string]int32, + newColName2Idx map[string]int32, + targetBranchActivePos []int32, +) (int32, *plan.Node, error) { + tableDef := dmlCtx.tableDefs[targets[0]] + updatedColsSet := make(map[string]struct{}) + var contributions []physicalTargetContribution + for _, targetIdx := range targets { + for colName := range dmlCtx.updateCol2Expr[targetIdx] { + updatedColsSet[colName] = struct{}{} + contributions = append(contributions, physicalTargetContribution{ + targetIdx: targetIdx, + colName: colName, + }) + } + } + sort.SliceStable(contributions, func(i, j int) bool { + if contributions[i].targetIdx != contributions[j].targetIdx { + return contributions[i].targetIdx < contributions[j].targetIdx + } + return contributions[i].colName < contributions[j].colName + }) + updatedCols := make([]string, 0, len(updatedColsSet)) + for colName := range updatedColsSet { + updatedCols = append(updatedCols, colName) + } + sort.Strings(updatedCols) + + // Canonical layout: old physical row, followed by a value and an explicit + // assignment marker for each alias/column contribution. + canonicalTypes := make([]plan.Type, 0, len(tableDef.Cols)+2*len(contributions)) + for _, col := range tableDef.Cols { + canonicalTypes = append(canonicalTypes, col.Typ) + } + for i := range contributions { + colIdx := tableDef.Name2ColIndex[contributions[i].colName] + contributions[i].valuePos = int32(len(canonicalTypes)) + canonicalTypes = append(canonicalTypes, tableDef.Cols[colIdx].Typ) + contributions[i].markerPos = int32(len(canonicalTypes)) + canonicalTypes = append(canonicalTypes, plan.Type{Id: int32(types.T_bool)}) + } + currentTableID := tableDef.TblId + fillerByTableCol := make(map[string]*physicalTargetFiller) + var fillers []*physicalTargetFiller + for targetIdx, updateCols := range dmlCtx.updateCol2Expr { + if len(updateCols) == 0 || dmlCtx.tableDefs[targetIdx].TblId == currentTableID { + continue + } + otherDef := dmlCtx.tableDefs[targetIdx] + otherAlias := dmlCtx.aliases[targetIdx] + for _, col := range otherDef.Cols { + fillerKey := fmt.Sprintf("%d.%s", otherDef.TblId, col.Name) + filler := fillerByTableCol[fillerKey] + if filler == nil { + filler = &physicalTargetFiller{ + sourcePos: oldColName2Idx[otherAlias+"."+col.Name], + canonicalPos: int32(len(canonicalTypes)), + } + fillerByTableCol[fillerKey] = filler + fillers = append(fillers, filler) + canonicalTypes = append(canonicalTypes, col.Typ) + } + filler.outputPos = append(filler.outputPos, oldColName2Idx[otherAlias+"."+col.Name]) + if newPos, ok := newColName2Idx[otherAlias+"."+col.Name]; ok { + filler.outputPos = append(filler.outputPos, newPos) + } + } + } + branchIDs := make([]int32, 0, len(targets)) + branchTags := make([]int32, 0, len(targets)) + for _, sourceIdx := range targets { + sourceAlias := dmlCtx.aliases[sourceIdx] + branchScanID := builder.appendPositionalSinkScan(bindCtx, sourceStep) + branchScanTag := builder.genNewBindTag() + builder.qry.Nodes[branchScanID].BindingTags = []int32{branchScanTag} + rowIDPos := oldColName2Idx[sourceAlias+"."+catalog.Row_ID] + dedupInputProject := make([]*plan.Expr, 0, len(selectNode.ProjectList)+1) + for pos, expr := range selectNode.ProjectList { + dedupInputProject = append(dedupInputProject, &plan.Expr{ + Typ: expr.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: branchScanTag, ColPos: int32(pos)}, + }, + }) + } + rowIDColExpr := &plan.Expr{ + Typ: selectNode.ProjectList[rowIDPos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: branchScanTag, ColPos: rowIDPos}, + }, + } + rowIDPartitionExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "greatest", + []*plan.Expr{rowIDColExpr, DeepCopyExpr(rowIDColExpr)}, + ) + if err != nil { + return 0, nil, err + } + dedupInputProject = append(dedupInputProject, rowIDPartitionExpr) + dedupInputTag := builder.genNewBindTag() + dedupInputNode := &plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{branchScanID}, + ProjectList: dedupInputProject, + BindingTags: []int32{dedupInputTag}, + } + dedupInputID := builder.appendNode(dedupInputNode, bindCtx) + dedupID, dedupNode, dedupTag, err := builder.appendRowNumberDedupNode( + bindCtx, + dedupInputID, + dedupInputNode, + dedupInputTag, + []int32{int32(len(selectNode.ProjectList))}, + ) + if err != nil { + return 0, nil, err + } + branchTag := builder.genNewBindTag() + branchColExpr := func(pos int32) *plan.Expr { + return &plan.Expr{ + Typ: dedupNode.ProjectList[pos].Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: dedupTag, ColPos: pos}, + }, + } + } + branchProject := make([]*plan.Expr, 0, len(canonicalTypes)) + for _, col := range tableDef.Cols { + sourcePos := oldColName2Idx[sourceAlias+"."+col.Name] + branchProject = append( + branchProject, + branchColExpr(sourcePos), + ) + } + for _, contribution := range contributions { + if contribution.targetIdx == sourceIdx { + branchProject = append( + branchProject, + branchColExpr(newColName2Idx[sourceAlias+"."+contribution.colName]), + makePlan2BoolConstExprWithType(true), + ) + } else { + colIdx := tableDef.Name2ColIndex[contribution.colName] + branchProject = append( + branchProject, + nullUpdateProjectionExpr(tableDef.Cols[colIdx].Typ), + nullUpdateProjectionExpr(plan.Type{Id: int32(types.T_bool)}), + ) + } + } + for _, filler := range fillers { + if sourceIdx == targets[0] { + branchProject = append(branchProject, branchColExpr(filler.sourcePos)) + } else { + branchProject = append( + branchProject, + nullUpdateProjectionExpr(canonicalTypes[filler.canonicalPos]), + ) + } + } + branchIDs = append(branchIDs, builder.appendNode(&plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{dedupID}, + ProjectList: branchProject, + BindingTags: []int32{branchTag}, + }, bindCtx)) + branchTags = append(branchTags, branchTag) + } + + unionID := branchIDs[0] + unionInputTag := branchTags[0] + for branchIdx := 1; branchIdx < len(branchIDs); branchIdx++ { + unionProject := make([]*plan.Expr, len(canonicalTypes)) + for pos, typ := range canonicalTypes { + unionProject[pos] = &plan.Expr{ + Typ: typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: unionInputTag, ColPos: int32(pos)}, + }, + } + } + unionTag := builder.genNewBindTag() + unionID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_UNION_ALL, + Children: []int32{unionID, branchIDs[branchIdx]}, + ProjectList: unionProject, + BindingTags: []int32{unionTag}, + }, bindCtx) + unionInputTag = unionTag + } + unionTag := unionInputTag + + rowIDCanonicalPos := int32(tableDef.Name2ColIndex[catalog.Row_ID]) + groupExpr := &plan.Expr{ + Typ: canonicalTypes[rowIDCanonicalPos], + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: unionTag, ColPos: rowIDCanonicalPos}, + }, + } + groupTag := builder.genNewBindTag() + aggTag := builder.genNewBindTag() + aggList := make([]*plan.Expr, 0, len(canonicalTypes)-1) + canonicalAggPos := make([]int32, len(canonicalTypes)) + for pos, typ := range canonicalTypes { + if int32(pos) == rowIDCanonicalPos { + canonicalAggPos[pos] = -1 + continue + } + input := &plan.Expr{ + Typ: typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: unionTag, ColPos: int32(pos)}, + }, + } + aggExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + "any_value", + []*plan.Expr{input}, + ) + if err != nil { + return 0, nil, err + } + canonicalAggPos[pos] = int32(len(aggList)) + aggList = append(aggList, aggExpr) + } + aggID := builder.appendNode(&plan.Node{ + NodeType: plan.Node_AGG, + Children: []int32{unionID}, + GroupBy: []*plan.Expr{groupExpr}, + AggList: aggList, + BindingTags: []int32{groupTag, aggTag}, + SpillMem: builder.aggSpillMem, + }, bindCtx) + + canonicalResultExpr := func(pos int32) *plan.Expr { + typ := canonicalTypes[pos] + if pos == rowIDCanonicalPos { + return &plan.Expr{ + Typ: typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: groupTag, ColPos: 0}, + }, + } + } + return &plan.Expr{ + Typ: typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{RelPos: aggTag, ColPos: canonicalAggPos[pos]}, + }, + } + } + + finalProject := make([]*plan.Expr, len(selectNode.ProjectList)) + for pos, expr := range selectNode.ProjectList { + finalProject[pos] = nullUpdateProjectionExpr(expr.Typ) + } + for _, filler := range fillers { + for _, outputPos := range filler.outputPos { + finalProject[outputPos] = canonicalResultExpr(filler.canonicalPos) + } + } + targetSet := make(map[int]struct{}, len(targets)) + for _, targetIdx := range targets { + targetSet[targetIdx] = struct{}{} + } + rowIDExpr := canonicalResultExpr(rowIDCanonicalPos) + for targetIdx, activePos := range targetBranchActivePos { + if activePos < 0 { + continue + } + operator := "isnull" + if _, belongsToPhysicalTarget := targetSet[targetIdx]; belongsToPhysicalTarget { + operator = "isnotnull" + } + activeExpr, err := BindFuncExprImplByPlanExpr( + builder.GetContext(), + operator, + []*plan.Expr{DeepCopyExpr(rowIDExpr)}, + ) + if err != nil { + return 0, nil, err + } + finalProject[activePos] = activeExpr + } + finalUpdatedExprs := make(map[string]*plan.Expr, len(updatedCols)) + for _, colName := range updatedCols { + finalExpr := canonicalResultExpr(int32(tableDef.Name2ColIndex[colName])) + for _, contribution := range contributions { + if contribution.colName != colName { + continue + } + var err error + finalExpr, err = BindFuncExprImplByPlanExpr( + builder.GetContext(), + "if", + []*plan.Expr{ + canonicalResultExpr(contribution.markerPos), + canonicalResultExpr(contribution.valuePos), + finalExpr, + }, + ) + if err != nil { + return 0, nil, err + } + } + finalUpdatedExprs[colName] = finalExpr + } + for _, targetIdx := range targets { + alias := dmlCtx.aliases[targetIdx] + for colPos, col := range tableDef.Cols { + finalProject[oldColName2Idx[alias+"."+col.Name]] = + canonicalResultExpr(int32(colPos)) + } + for _, colName := range updatedCols { + key := alias + "." + colName + targetPos, exists := newColName2Idx[key] + if !exists { + oldPos := oldColName2Idx[key] + oldColName2Idx[key] = int32(len(finalProject)) + finalProject = append(finalProject, canonicalResultExpr(int32(tableDef.Name2ColIndex[colName]))) + targetPos = oldPos + newColName2Idx[key] = targetPos + } + finalProject[targetPos] = DeepCopyExpr(finalUpdatedExprs[colName]) + } + } + + projectTag := builder.genNewBindTag() + projectNode := &plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{aggID}, + ProjectList: finalProject, + BindingTags: []int32{projectTag}, + } + projectID := builder.appendNode(projectNode, bindCtx) + return projectID, projectNode, nil +} + func irregularIndexAffectedByUpdate( tableDef *plan.TableDef, idxDef *plan.IndexDef, @@ -1296,11 +2148,12 @@ func irregularIndexAffectedByUpdate( } // classifyIrregularIndexesForUpdate separates synchronous inline maintenance -// from CDC-only indexes using plugin metadata. The bool return preserves the -// legacy route only for an affected irregular algorithm that has not migrated to -// the plugin contract (currently MASTER); supported plugin indexes never fall -// back. A synchronous-index PK update is rejected here, before lock/mutation -// nodes are built, because its hidden rows are keyed by the old source PK. +// from CDC-only indexes using plugin metadata. MASTER has no plugin, but shares +// the modern synchronous maintenance pipeline with the plugin-backed indexes. +// The bool return preserves the legacy route only for an affected irregular +// algorithm that has not migrated to either mechanism. A synchronous-index PK +// update is rejected here, before lock/mutation nodes are built, because its +// hidden rows are keyed by the old source PK. func classifyIrregularIndexesForUpdate( ctx context.Context, tableDef *plan.TableDef, @@ -1323,8 +2176,23 @@ func classifyIrregularIndexesForUpdate( p, ok := indexplugin.Get(idxDef.IndexAlgo) if !ok { - if affected || pkUpdated { - return nil, true, nil + if !isModernMaintainedIrregularAlgo(idxDef.IndexAlgo) { + if affected || pkUpdated { + return nil, true, nil + } + continue + } + if pkUpdated { + return nil, false, newUpdatePlannerRouteError( + updatePlannerRejected, + updateRouteReasonIrregularIndex, + moerr.NewUnsupportedDML( + ctx, + "update primary key on a table with a synchronous irregular index"), + ) + } + if affected { + affectedSyncGroups[idxDef.IndexName+"\x00"+idxDef.IndexTableName] = true } continue } @@ -1362,6 +2230,16 @@ func classifyIrregularIndexesForUpdate( return inline, false, nil } +func updateHasMultipleSourceTables(stmt *tree.Update) bool { + if stmt.From != nil && len(stmt.From.Tables) > 0 { + return true + } + if len(stmt.Tables) > 1 { + return true + } + return len(stmt.Tables) == 1 && tableExprContainsJoin(stmt.Tables[0]) +} + func primaryKeyUpdated(tableDef *plan.TableDef, updateCols map[string]tree.Expr) bool { if tableDef == nil || tableDef.Pkey == nil || len(updateCols) == 0 { return false @@ -1378,6 +2256,119 @@ func primaryKeyUpdated(tableDef *plan.TableDef, updateCols map[string]tree.Expr) return false } +// appendTargetRowNumberNode appends an independent row_number() window for one +// updated target. Unlike appendRowNumberDedupNode, it deliberately keeps every +// input row: each MULTI_UPDATE context later consumes only its own row_number=1 +// rows. This is required for multi-target UPDATE because one shared global +// filter cannot independently choose representatives for two different Rowids. +func (builder *QueryBuilder) appendTargetRowNumberNode( + bindCtx *BindContext, + lastNodeID int32, + selectNode *plan.Node, + selectNodeTag int32, + targetRowIDPos int32, + targetActivePos int32, +) (int32, *plan.Node, int32, int32, error) { + childColExpr := func(pos int32) *plan.Expr { + e := selectNode.ProjectList[pos] + name := "" + if col, ok := e.Expr.(*plan.Expr_Col); ok { + name = col.Col.Name + } + return &plan.Expr{ + Typ: e.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: selectNodeTag, + ColPos: pos, + Name: name, + }, + }, + } + } + + targetRowIDExpr := childColExpr(targetRowIDPos) + targetActiveExpr := childColExpr(targetActivePos) + partitionBy := []*plan.OrderBySpec{ + { + Expr: DeepCopyExpr(targetActiveExpr), + Flag: plan.OrderBySpec_INTERNAL, + }, + { + Expr: DeepCopyExpr(targetRowIDExpr), + Flag: plan.OrderBySpec_INTERNAL, + }, + } + windowTag := builder.genNewBindTag() + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_PARTITION, + Children: []int32{lastNodeID}, + OrderBy: partitionBy, + BindingTags: []int32{windowTag}, + }, bindCtx) + + rowNumberFunc, err := BindFuncExprImplByPlanExpr(builder.GetContext(), "row_number", nil) + if err != nil { + return 0, nil, 0, 0, err + } + rowNumberExpr := &plan.Expr{ + Typ: rowNumberFunc.Typ, + Expr: &plan.Expr_W{ + W: &plan.WindowSpec{ + WindowFunc: rowNumberFunc, + Name: "row_number", + PartitionBy: []*plan.Expr{ + DeepCopyExpr(targetActiveExpr), + DeepCopyExpr(targetRowIDExpr), + }, + Frame: &plan.FrameClause{ + Type: plan.FrameClause_ROWS, + Start: &plan.FrameBound{ + Type: plan.FrameBound_PRECEDING, + UnBounded: true, + }, + End: &plan.FrameBound{ + Type: plan.FrameBound_FOLLOWING, + UnBounded: true, + }, + }, + }, + }, + } + lastNodeID = builder.appendNode(&plan.Node{ + NodeType: plan.Node_WINDOW, + Children: []int32{lastNodeID}, + WinSpecList: []*plan.Expr{rowNumberExpr}, + WindowIdx: 0, + BindingTags: []int32{windowTag}, + }, bindCtx) + + rowNumberProjectPos := int32(len(selectNode.ProjectList)) + projectTag := builder.genNewBindTag() + projectList := make([]*plan.Expr, 0, len(selectNode.ProjectList)+1) + for pos := range selectNode.ProjectList { + projectList = append(projectList, childColExpr(int32(pos))) + } + projectList = append(projectList, &plan.Expr{ + Typ: rowNumberFunc.Typ, + Expr: &plan.Expr_Col{ + Col: &plan.ColRef{ + RelPos: windowTag, + ColPos: 0, + Name: "__mo_multi_target_update_row_number", + }, + }, + }) + projectNode := &plan.Node{ + NodeType: plan.Node_PROJECT, + Children: []int32{lastNodeID}, + ProjectList: projectList, + BindingTags: []int32{projectTag}, + } + lastNodeID = builder.appendNode(projectNode, bindCtx) + return lastNodeID, projectNode, projectTag, rowNumberProjectPos, nil +} + func (builder *QueryBuilder) appendUpdateFromDedupNode( bindCtx *BindContext, lastNodeID int32, diff --git a/pkg/sql/plan/bind_update_test.go b/pkg/sql/plan/bind_update_test.go index d43af707584aa..c9e2fbcf5ad87 100644 --- a/pkg/sql/plan/bind_update_test.go +++ b/pkg/sql/plan/bind_update_test.go @@ -154,10 +154,10 @@ func TestClassifyIrregularIndexesForUpdate(t *testing.T) { updateCols: map[string]tree.Expr{"id": nil}, }, { - name: "unmigrated master stays legacy", + name: "synchronous master uses modern maintenance", tableDef: newTableDef(newIndex("master", catalog.MOIndexMasterAlgo.ToString(), "", "body")), updateCols: map[string]tree.Expr{"body": nil}, - wantLegacy: true, + wantInline: 1, }, } diff --git a/pkg/sql/plan/build.go b/pkg/sql/plan/build.go index 6ff66d0d040b7..74b64a6b9a954 100644 --- a/pkg/sql/plan/build.go +++ b/pkg/sql/plan/build.go @@ -408,6 +408,10 @@ func bindAndOptimizeUpdateQuery(ctx CompilerContext, stmt *tree.Update, isPrepar route, reason, routedErr := classifyUpdatePlannerError(err) switch route { case updatePlannerLegacy: + if updateHasMultiTableTargetShape(stmt) { + recordUpdatePlannerRoute(updatePlannerRejected, reason, "rejected") + return nil, routedErr + } recordUpdatePlannerRoute(route, reason, "selected") if stmt.HasReturning() { if reason == updateRouteReasonExternalTable { diff --git a/pkg/sql/plan/build_test.go b/pkg/sql/plan/build_test.go index c9fb0db8771e6..5663b37697374 100644 --- a/pkg/sql/plan/build_test.go +++ b/pkg/sql/plan/build_test.go @@ -37,6 +37,7 @@ import ( lockpb "github.com/matrixorigin/matrixone/pkg/pb/lock" "github.com/matrixorigin/matrixone/pkg/pb/plan" txnpb "github.com/matrixorigin/matrixone/pkg/pb/txn" + "github.com/matrixorigin/matrixone/pkg/sql/features" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect" "github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect/mysql" "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" @@ -2482,6 +2483,212 @@ func TestUpdatePgStyleFromDedupsDuplicateSourceMatchesOnNewPath(t *testing.T) { } } +func TestMySQLSingleTargetMultiTableUpdateDedupsDuplicateSourceMatches(t *testing.T) { + mock := NewMockOptimizer(true) + logicPlan, err := runOneStmt(mock, t, + "update nation as target, (select n_regionkey from nation) as source "+ + "set target.n_regionkey = 555 where target.n_nationkey = 3") + require.NoError(t, err) + require.True(t, hasUpdateFromDedupWindow(logicPlan.GetQuery(), 1)) +} + +func TestMultiTargetUpdateUsesIndependentModernSelectors(t *testing.T) { + mock := NewMockOptimizer(true) + logicPlan, err := runOneStmt( + mock, + t, + "UPDATE nation n JOIN nation2 n2 ON n.n_nationkey = n2.n_nationkey "+ + "SET n.n_name = n2.n_name, n2.n_comment = n.n_comment", + ) + require.NoError(t, err) + + query := logicPlan.GetQuery() + var multiUpdate *plan.Node + rowNumberWindows := 0 + for _, node := range query.Nodes { + if node.NodeType == plan.Node_WINDOW { + for _, specExpr := range node.WinSpecList { + if spec := specExpr.GetW(); spec != nil && + spec.Name == "row_number" && + len(spec.PartitionBy) == 2 { + rowNumberWindows++ + } + } + } + if node.NodeType == plan.Node_MULTI_UPDATE { + multiUpdate = node + } + } + require.NotNil(t, multiUpdate) + require.Equal(t, 2, rowNumberWindows) + + mainCtxs := make(map[string]*plan.UpdateCtx) + for _, updateCtx := range multiUpdate.UpdateCtxList { + if updateCtx.TableDef == nil { + continue + } + if updateCtx.TableDef.Name == "nation" || updateCtx.TableDef.Name == "nation2" { + mainCtxs[updateCtx.TableDef.Name] = updateCtx + } + } + require.Len(t, mainCtxs, 2) + for _, name := range []string{"nation", "nation2"} { + updateCtx := mainCtxs[name] + require.NotNil(t, updateCtx) + require.True(t, updateCtx.DedupByTargetRowId) + require.Len(t, updateCtx.DeleteCols, 4) + require.NotEqual(t, updateCtx.DeleteCols[0].ColPos, updateCtx.DeleteCols[2].ColPos) + require.NotEqual(t, updateCtx.DeleteCols[2].ColPos, updateCtx.DeleteCols[3].ColPos) + } + require.NotEqual( + t, + mainCtxs["nation"].DeleteCols[0].ColPos, + mainCtxs["nation2"].DeleteCols[0].ColPos, + ) + + require.Len(t, multiUpdate.Children, 1) + lockNode := query.Nodes[multiUpdate.Children[0]] + require.Equal(t, plan.Node_LOCK_OP, lockNode.NodeType) + for i := 1; i < len(lockNode.LockTargets); i++ { + previous := lockNode.LockTargets[i-1] + current := lockNode.LockTargets[i] + require.True(t, + previous.TableId < current.TableId || + (previous.TableId == current.TableId && + previous.PrimaryColIdxInBat <= current.PrimaryColIdxInBat), + ) + } +} + +func TestPartitionedMultiTargetUpdateUsesModernPlan(t *testing.T) { + for _, test := range []struct { + sql string + partitionColumnCount int + }{ + { + sql: "UPDATE nation n JOIN nation2 n2 ON n.n_nationkey = n2.n_nationkey " + + "SET n.n_name = n2.n_name, n2.n_comment = n.n_comment", + partitionColumnCount: 1, + }, + { + sql: "UPDATE nation2 n2 JOIN nation n ON n.n_nationkey = n2.n_nationkey " + + "SET n2.n_comment = n.n_comment, n.n_name = n2.n_name", + partitionColumnCount: 1, + }, + { + sql: "UPDATE nation n JOIN nation2 n2 ON n.n_nationkey = n2.n_nationkey " + + "SET n.n_nationkey = n.n_nationkey + 10, n2.n_comment = n.n_comment", + partitionColumnCount: 2, + }, + } { + mock := NewMockOptimizer(true) + mock.ctxt.tables["nation"].FeatureFlag |= features.Partitioned + mock.ctxt.tables["nation"].Partition = &plan.Partition{ + PartitionDefs: []*plan.PartitionDef{{ + Def: &plan.Expr{Expr: &plan.Expr_F{F: &plan.Function{Args: []*plan.Expr{ + {Expr: &plan.Expr_Col{Col: &plan.ColRef{Name: "n_nationkey"}}}, + }}}}, + }}, + } + logicPlan, err := runOneStmt(mock, t, test.sql) + require.NoError(t, err) + + multiUpdates := 0 + for _, node := range logicPlan.GetQuery().Nodes { + if node.NodeType == plan.Node_MULTI_UPDATE { + multiUpdates++ + require.Len(t, node.UpdateCtxList, 2) + for _, updateCtx := range node.UpdateCtxList { + if updateCtx.TableDef.Name == "nation" { + require.Len(t, updateCtx.PartitionCols, test.partitionColumnCount) + require.NotEqual(t, int32(-1), updateCtx.PartitionCols[0].ColPos) + } else { + require.Empty(t, updateCtx.PartitionCols) + } + } + } + } + require.Equal(t, 1, multiUpdates) + } +} + +func TestSamePhysicalTargetAliasesShareMergedFinalRows(t *testing.T) { + for _, sql := range []string{ + "UPDATE nation a JOIN nation b ON a.n_nationkey = b.n_nationkey " + + "SET a.n_name = 'a', b.n_comment = 'b'", + "UPDATE nation a JOIN nation b ON a.n_nationkey <> b.n_nationkey " + + "SET a.n_name = 'a', b.n_comment = 'b'", + "UPDATE nation a JOIN nation b ON a.n_nationkey <> b.n_nationkey " + + "JOIN nation2 n2 ON n2.n_nationkey = a.n_nationkey " + + "SET a.n_name = 'a', b.n_comment = 'b', n2.n_name = 'n2'", + } { + mock := NewMockOptimizer(true) + logicPlan, err := runOneStmt(mock, t, sql) + require.NoError(t, err, sql) + + query := logicPlan.GetQuery() + var multiUpdate *plan.Node + mainContexts := 0 + hasUnionAll := false + hasAggregate := false + for _, node := range query.Nodes { + switch node.NodeType { + case plan.Node_MULTI_UPDATE: + multiUpdate = node + case plan.Node_UNION_ALL: + hasUnionAll = true + case plan.Node_AGG: + hasAggregate = true + } + } + + require.NotNil(t, multiUpdate) + require.True(t, hasUnionAll) + require.True(t, hasAggregate) + var tableID uint64 + for _, updateCtx := range multiUpdate.UpdateCtxList { + if updateCtx.TableDef == nil || updateCtx.TableDef.Name != "nation" { + continue + } + mainContexts++ + require.True(t, updateCtx.DedupByTargetRowId) + if tableID == 0 { + tableID = updateCtx.TableDef.TblId + } else { + require.Equal(t, tableID, updateCtx.TableDef.TblId) + } + } + require.Equal(t, 2, mainContexts) + if strings.Contains(sql, "nation2") { + require.Len(t, multiUpdate.UpdateCtxList, 3) + } + } +} + +func TestModernMultiTargetOnUpdateColumnsKeepActiveSelectorsTyped(t *testing.T) { + for _, sql := range []string{ + "UPDATE nation a JOIN nation b ON a.n_nationkey = b.n_nationkey " + + "SET a.n_name = 'a', b.n_comment = 'b'", + "UPDATE emp, dept SET emp.job = 'a', dept.loc = 'b' " + + "WHERE emp.deptno = dept.deptno", + } { + mock := NewMockOptimizer(true) + setMockOnUpdateExpr(t, mock, "nation", "n_regionkey", "1") + setMockOnUpdateExpr(t, mock, "emp", "sal", "1") + setMockOnUpdateExpr(t, mock, "dept", "dname", "'updated'") + + logicPlan, err := runOneStmt(mock, t, sql) + require.NoError(t, err, sql) + multiUpdates := 0 + for _, node := range logicPlan.GetQuery().Nodes { + if node.NodeType == plan.Node_MULTI_UPDATE { + multiUpdates++ + } + } + require.Equal(t, 1, multiUpdates) + } +} + func TestUpdatePgStyleFromDedupPicksWholeSourceRow(t *testing.T) { mock := NewMockOptimizer(true) @@ -2672,146 +2879,22 @@ func TestUpdatePgStyleFromDedupAllowsDecimal256AndEnumUpdateColumns(t *testing.T } } -func TestUpdateFallbackMultiTargetGeneratedColumnsKeepProjectLayout(t *testing.T) { +func TestModernMultiTargetGeneratedColumns(t *testing.T) { mock := NewMockOptimizer(true) setMockGeneratedColumn(t, mock, "emp", "ename", "job") setMockGeneratedColumn(t, mock, "dept", "dname", "loc") logicPlan, err := runOneStmt(mock, t, "UPDATE emp, dept SET emp.job = dept.loc, dept.loc = emp.job WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback multi-target update with generated columns: %v", err) - } - query := logicPlan.GetQuery() - - assertFallbackUpdateProjectLength(t, query, len(mock.ctxt.tables["emp"].Cols)+2) - assertFallbackUpdateProjectLength(t, query, len(mock.ctxt.tables["dept"].Cols)+2) -} - -// TestUpdateFallbackProjectLayoutDeterministic guards the per-target column-block -// order of the fallback UPDATE planner. A multi-column SET must produce a -// byte-identical project layout on every build; before the fix, ranging the -// updateKeys map (column -> expr) appended the update expressions to the project -// list in random order across runs. A fresh optimizer per iteration rebuilds the -// maps, and Go randomizes map iteration, so a regression here fails reliably. -func TestUpdateFallbackProjectLayoutDeterministic(t *testing.T) { - // Multi-target (emp, dept) exercises the table-block order; the two plain - // (non-indexed) update columns on emp (mgr, sal) exercise the per-target - // column order. Both were Go-map-ordered before the fix. - const sql = "UPDATE emp, dept SET emp.mgr = 1, emp.sal = 2, dept.loc = 'x' WHERE emp.deptno = dept.deptno" - var want []string - for iter := 0; iter < 16; iter++ { - mock := NewMockOptimizer(true) - logicPlan, err := runOneStmt(mock, t, sql) - if err != nil { - t.Fatalf("build fallback update (iter %d): %v", iter, err) - } - got := fallbackUpdateProjectLayout(logicPlan.GetQuery()) - if len(got) == 0 { - t.Fatalf("iter %d: no fallback update project node found", iter) - } - if iter == 0 { - want = got - continue - } - assert.Equal(t, want, got, - "fallback UPDATE project layout must be deterministic across builds (iter %d)", iter) - } -} - -// fallbackUpdateProjectLayout returns a stable signature of every fallback UPDATE -// project node (a PROJECT over a SINK_SCAN): the ordered string form of each -// project expression. query.Nodes is built in a deterministic index order, so -// any cross-build difference reflects nondeterministic plan construction. -func fallbackUpdateProjectLayout(query *Query) []string { - var layout []string - for _, node := range query.Nodes { - if node.NodeType != plan.Node_PROJECT || len(node.Children) != 1 { - continue - } - if query.Nodes[node.Children[0]].NodeType != plan.Node_SINK_SCAN { - continue - } - for _, e := range node.ProjectList { - layout = append(layout, e.String()) - } - } - return layout -} - -func TestUpdateFallbackGeneratedColumnsUseDefaultAfterRewrite(t *testing.T) { - mock := NewMockOptimizer(true) - setMockDefaultExpr(t, mock, "emp", "job", "job-default") - setMockGeneratedColumn(t, mock, "emp", "ename", "job") - - logicPlan, err := runOneStmt(mock, t, - "UPDATE emp, dept SET emp.job = DEFAULT, dept.loc = 'default-marker' WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback update with generated column over DEFAULT: %v", err) - } - - node := requireFallbackSourceProjectNode(t, logicPlan.GetQuery(), - len(mock.ctxt.tables["emp"].Cols)+2+len(mock.ctxt.tables["dept"].Cols)+1, "default-marker") - if !nodeContainsStringLiteral(node, "job-default") { - t.Fatalf("generated column should use expanded DEFAULT expression, got %v", node.ProjectList) - } -} - -func TestUpdateFallbackGeneratedColumnsUseOnUpdateAfterRewrite(t *testing.T) { - mock := NewMockOptimizer(true) - setMockOnUpdateExpr(t, mock, "emp", "job", "job-on-update") - setMockGeneratedColumn(t, mock, "emp", "ename", "job") - - logicPlan, err := runOneStmt(mock, t, - "UPDATE emp, dept SET emp.comm = 1, dept.loc = 'on-update-marker' WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback update with generated column over ON UPDATE: %v", err) - } - - node := requireFallbackSourceProjectNode(t, logicPlan.GetQuery(), - len(mock.ctxt.tables["emp"].Cols)+2+len(mock.ctxt.tables["dept"].Cols)+1, "on-update-marker") - if !nodeContainsStringLiteral(node, "job-on-update") { - t.Fatalf("generated column should use ON UPDATE expression, got %v", node.ProjectList) - } -} - -func TestUpdateFallbackGeneratedColumnChainUsesFreshExpr(t *testing.T) { - mock := NewMockOptimizer(true) - setMockGeneratedColumn(t, mock, "emp", "mgr", "empno") - setMockGeneratedColumn(t, mock, "emp", "deptno", "mgr") - - logicPlan, err := runOneStmt(mock, t, - "UPDATE emp, dept SET emp.comm = 1, dept.loc = 'chain-marker' WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback update with generated column chain: %v", err) - } - - query := logicPlan.GetQuery() - assertFallbackUpdateAggDedupWithAnyValue(t, query) + require.NoError(t, err) - // Verify the generated-column chain without depending on the order of the - // appended update/recompute slots (that order is sensitive to map iteration - // and was a source of flakiness). emp contributes len(emp.Cols) base columns - // followed by its appended update + recomputed-generated expressions; both - // generated columns (mgr, deptno) must be freshly recomputed down to empno, - // so within that appended region none may reference the stale mgr column and - // exactly two must reference empno. - empCols := len(mock.ctxt.tables["emp"].Cols) - deptCols := len(mock.ctxt.tables["dept"].Cols) - node := requireFallbackSourceProjectNode(t, query, empCols+3+deptCols+1, "chain-marker") - empnoRefs := 0 - for pos := empCols; pos < empCols+3; pos++ { - e := node.ProjectList[pos] - if exprContainsColName(e, "mgr") { - t.Fatalf("generated column chain must use freshly recomputed empno, not stale mgr; appended pos %d = %s", pos, e.String()) - } - if exprContainsColName(e, "empno") { - empnoRefs++ + multiUpdates := 0 + for _, node := range logicPlan.GetQuery().Nodes { + if node.NodeType == plan.Node_MULTI_UPDATE { + multiUpdates++ } } - if empnoRefs != 2 { - t.Fatalf("expected both generated columns (mgr, deptno) freshly recomputed to empno, got %d empno refs in emp appended region", empnoRefs) - } + require.Equal(t, 1, multiUpdates) } func TestPreparedForeignKeyActionsMarkQueryUncacheable(t *testing.T) { @@ -2931,55 +3014,6 @@ func setMockEmpDeptForeignKeyAction( deptTable.RefChildTbls = []uint64{empTable.TblId} } -func TestUpdateFallbackGeneratedColumnMultiTableNonFirstHasGenerated(t *testing.T) { - mock := NewMockOptimizer(true) - // Generate dname from loc on the second table (dept). - setMockGeneratedColumn(t, mock, "dept", "dname", "loc") - - logicPlan, err := runOneStmt(mock, t, - "UPDATE emp, dept SET emp.comm = 1, dept.loc = 'non-first-gen' WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback multi-table update with non-first table generated column: %v", err) - } - query := logicPlan.GetQuery() - - // The source project should contain emp cols (9) + SET comm (1) + dept cols (4) + SET loc (1) + generated dname (1) = 16. - empCols := len(mock.ctxt.tables["emp"].Cols) - deptCols := len(mock.ctxt.tables["dept"].Cols) - expectedLen := empCols + 1 + deptCols + 1 + 1 // emp SET + dept SET + dname generated - node := requireFallbackSourceProjectNode(t, query, expectedLen, "non-first-gen") - if !nodeContainsStringLiteral(node, "non-first-gen") { - t.Fatalf("generated column on non-first table should contain the SET value, got %v", node.ProjectList) - } -} - -func TestUpdateFallbackGeneratedColumnChainAfterOptimize(t *testing.T) { - mock := NewMockOptimizer(true) - // Chain: sal depends on comm, comm is a SET column. - // After optimization and rewrite, sal's generated expr should use the SET value of comm. - setMockGeneratedColumn(t, mock, "emp", "sal", "comm") - - logicPlan, err := runOneStmt(mock, t, - "UPDATE emp, dept SET emp.comm = 1, dept.loc = 'chain-opt-marker' WHERE emp.deptno = dept.deptno") - if err != nil { - t.Fatalf("build fallback update with generated column after optimization: %v", err) - } - - // emp cols (9) + SET comm (1) + generated sal (1) + dept cols (4) + SET loc (1) = 16 - empCols := len(mock.ctxt.tables["emp"].Cols) - deptCols := len(mock.ctxt.tables["dept"].Cols) - expectedLen := empCols + 2 + deptCols + 1 - // Position of generated sal: after emp cols (9) + SET comm (1) = index 10 - generatedExpr := requireFallbackSourceProjectExpr(t, logicPlan.GetQuery(), expectedLen, - empCols+1, "chain-opt-marker") - if generatedExpr == nil { - t.Fatal("generated column position after optimization should not be nil") - } - // The generated expr should be a non-nil expression (DeepCopy of the SET value). - // We don't check the exact contents since substituteColRefsInExpr deep-copies, - // but we verify the expression exists at the expected position. -} - func TestUpdateGeneratedColumnDerivedTableSourceOnFKTable(t *testing.T) { mock := NewMockOptimizer(true) setMockGeneratedColumn(t, mock, "emp", "sal", "comm") @@ -3093,49 +3127,6 @@ func makeStringConstExpr(typ plan.Type, value string) *plan.Expr { } } -func requireFallbackSourceProjectNode(t *testing.T, query *Query, projectLen int, marker string) *Node { - for _, node := range query.Nodes { - if !isFallbackSourceProjectNode(query, node, projectLen, marker) { - continue - } - return node - } - t.Fatalf("missing fallback source project with length %d and marker %q", projectLen, marker) - return nil -} - -func requireFallbackSourceProjectExpr(t *testing.T, query *Query, projectLen int, pos int, marker string) *plan.Expr { - for _, node := range query.Nodes { - if !isFallbackSourceProjectNode(query, node, projectLen, marker) { - continue - } - if pos >= len(node.ProjectList) { - continue - } - return node.ProjectList[pos] - } - t.Fatalf("missing fallback source project with length %d and marker %q", projectLen, marker) - return nil -} - -func isFallbackSourceProjectNode(query *Query, node *Node, projectLen int, marker string) bool { - if node.NodeType != plan.Node_PROJECT || len(node.ProjectList) != projectLen { - return false - } - if len(node.Children) == 1 { - childIdx := node.Children[0] - if childIdx >= 0 && childIdx < int32(len(query.Nodes)) && query.Nodes[childIdx].NodeType == plan.Node_SINK_SCAN { - return false - } - } - for _, expr := range node.ProjectList { - if exprContainsStringLiteral(expr, marker) { - return true - } - } - return false -} - func hasUpdateFromDedupAnyValueAgg(query *Query, groupByLen int) bool { for _, node := range query.Nodes { if node.NodeType != plan.Node_AGG || len(node.GroupBy) != groupByLen { @@ -3254,49 +3245,6 @@ func queryContainsExpr(query *Query, accept func(*plan.Expr) bool) bool { return false } -func nodeContainsStringLiteral(node *Node, value string) bool { - for _, expr := range node.ProjectList { - if exprContainsStringLiteral(expr, value) { - return true - } - } - return false -} - -func assertFallbackUpdateProjectLength(t *testing.T, query *Query, projectLen int) { - for _, node := range query.Nodes { - if node.NodeType != plan.Node_PROJECT || len(node.ProjectList) != projectLen || len(node.Children) != 1 { - continue - } - child := query.Nodes[node.Children[0]] - if child.NodeType != plan.Node_SINK_SCAN { - continue - } - return - } - t.Fatalf("missing fallback update project with length %d", projectLen) -} - -func assertFallbackUpdateAggDedupWithAnyValue(t *testing.T, query *Query) { - foundAgg := false - foundAnyValue := false - for _, node := range query.Nodes { - if node.NodeType != plan.Node_AGG { - continue - } - foundAgg = true - for _, expr := range node.AggList { - if exprContainsFuncName(expr, "any_value") { - foundAnyValue = true - break - } - } - } - if !foundAgg || !foundAnyValue { - t.Fatalf("fallback update should build agg dedup path with any_value, foundAgg=%v foundAnyValue=%v", foundAgg, foundAnyValue) - } -} - func exprContainsFuncName(expr *plan.Expr, name string) bool { switch e := expr.Expr.(type) { case *plan.Expr_F: diff --git a/pkg/sql/plan/deepcopy.go b/pkg/sql/plan/deepcopy.go index c2cb89e75980c..8a8958706d2fe 100644 --- a/pkg/sql/plan/deepcopy.go +++ b/pkg/sql/plan/deepcopy.go @@ -108,6 +108,8 @@ func DeepCopyUpdateCtxList(updateCtxList []*plan.UpdateCtx) []*plan.UpdateCtx { InsertPkColIdx: ctx.InsertPkColIdx, CountDeleteAffectRows: ctx.CountDeleteAffectRows, IgnoreAffectedRows: ctx.IgnoreAffectedRows, + DedupByTargetRowId: ctx.DedupByTargetRowId, + TargetUpdateCtxIdx: ctx.TargetUpdateCtxIdx, } } diff --git a/pkg/sql/plan/dml_context.go b/pkg/sql/plan/dml_context.go index c1c3c0b703fd4..ac0053f253a29 100644 --- a/pkg/sql/plan/dml_context.go +++ b/pkg/sql/plan/dml_context.go @@ -114,13 +114,6 @@ func (dmlCtx *DMLContext) ResolveUpdateTables(ctx CompilerContext, stmt *tree.Up } } - if len(usedTbl) > 1 { - return newLegacyUpdatePlannerRouteError( - updateRouteReasonMultiTarget, - moerr.NewUnsupportedDML(ctx.GetContext(), "multi-table update"), - ) - } - dmlCtx.updateCol2Expr = make([]map[string]tree.Expr, len(dmlCtx.tableDefs)) for alias, columnMap := range usedTbl { idx := dmlCtx.aliasMap[alias] @@ -159,10 +152,21 @@ func classifyUpdateTableResolutionError(ctx CompilerContext, stmt *tree.Update, moerr.NewInvalidInput(ctx.GetContext(), "cannot insert/update/delete from external table"), ) case foreignKeyUnsupportedDMLMsg: + if updateHasMultiTableTargetShape(stmt) { + return newUpdatePlannerRouteError( + updatePlannerRejected, + updateRouteReasonForeignKey, + err, + ) + } return newLegacyUpdatePlannerRouteError(updateRouteReasonForeignKey, err) case unsupportedTableTypeDMLMsg: if updateHasMultiTableTargetShape(stmt) { - return newLegacyUpdatePlannerRouteError(updateRouteReasonMultiTarget, err) + return newUpdatePlannerRouteError( + updatePlannerRejected, + updateRouteReasonTableForm, + err, + ) } return newUpdatePlannerRouteError( updatePlannerRejected, @@ -275,34 +279,53 @@ func (dmlCtx *DMLContext) resolveSingleTable( ) error { var tblName, dbName, alias string - if aliasTbl, ok := tbl.(*tree.AliasedTableExpr); ok { - alias = string(aliasTbl.As.Alias) - tbl = aliasTbl.Expr - } - for { - if baseTbl, ok := tbl.(*tree.ParenTableExpr); ok { + if aliasTbl, ok := tbl.(*tree.AliasedTableExpr); ok { + alias = string(aliasTbl.As.Alias) + tbl = aliasTbl.Expr + } else if baseTbl, ok := tbl.(*tree.ParenTableExpr); ok { tbl = baseTbl.Expr } else { break } } - //if joinTbl, ok := tbl.(*tree.JoinTableExpr); ok { - // dmlCtx.needAggFilter = true - // err := setTableExprToDmlTableInfo(ctx, joinTbl.Left, dmlCtx, aliasMap, withMap) - // if err != nil { - // return err - // } - // if joinTbl.Right != nil { - // return setTableExprToDmlTableInfo(ctx, joinTbl.Right, dmlCtx, aliasMap, withMap) - // } - // return nil - //} + if joinTbl, ok := tbl.(*tree.JoinTableExpr); ok { + if err := dmlCtx.resolveSingleTable( + ctx, + joinTbl.Left, + aliasMap, + withMap, + foreignKeyPolicy, + ); err != nil { + return err + } + if joinTbl.Right != nil { + return dmlCtx.resolveSingleTable( + ctx, + joinTbl.Right, + aliasMap, + withMap, + foreignKeyPolicy, + ) + } + return nil + } if baseTbl, ok := tbl.(*tree.TableName); ok { dbName = string(baseTbl.SchemaName) tblName = string(baseTbl.ObjectName) + } else if _, ok := tbl.(*tree.Subquery); ok { + // Derived tables are read-only UPDATE sources. The SELECT binder owns + // their plan; DML target discovery must not route the whole statement to + // the legacy planner merely because a joined source is not writable. + return nil + } else if _, ok := tbl.(*tree.StatementSource); ok { + return nil + } else if _, ok := tbl.(*tree.ParenSelect); ok { + return nil + } else if _, ok := tbl.(*tree.Select); ok { + return nil } else { return moerr.NewUnsupportedDML(ctx.GetContext(), "unsupported table type") } diff --git a/pkg/sql/plan/types.go b/pkg/sql/plan/types.go index 59a71afaf40a8..5091b9df38128 100644 --- a/pkg/sql/plan/types.go +++ b/pkg/sql/plan/types.go @@ -309,6 +309,7 @@ type QueryBuilder struct { irregularMaintTableDef *plan.TableDef irregularMaintObjRef *plan.ObjectRef irregularMaintSkipInsert bool + irregularUpdateMaints []irregularUpdateMaintenance // DML RETURNING consumes an attempt-local row image from a dedicated sink. // The mutation plan and the returning projection use independent SINK_SCAN @@ -334,6 +335,16 @@ type QueryBuilder struct { cteRefs []*CTERef } +type irregularUpdateMaintenance struct { + sourceStep int32 + deleteStep int32 + deletePkPos int32 + deletePkTyp plan.Type + indexes []*plan.IndexDef + tableDef *plan.TableDef + objRef *plan.ObjectRef +} + type OptimizerHints struct { pushDownLimitToScan int pushDownTopThroughLeftJoin int diff --git a/pkg/sql/plan/update_planner_route_test.go b/pkg/sql/plan/update_planner_route_test.go index 4f83cbaf3d41d..a0239461a69cd 100644 --- a/pkg/sql/plan/update_planner_route_test.go +++ b/pkg/sql/plan/update_planner_route_test.go @@ -178,8 +178,8 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) { { name: "multi target", sql: "UPDATE emp, dept SET emp.sal = 1, dept.loc = 'x'", - wantRoute: updatePlannerLegacy, - wantReason: updateRouteReasonMultiTarget, + wantRoute: updatePlannerModern, + wantReason: updateRouteReasonNone, }, { name: "irregular index column", @@ -231,6 +231,24 @@ func TestBindUpdateProducesTypedPlannerRoutes(t *testing.T) { } } +func TestMultiTableUpdateNeverFallsBackToLegacyPlanner(t *testing.T) { + mock := NewMockOptimizer(true) + logicPlan, err := runOneStmt( + mock, + t, + "UPDATE emp, dept SET emp.sal = 1, dept.loc = 'x'", + ) + require.NoError(t, err) + + multiUpdates := 0 + for _, node := range logicPlan.GetQuery().Nodes { + if node.NodeType == planpb.Node_MULTI_UPDATE { + multiUpdates++ + } + } + require.Equal(t, 1, multiUpdates) +} + func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { prepareEmpDept := func(mock *MockOptimizer) { emp := mock.ctxt.tables["emp"] @@ -338,7 +356,7 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { )) }) - t.Run("auto increment child key uses legacy final row validation", func(t *testing.T) { + t.Run("auto increment child key uses modern final row validation", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) emp := mock.ctxt.tables["emp"] @@ -359,10 +377,9 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) - require.Error(t, err) - route, reason, _ := classifyUpdatePlannerError(err) - require.Equal(t, updatePlannerLegacy, route) - require.Equal(t, updateRouteReasonAutoIncrementFK, reason) + require.NoError(t, err) + require.Equal(t, 1, countUpdateFkPlanNodes(builder.qry, planpb.Node_PRE_INSERT)) + require.Equal(t, 1, countUpdateFkAsserts(builder.qry)) }) t.Run("disabled checks keep auto increment child key on modern route", func(t *testing.T) { @@ -390,6 +407,23 @@ func TestBindUpdateForeignKeyRoutingByAffectedColumns(t *testing.T) { require.Equal(t, 0, countUpdateFkMarkJoins(query)) }) + t.Run("multi target auto increment child key stays modern", func(t *testing.T) { + mock := NewMockOptimizer(true) + prepareEmpDept(mock) + for _, col := range mock.ctxt.tables["emp"].Cols { + if col.Name == "deptno" { + col.Typ.AutoIncr = true + } + } + + logicPlan, err := runOneStmt(mock, t, + "UPDATE emp, dept SET emp.deptno = DEFAULT, dept.loc = 'changed' "+ + "WHERE emp.deptno = dept.deptno") + require.NoError(t, err) + require.Equal(t, 1, countUpdateFkPlanNodes(logicPlan.GetQuery(), planpb.Node_PRE_INSERT)) + require.Equal(t, 1, countUpdateFkPlanNodes(logicPlan.GetQuery(), planpb.Node_MULTI_UPDATE)) + }) + t.Run("affected restricted parent key stays modern with child probe", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) @@ -912,10 +946,14 @@ func TestBindUpdateAutoIncrementRunsBeforeForeignKeys(t *testing.T) { return -1 } - t.Run("child generated key uses legacy final row validation", func(t *testing.T) { + t.Run("child generated key uses modern final row validation", func(t *testing.T) { mock := NewMockOptimizer(true) prepareEmpDept(mock) - mock.ctxt.tables["emp"].Cols[7].Typ.AutoIncr = true + for _, col := range mock.ctxt.tables["emp"].Cols { + if col.Name == "deptno" { + col.Typ.AutoIncr = true + } + } stmt, err := parsers.ParseOne( mock.CurrentContext().GetContext(), dialect.MYSQL, @@ -925,12 +963,11 @@ func TestBindUpdateAutoIncrementRunsBeforeForeignKeys(t *testing.T) { require.NoError(t, err) defer stmt.Free() - builder := NewQueryBuilder(planpb.Query_UPDATE, mock.CurrentContext(), false, true) - _, err = builder.bindUpdate(stmt.(*tree.Update), NewBindContext(builder, nil)) - require.ErrorContains(t, err, "auto_increment foreign key update") - route, reason, _ := classifyUpdatePlannerError(err) - require.Equal(t, updatePlannerLegacy, route) - require.Equal(t, updateRouteReasonAutoIncrementFK, reason) + query := bindDirect(t, mock, "UPDATE emp SET deptno = DEFAULT") + preInsertPos := firstNode(query, func(node *planpb.Node) bool { + return node.NodeType == planpb.Node_PRE_INSERT + }) + require.NotEqual(t, -1, preInsertPos) }) t.Run("parent action on generated key uses legacy planner", func(t *testing.T) { diff --git a/proto/plan.proto b/proto/plan.proto index 6ec773bb86223..2e6a56ec5ecac 100644 --- a/proto/plan.proto +++ b/proto/plan.proto @@ -640,6 +640,8 @@ message UpdateCtx { int32 insert_pk_col_idx = 11; bool count_delete_affect_rows = 12; bool ignore_affected_rows = 13; + bool dedup_by_target_row_id = 14; + int32 target_update_ctx_idx = 15; } message InsertCtx { diff --git a/test/distributed/cases/dml/update/update_multi_target_modern.result b/test/distributed/cases/dml/update/update_multi_target_modern.result new file mode 100644 index 0000000000000..e225537e69021 --- /dev/null +++ b/test/distributed/cases/dml/update/update_multi_target_modern.result @@ -0,0 +1,310 @@ +DROP TABLE IF EXISTS multi_update_target_a; +DROP TABLE IF EXISTS multi_update_target_b; +CREATE TABLE multi_update_target_a ( +id INT PRIMARY KEY, +grp INT, +x INT, +y INT, +UNIQUE KEY ux_a (id, x), +KEY iy_a (y) +); +CREATE TABLE multi_update_target_b ( +id INT PRIMARY KEY, +grp INT, +x INT, +y INT, +UNIQUE KEY ux_b (id, x), +KEY iy_b (y) +); +INSERT INTO multi_update_target_a VALUES +(1, 1, 0, 0), +(2, 1, 0, 0), +(3, 2, 0, 0); +INSERT INTO multi_update_target_b VALUES +(10, 1, 0, 0), +(20, 1, 0, 0), +(30, 3, 0, 0); +UPDATE multi_update_target_a a +JOIN multi_update_target_b b ON a.grp = b.grp +SET +a.x = b.id, +a.y = b.id, +b.x = a.id, +b.y = a.id; +SELECT COUNT(*) FROM multi_update_target_a WHERE x <> y; +count(*) +0 +SELECT COUNT(*) FROM multi_update_target_b WHERE x <> y; +count(*) +0 +SELECT COUNT(*) FROM multi_update_target_a WHERE grp = 1 AND x = 0; +count(*) +0 +SELECT COUNT(*) FROM multi_update_target_b WHERE grp = 1 AND x = 0; +count(*) +0 +UPDATE multi_update_target_a a +LEFT JOIN multi_update_target_b b ON a.grp = b.grp +SET +a.x = 7, +b.x = 9; +UPDATE multi_update_target_a a +RIGHT JOIN multi_update_target_b b ON a.grp = b.grp +SET +a.y = 11, +b.y = 13; +SELECT id, x, y FROM multi_update_target_a ORDER BY id; +id x y +1 7 11 +2 7 11 +3 7 0 +SELECT id, x, y FROM multi_update_target_b ORDER BY id; +id x y +10 9 13 +20 9 13 +30 0 13 +DROP TABLE multi_update_target_a; +DROP TABLE multi_update_target_b; +DROP TABLE IF EXISTS multi_update_alias_target; +CREATE TABLE multi_update_alias_target ( +id INT PRIMARY KEY, +x INT, +y INT +); +INSERT INTO multi_update_alias_target VALUES (1, 0, 0), (2, 0, 0); +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = b.id +SET +a.x = 1, +b.y = 2; +SELECT ROW_COUNT(); +row_count() +4 +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; +id x y +1 1 2 +2 1 2 +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = 1 AND b.id = 1 +SET +a.x = 3, +b.y = 4; +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; +id x y +1 3 4 +2 1 2 +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id <> b.id +SET +a.x = 1, +b.y = 2; +SELECT ROW_COUNT(); +row_count() +4 +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; +id x y +1 1 2 +2 1 2 +CREATE TABLE multi_update_alias_source ( +target_id INT, +source_x INT, +source_y INT +); +INSERT INTO multi_update_alias_source VALUES +(1, NULL, 1), +(1, 2, 2), +(2, NULL, 1), +(2, 2, 2); +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = b.id +JOIN multi_update_alias_source s ON s.target_id = a.id +SET +a.x = s.source_x, +a.y = s.source_y, +b.id = b.id; +SELECT COUNT(*) AS mixed_source_rows +FROM multi_update_alias_target +WHERE NOT ((x IS NULL AND y = 1) OR (x = 2 AND y = 2)); +mixed_source_rows +0 +CREATE TABLE multi_update_third_target ( +id INT PRIMARY KEY, +z INT +); +INSERT INTO multi_update_third_target VALUES (1, 0), (2, 0); +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id <> b.id +JOIN multi_update_third_target u ON u.id = a.id +SET +a.x = 1, +b.y = 2, +u.z = 3; +SELECT ROW_COUNT(); +row_count() +6 +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; +id x y +1 1 2 +2 1 2 +SELECT id, z FROM multi_update_third_target ORDER BY id; +id z +1 3 +2 3 +DROP TABLE multi_update_third_target; +DROP TABLE multi_update_alias_source; +DROP TABLE multi_update_alias_target; +DROP TABLE IF EXISTS multi_update_partition_target; +DROP TABLE IF EXISTS multi_update_plain_target; +CREATE TABLE multi_update_partition_target ( +id INT PRIMARY KEY, +x INT, +y INT +) PARTITION BY RANGE (id) ( +PARTITION p0 VALUES LESS THAN (2), +PARTITION p1 VALUES LESS THAN (MAXVALUE) +); +CREATE TABLE multi_update_plain_target ( +id INT PRIMARY KEY, +x INT +); +INSERT INTO multi_update_partition_target VALUES (1, 0, 0), (2, 0, 0); +INSERT INTO multi_update_plain_target VALUES (1, 0), (2, 0); +UPDATE multi_update_partition_target p +JOIN multi_update_plain_target n ON p.id = n.id +SET +p.x = p.x + 1, +n.x = n.x + 2; +SELECT id, x FROM multi_update_partition_target ORDER BY id; +id x +1 1 +2 1 +SELECT id, x FROM multi_update_plain_target ORDER BY id; +id x +1 2 +2 2 +UPDATE multi_update_plain_target n +JOIN multi_update_partition_target p ON n.id = p.id +SET +n.x = n.x + 2, +p.x = p.x + 1; +SELECT id, x FROM multi_update_partition_target ORDER BY id; +id x +1 2 +2 2 +SELECT id, x FROM multi_update_plain_target ORDER BY id; +id x +1 4 +2 4 +UPDATE multi_update_partition_target p +JOIN multi_update_plain_target n ON p.id = n.id +SET +p.id = p.id + 10, +n.x = 9 +WHERE p.id = 1; +SELECT ROW_COUNT(); +row_count() +2 +SELECT id, x FROM multi_update_partition_target ORDER BY id; +id x +2 2 +11 2 +SELECT id, x FROM multi_update_plain_target ORDER BY id; +id x +1 9 +2 4 +UPDATE multi_update_partition_target a +JOIN multi_update_partition_target b ON a.id = b.id +SET +a.x = 7, +b.y = 8; +SELECT ROW_COUNT(); +row_count() +4 +SELECT id, x, y FROM multi_update_partition_target ORDER BY id; +id x y +2 7 8 +11 7 8 +DROP TABLE multi_update_partition_target; +DROP TABLE multi_update_plain_target; +DROP TABLE IF EXISTS multi_update_on_update; +CREATE TABLE multi_update_on_update ( +id INT PRIMARY KEY, +x INT, +y INT, +updated_at TIMESTAMP DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, +KEY idx_updated_at (updated_at) +); +INSERT INTO multi_update_on_update (id, x, y) VALUES (1, 0, 0), (2, 0, 0); +UPDATE multi_update_on_update a +JOIN multi_update_on_update b ON a.id = b.id +SET +a.x = 1, +b.y = 2; +SELECT id, x, y FROM multi_update_on_update ORDER BY id; +id x y +1 1 2 +2 1 2 +SELECT COUNT(*) FROM multi_update_on_update WHERE updated_at = '2000-01-01 00:00:00'; +count(*) +0 +DROP TABLE multi_update_on_update; +DROP TABLE IF EXISTS multi_update_master_target; +DROP TABLE IF EXISTS multi_update_master_plain; +CREATE TABLE multi_update_master_target ( +id VARCHAR(30) PRIMARY KEY, +a VARCHAR(30), +b VARCHAR(30) +); +CREATE INDEX idx_multi_update_master USING MASTER ON multi_update_master_target(a, b); +CREATE TABLE multi_update_master_plain ( +id VARCHAR(30) PRIMARY KEY, +v VARCHAR(30) +); +INSERT INTO multi_update_master_target VALUES ('1', 'old', 'value'); +INSERT INTO multi_update_master_plain VALUES ('1', 'old'); +UPDATE multi_update_master_target m +JOIN multi_update_master_plain p ON m.id = p.id +SET +m.a = 'changed', +p.v = 'z'; +SELECT * FROM multi_update_master_target WHERE a = 'changed' AND b = 'value'; +id a b +1 changed value +SELECT COUNT(*) FROM multi_update_master_target WHERE a = 'old' AND b = 'value'; +count(*) +0 +SELECT * FROM multi_update_master_plain ORDER BY id; +id v +1 z +DROP TABLE multi_update_master_target; +DROP TABLE multi_update_master_plain; +DROP TABLE IF EXISTS multi_update_auto_child; +DROP TABLE IF EXISTS multi_update_auto_plain; +DROP TABLE IF EXISTS multi_update_auto_parent; +CREATE TABLE multi_update_auto_parent (pid INT PRIMARY KEY); +CREATE TABLE multi_update_auto_child ( +id INT PRIMARY KEY, +pid INT AUTO_INCREMENT, +FOREIGN KEY (pid) REFERENCES multi_update_auto_parent(pid) +); +CREATE TABLE multi_update_auto_plain (id INT PRIMARY KEY, v INT); +INSERT INTO multi_update_auto_parent VALUES (1), (2); +INSERT INTO multi_update_auto_child (id, pid) VALUES (1, 1); +INSERT INTO multi_update_auto_plain VALUES (1, 0); +UPDATE multi_update_auto_child c +JOIN multi_update_auto_plain p ON c.id = p.id +SET +c.pid = DEFAULT, +p.v = 9; +SELECT id, pid FROM multi_update_auto_child; +id pid +1 2 +SELECT id, v FROM multi_update_auto_plain; +id v +1 9 +DROP TABLE multi_update_auto_child; +DROP TABLE multi_update_auto_plain; +DROP TABLE multi_update_auto_parent; diff --git a/test/distributed/cases/dml/update/update_multi_target_modern.sql b/test/distributed/cases/dml/update/update_multi_target_modern.sql new file mode 100644 index 0000000000000..b8b6819723239 --- /dev/null +++ b/test/distributed/cases/dml/update/update_multi_target_modern.sql @@ -0,0 +1,274 @@ +-- @suit + +-- @case +-- @desc: multi-target UPDATE uses independent physical-row selection +-- @label: bvt + +DROP TABLE IF EXISTS multi_update_target_a; +DROP TABLE IF EXISTS multi_update_target_b; + +CREATE TABLE multi_update_target_a ( + id INT PRIMARY KEY, + grp INT, + x INT, + y INT, + UNIQUE KEY ux_a (id, x), + KEY iy_a (y) +); + +CREATE TABLE multi_update_target_b ( + id INT PRIMARY KEY, + grp INT, + x INT, + y INT, + UNIQUE KEY ux_b (id, x), + KEY iy_b (y) +); + +INSERT INTO multi_update_target_a VALUES + (1, 1, 0, 0), + (2, 1, 0, 0), + (3, 2, 0, 0); + +INSERT INTO multi_update_target_b VALUES + (10, 1, 0, 0), + (20, 1, 0, 0), + (30, 3, 0, 0); + +UPDATE multi_update_target_a a +JOIN multi_update_target_b b ON a.grp = b.grp +SET + a.x = b.id, + a.y = b.id, + b.x = a.id, + b.y = a.id; + +SELECT COUNT(*) FROM multi_update_target_a WHERE x <> y; +SELECT COUNT(*) FROM multi_update_target_b WHERE x <> y; +SELECT COUNT(*) FROM multi_update_target_a WHERE grp = 1 AND x = 0; +SELECT COUNT(*) FROM multi_update_target_b WHERE grp = 1 AND x = 0; + +UPDATE multi_update_target_a a +LEFT JOIN multi_update_target_b b ON a.grp = b.grp +SET + a.x = 7, + b.x = 9; + +UPDATE multi_update_target_a a +RIGHT JOIN multi_update_target_b b ON a.grp = b.grp +SET + a.y = 11, + b.y = 13; + +SELECT id, x, y FROM multi_update_target_a ORDER BY id; +SELECT id, x, y FROM multi_update_target_b ORDER BY id; + +DROP TABLE multi_update_target_a; +DROP TABLE multi_update_target_b; + +DROP TABLE IF EXISTS multi_update_alias_target; +CREATE TABLE multi_update_alias_target ( + id INT PRIMARY KEY, + x INT, + y INT +); +INSERT INTO multi_update_alias_target VALUES (1, 0, 0), (2, 0, 0); + +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = b.id +SET + a.x = 1, + b.y = 2; + +SELECT ROW_COUNT(); +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; + +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = 1 AND b.id = 1 +SET + a.x = 3, + b.y = 4; + +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; + +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id <> b.id +SET + a.x = 1, + b.y = 2; + +SELECT ROW_COUNT(); +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; + +CREATE TABLE multi_update_alias_source ( + target_id INT, + source_x INT, + source_y INT +); +INSERT INTO multi_update_alias_source VALUES + (1, NULL, 1), + (1, 2, 2), + (2, NULL, 1), + (2, 2, 2); + +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id = b.id +JOIN multi_update_alias_source s ON s.target_id = a.id +SET + a.x = s.source_x, + a.y = s.source_y, + b.id = b.id; + +SELECT COUNT(*) AS mixed_source_rows +FROM multi_update_alias_target +WHERE NOT ((x IS NULL AND y = 1) OR (x = 2 AND y = 2)); + +CREATE TABLE multi_update_third_target ( + id INT PRIMARY KEY, + z INT +); +INSERT INTO multi_update_third_target VALUES (1, 0), (2, 0); + +UPDATE multi_update_alias_target SET x = 0, y = 0; +UPDATE multi_update_alias_target a +JOIN multi_update_alias_target b ON a.id <> b.id +JOIN multi_update_third_target u ON u.id = a.id +SET + a.x = 1, + b.y = 2, + u.z = 3; + +SELECT ROW_COUNT(); +SELECT id, x, y FROM multi_update_alias_target ORDER BY id; +SELECT id, z FROM multi_update_third_target ORDER BY id; + +DROP TABLE multi_update_third_target; +DROP TABLE multi_update_alias_source; +DROP TABLE multi_update_alias_target; + +DROP TABLE IF EXISTS multi_update_partition_target; +DROP TABLE IF EXISTS multi_update_plain_target; +CREATE TABLE multi_update_partition_target ( + id INT PRIMARY KEY, + x INT, + y INT +) PARTITION BY RANGE (id) ( + PARTITION p0 VALUES LESS THAN (2), + PARTITION p1 VALUES LESS THAN (MAXVALUE) +); +CREATE TABLE multi_update_plain_target ( + id INT PRIMARY KEY, + x INT +); +INSERT INTO multi_update_partition_target VALUES (1, 0, 0), (2, 0, 0); +INSERT INTO multi_update_plain_target VALUES (1, 0), (2, 0); + +UPDATE multi_update_partition_target p +JOIN multi_update_plain_target n ON p.id = n.id +SET + p.x = p.x + 1, + n.x = n.x + 2; + +SELECT id, x FROM multi_update_partition_target ORDER BY id; +SELECT id, x FROM multi_update_plain_target ORDER BY id; + +UPDATE multi_update_plain_target n +JOIN multi_update_partition_target p ON n.id = p.id +SET + n.x = n.x + 2, + p.x = p.x + 1; + +SELECT id, x FROM multi_update_partition_target ORDER BY id; +SELECT id, x FROM multi_update_plain_target ORDER BY id; + +UPDATE multi_update_partition_target p +JOIN multi_update_plain_target n ON p.id = n.id +SET + p.id = p.id + 10, + n.x = 9 +WHERE p.id = 1; + +SELECT ROW_COUNT(); +SELECT id, x FROM multi_update_partition_target ORDER BY id; +SELECT id, x FROM multi_update_plain_target ORDER BY id; + +UPDATE multi_update_partition_target a +JOIN multi_update_partition_target b ON a.id = b.id +SET + a.x = 7, + b.y = 8; + +SELECT ROW_COUNT(); +SELECT id, x, y FROM multi_update_partition_target ORDER BY id; + +DROP TABLE multi_update_partition_target; +DROP TABLE multi_update_plain_target; + +DROP TABLE IF EXISTS multi_update_on_update; +CREATE TABLE multi_update_on_update ( + id INT PRIMARY KEY, + x INT, + y INT, + updated_at TIMESTAMP DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + KEY idx_updated_at (updated_at) +); +INSERT INTO multi_update_on_update (id, x, y) VALUES (1, 0, 0), (2, 0, 0); +UPDATE multi_update_on_update a +JOIN multi_update_on_update b ON a.id = b.id +SET + a.x = 1, + b.y = 2; +SELECT id, x, y FROM multi_update_on_update ORDER BY id; +SELECT COUNT(*) FROM multi_update_on_update WHERE updated_at = '2000-01-01 00:00:00'; +DROP TABLE multi_update_on_update; + +DROP TABLE IF EXISTS multi_update_master_target; +DROP TABLE IF EXISTS multi_update_master_plain; +CREATE TABLE multi_update_master_target ( + id VARCHAR(30) PRIMARY KEY, + a VARCHAR(30), + b VARCHAR(30) +); +CREATE INDEX idx_multi_update_master USING MASTER ON multi_update_master_target(a, b); +CREATE TABLE multi_update_master_plain ( + id VARCHAR(30) PRIMARY KEY, + v VARCHAR(30) +); +INSERT INTO multi_update_master_target VALUES ('1', 'old', 'value'); +INSERT INTO multi_update_master_plain VALUES ('1', 'old'); +UPDATE multi_update_master_target m +JOIN multi_update_master_plain p ON m.id = p.id +SET + m.a = 'changed', + p.v = 'z'; +SELECT * FROM multi_update_master_target WHERE a = 'changed' AND b = 'value'; +SELECT COUNT(*) FROM multi_update_master_target WHERE a = 'old' AND b = 'value'; +SELECT * FROM multi_update_master_plain ORDER BY id; +DROP TABLE multi_update_master_target; +DROP TABLE multi_update_master_plain; + +DROP TABLE IF EXISTS multi_update_auto_child; +DROP TABLE IF EXISTS multi_update_auto_plain; +DROP TABLE IF EXISTS multi_update_auto_parent; +CREATE TABLE multi_update_auto_parent (pid INT PRIMARY KEY); +CREATE TABLE multi_update_auto_child ( + id INT PRIMARY KEY, + pid INT AUTO_INCREMENT, + FOREIGN KEY (pid) REFERENCES multi_update_auto_parent(pid) +); +CREATE TABLE multi_update_auto_plain (id INT PRIMARY KEY, v INT); +INSERT INTO multi_update_auto_parent VALUES (1), (2); +INSERT INTO multi_update_auto_child (id, pid) VALUES (1, 1); +INSERT INTO multi_update_auto_plain VALUES (1, 0); +UPDATE multi_update_auto_child c +JOIN multi_update_auto_plain p ON c.id = p.id +SET + c.pid = DEFAULT, + p.v = 9; +SELECT id, pid FROM multi_update_auto_child; +SELECT id, v FROM multi_update_auto_plain; +DROP TABLE multi_update_auto_child; +DROP TABLE multi_update_auto_plain; +DROP TABLE multi_update_auto_parent;