diff --git a/src/air.cairo b/src/air.cairo new file mode 100644 index 000000000..e737af296 --- /dev/null +++ b/src/air.cairo @@ -0,0 +1,8 @@ +mod composition; +mod global_values; +mod constants; +mod public_input; +mod public_memory; +mod diluted; +mod pedersen; +mod autogenerated; diff --git a/src/air/autogenerated.cairo b/src/air/autogenerated.cairo new file mode 100644 index 000000000..86ff3e232 --- /dev/null +++ b/src/air/autogenerated.cairo @@ -0,0 +1,795 @@ +use cairo_verifier::air::global_values::GlobalValues; +use cairo_verifier::common::math::{Felt252Div, pow}; + +fn eval_composition_polynomial_inner( + mask_values: Array, + constraint_coefficients: Array, + point: felt252, + trace_generator: felt252, + global_values: GlobalValues +) -> felt252 { + // Compute powers. + let pow0 = pow(point, global_values.trace_length / 2048); + let pow1 = pow0 * pow0; + let pow2 = pow(point, global_values.trace_length / 128); + let pow3 = pow(point, global_values.trace_length / 32); + let pow4 = pow3 * pow3; + let pow5 = pow(point, global_values.trace_length / 4); + let pow6 = pow5 * pow5; + let pow7 = pow6 * pow6; + let pow8 = pow(trace_generator, global_values.trace_length / 64); + let pow9 = pow8 * pow8; + let pow10 = pow8 * pow9; + let pow11 = pow8 * pow10; + let pow12 = pow8 * pow11; + let pow13 = pow8 * pow12; + let pow14 = pow8 * pow13; + let pow15 = pow8 * pow14; + let pow16 = pow8 * pow15; + let pow17 = pow8 * pow16; + let pow18 = pow8 * pow17; + let pow19 = pow8 * pow18; + let pow20 = pow8 * pow19; + let pow21 = pow8 * pow20; + let pow22 = pow8 * pow21; + let pow23 = pow(trace_generator, global_values.trace_length / 2); + let pow24 = pow(trace_generator, 3 * global_values.trace_length / 4); + let pow25 = pow19 * pow24; + let pow26 = pow10 * pow25; + let pow27 = pow(trace_generator, 255 * global_values.trace_length / 256); + let pow28 = pow(trace_generator, 16 * (global_values.trace_length / 16 - 1)); + let pow29 = pow(trace_generator, 2 * (global_values.trace_length / 2 - 1)); + let pow30 = pow(trace_generator, 4 * (global_values.trace_length / 4 - 1)); + let pow31 = pow(trace_generator, global_values.trace_length - 1); + let pow32 = pow(trace_generator, 2048 * (global_values.trace_length / 2048 - 1)); + let pow33 = pow(trace_generator, 128 * (global_values.trace_length / 128 - 1)); + + // Compute domains. + let domain0 = pow7 - 1; + let domain1 = pow6 - 1; + let domain2 = pow5 - 1; + let domain3 = pow4 - pow25; + let domain4 = pow4 - 1; + let domain5 = pow3 - 1; + let domain6 = pow2 - 1; + let domain7 = pow2 - pow24; + let domain8 = pow2 - pow8; + let domain8 = domain8 * (pow2 - pow9); + let domain8 = domain8 * (pow2 - pow10); + let domain8 = domain8 * (pow2 - pow11); + let domain8 = domain8 * (pow2 - pow12); + let domain8 = domain8 * (pow2 - pow13); + let domain8 = domain8 * (pow2 - pow14); + let domain8 = domain8 * (pow2 - pow15); + let domain8 = domain8 * (pow2 - pow16); + let domain8 = domain8 * (pow2 - pow17); + let domain8 = domain8 * (pow2 - pow18); + let domain8 = domain8 * (pow2 - pow19); + let domain8 = domain8 * (pow2 - pow20); + let domain8 = domain8 * (pow2 - pow21); + let domain8 = domain8 * (pow2 - pow22); + let domain8 = domain8 * (domain6); + let domain9 = pow1 - 1; + let domain10 = pow1 - pow27; + let domain11 = pow1 - pow26; + let domain12 = pow0 - pow23; + let domain13 = pow0 - 1; + let domain14 = point - pow28; + let domain15 = point - 1; + let domain16 = point - pow29; + let domain17 = point - pow30; + let domain18 = point - pow31; + let domain19 = point - pow32; + let domain20 = point - pow33; + + // Fetch mask variables. + let column0_row0 = *mask_values[0]; + let column0_row1 = *mask_values[1]; + let column0_row2 = *mask_values[2]; + let column0_row3 = *mask_values[3]; + let column0_row4 = *mask_values[4]; + let column0_row5 = *mask_values[5]; + let column0_row6 = *mask_values[6]; + let column0_row7 = *mask_values[7]; + let column0_row8 = *mask_values[8]; + let column0_row9 = *mask_values[9]; + let column0_row10 = *mask_values[10]; + let column0_row11 = *mask_values[11]; + let column0_row12 = *mask_values[12]; + let column0_row13 = *mask_values[13]; + let column0_row14 = *mask_values[14]; + let column0_row15 = *mask_values[15]; + let column1_row0 = *mask_values[16]; + let column1_row1 = *mask_values[17]; + let column1_row2 = *mask_values[18]; + let column1_row4 = *mask_values[19]; + let column1_row6 = *mask_values[20]; + let column1_row8 = *mask_values[21]; + let column1_row10 = *mask_values[22]; + let column1_row12 = *mask_values[23]; + let column1_row14 = *mask_values[24]; + let column1_row16 = *mask_values[25]; + let column1_row18 = *mask_values[26]; + let column1_row20 = *mask_values[27]; + let column1_row22 = *mask_values[28]; + let column1_row24 = *mask_values[29]; + let column1_row26 = *mask_values[30]; + let column1_row28 = *mask_values[31]; + let column1_row30 = *mask_values[32]; + let column1_row32 = *mask_values[33]; + let column1_row33 = *mask_values[34]; + let column1_row64 = *mask_values[35]; + let column1_row65 = *mask_values[36]; + let column1_row88 = *mask_values[37]; + let column1_row90 = *mask_values[38]; + let column1_row92 = *mask_values[39]; + let column1_row94 = *mask_values[40]; + let column1_row96 = *mask_values[41]; + let column1_row97 = *mask_values[42]; + let column1_row120 = *mask_values[43]; + let column1_row122 = *mask_values[44]; + let column1_row124 = *mask_values[45]; + let column1_row126 = *mask_values[46]; + let column2_row0 = *mask_values[47]; + let column2_row1 = *mask_values[48]; + let column3_row0 = *mask_values[49]; + let column3_row1 = *mask_values[50]; + let column3_row2 = *mask_values[51]; + let column3_row3 = *mask_values[52]; + let column3_row4 = *mask_values[53]; + let column3_row5 = *mask_values[54]; + let column3_row8 = *mask_values[55]; + let column3_row9 = *mask_values[56]; + let column3_row10 = *mask_values[57]; + let column3_row11 = *mask_values[58]; + let column3_row12 = *mask_values[59]; + let column3_row13 = *mask_values[60]; + let column3_row16 = *mask_values[61]; + let column3_row26 = *mask_values[62]; + let column3_row27 = *mask_values[63]; + let column3_row42 = *mask_values[64]; + let column3_row43 = *mask_values[65]; + let column3_row58 = *mask_values[66]; + let column3_row74 = *mask_values[67]; + let column3_row75 = *mask_values[68]; + let column3_row91 = *mask_values[69]; + let column3_row122 = *mask_values[70]; + let column3_row123 = *mask_values[71]; + let column3_row154 = *mask_values[72]; + let column3_row202 = *mask_values[73]; + let column3_row522 = *mask_values[74]; + let column3_row523 = *mask_values[75]; + let column3_row1034 = *mask_values[76]; + let column3_row1035 = *mask_values[77]; + let column3_row2058 = *mask_values[78]; + let column4_row0 = *mask_values[79]; + let column4_row1 = *mask_values[80]; + let column4_row2 = *mask_values[81]; + let column4_row3 = *mask_values[82]; + let column5_row0 = *mask_values[83]; + let column5_row1 = *mask_values[84]; + let column5_row2 = *mask_values[85]; + let column5_row3 = *mask_values[86]; + let column5_row4 = *mask_values[87]; + let column5_row5 = *mask_values[88]; + let column5_row6 = *mask_values[89]; + let column5_row7 = *mask_values[90]; + let column5_row8 = *mask_values[91]; + let column5_row12 = *mask_values[92]; + let column5_row28 = *mask_values[93]; + let column5_row44 = *mask_values[94]; + let column5_row60 = *mask_values[95]; + let column5_row76 = *mask_values[96]; + let column5_row92 = *mask_values[97]; + let column5_row108 = *mask_values[98]; + let column5_row124 = *mask_values[99]; + let column5_row1021 = *mask_values[100]; + let column5_row1023 = *mask_values[101]; + let column5_row1025 = *mask_values[102]; + let column5_row1027 = *mask_values[103]; + let column5_row2045 = *mask_values[104]; + let column6_row0 = *mask_values[105]; + let column6_row1 = *mask_values[106]; + let column6_row2 = *mask_values[107]; + let column6_row3 = *mask_values[108]; + let column6_row4 = *mask_values[109]; + let column6_row5 = *mask_values[110]; + let column6_row7 = *mask_values[111]; + let column6_row9 = *mask_values[112]; + let column6_row11 = *mask_values[113]; + let column6_row13 = *mask_values[114]; + let column6_row17 = *mask_values[115]; + let column6_row25 = *mask_values[116]; + let column6_row768 = *mask_values[117]; + let column6_row772 = *mask_values[118]; + let column6_row784 = *mask_values[119]; + let column6_row788 = *mask_values[120]; + let column6_row1004 = *mask_values[121]; + let column6_row1008 = *mask_values[122]; + let column6_row1022 = *mask_values[123]; + let column6_row1024 = *mask_values[124]; + let column7_inter1_row0 = *mask_values[125]; + let column7_inter1_row1 = *mask_values[126]; + let column8_inter1_row0 = *mask_values[127]; + let column8_inter1_row1 = *mask_values[128]; + let column9_inter1_row0 = *mask_values[129]; + let column9_inter1_row1 = *mask_values[130]; + let column9_inter1_row2 = *mask_values[131]; + let column9_inter1_row5 = *mask_values[132]; + + // Compute intermediate values. + let cpu_decode_opcode_rc_bit_0 = column0_row0 - (column0_row1 + column0_row1); + let cpu_decode_opcode_rc_bit_2 = column0_row2 - (column0_row3 + column0_row3); + let cpu_decode_opcode_rc_bit_4 = column0_row4 - (column0_row5 + column0_row5); + let cpu_decode_opcode_rc_bit_3 = column0_row3 - (column0_row4 + column0_row4); + let cpu_decode_flag_op1_base_op0_0 = 1 + - (cpu_decode_opcode_rc_bit_2 + cpu_decode_opcode_rc_bit_4 + cpu_decode_opcode_rc_bit_3); + let cpu_decode_opcode_rc_bit_5 = column0_row5 - (column0_row6 + column0_row6); + let cpu_decode_opcode_rc_bit_6 = column0_row6 - (column0_row7 + column0_row7); + let cpu_decode_opcode_rc_bit_9 = column0_row9 - (column0_row10 + column0_row10); + let cpu_decode_flag_res_op1_0 = 1 + - (cpu_decode_opcode_rc_bit_5 + cpu_decode_opcode_rc_bit_6 + cpu_decode_opcode_rc_bit_9); + let cpu_decode_opcode_rc_bit_7 = column0_row7 - (column0_row8 + column0_row8); + let cpu_decode_opcode_rc_bit_8 = column0_row8 - (column0_row9 + column0_row9); + let cpu_decode_flag_pc_update_regular_0 = 1 + - (cpu_decode_opcode_rc_bit_7 + cpu_decode_opcode_rc_bit_8 + cpu_decode_opcode_rc_bit_9); + let cpu_decode_opcode_rc_bit_12 = column0_row12 - (column0_row13 + column0_row13); + let cpu_decode_opcode_rc_bit_13 = column0_row13 - (column0_row14 + column0_row14); + let cpu_decode_fp_update_regular_0 = 1 + - (cpu_decode_opcode_rc_bit_12 + cpu_decode_opcode_rc_bit_13); + let cpu_decode_opcode_rc_bit_1 = column0_row1 - (column0_row2 + column0_row2); + let npc_reg_0 = column3_row0 + cpu_decode_opcode_rc_bit_2 + 1; + let cpu_decode_opcode_rc_bit_10 = column0_row10 - (column0_row11 + column0_row11); + let cpu_decode_opcode_rc_bit_11 = column0_row11 - (column0_row12 + column0_row12); + let cpu_decode_opcode_rc_bit_14 = column0_row14 - (column0_row15 + column0_row15); + let memory_address_diff_0 = column4_row2 - column4_row0; + let rc16_diff_0 = column5_row6 - column5_row2; + let pedersen_hash0_ec_subset_sum_bit_0 = column6_row0 - (column6_row4 + column6_row4); + let pedersen_hash0_ec_subset_sum_bit_neg_0 = 1 - pedersen_hash0_ec_subset_sum_bit_0; + let rc_builtin_value0_0 = column5_row12; + let rc_builtin_value1_0 = rc_builtin_value0_0 * global_values.offset_size + column5_row28; + let rc_builtin_value2_0 = rc_builtin_value1_0 * global_values.offset_size + column5_row44; + let rc_builtin_value3_0 = rc_builtin_value2_0 * global_values.offset_size + column5_row60; + let rc_builtin_value4_0 = rc_builtin_value3_0 * global_values.offset_size + column5_row76; + let rc_builtin_value5_0 = rc_builtin_value4_0 * global_values.offset_size + column5_row92; + let rc_builtin_value6_0 = rc_builtin_value5_0 * global_values.offset_size + column5_row108; + let rc_builtin_value7_0 = rc_builtin_value6_0 * global_values.offset_size + column5_row124; + let bitwise_sum_var_0_0 = column1_row0 + + column1_row2 * 2 + + column1_row4 * 4 + + column1_row6 * 8 + + column1_row8 * 18446744073709551616 + + column1_row10 * 36893488147419103232 + + column1_row12 * 73786976294838206464 + + column1_row14 * 147573952589676412928; + let bitwise_sum_var_8_0 = column1_row16 * 340282366920938463463374607431768211456 + + column1_row18 * 680564733841876926926749214863536422912 + + column1_row20 * 1361129467683753853853498429727072845824 + + column1_row22 * 2722258935367507707706996859454145691648 + + column1_row24 * 6277101735386680763835789423207666416102355444464034512896 + + column1_row26 * 12554203470773361527671578846415332832204710888928069025792 + + column1_row28 * 25108406941546723055343157692830665664409421777856138051584 + + column1_row30 * 50216813883093446110686315385661331328818843555712276103168; + + // Sum constraints. + let total_sum = 0; + + // Constraint: cpu/decode/opcode_rc/bit. + let value = (cpu_decode_opcode_rc_bit_0 * cpu_decode_opcode_rc_bit_0 + - cpu_decode_opcode_rc_bit_0) + * domain3 + / domain0; + let total_sum = total_sum + *constraint_coefficients[0] * value; + + // Constraint: cpu/decode/opcode_rc/zero. + let value = (column0_row0) / domain3; + let total_sum = total_sum + *constraint_coefficients[1] * value; + + // Constraint: cpu/decode/opcode_rc_input. + let value = (column3_row1 + - (((column0_row0 * global_values.offset_size + column5_row4) * global_values.offset_size + + column5_row8) + * global_values.offset_size + + column5_row0)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[2] * value; + + // Constraint: cpu/decode/flag_op1_base_op0_bit. + let value = (cpu_decode_flag_op1_base_op0_0 * cpu_decode_flag_op1_base_op0_0 + - cpu_decode_flag_op1_base_op0_0) + / domain4; + let total_sum = total_sum + *constraint_coefficients[3] * value; + + // Constraint: cpu/decode/flag_res_op1_bit. + let value = (cpu_decode_flag_res_op1_0 * cpu_decode_flag_res_op1_0 - cpu_decode_flag_res_op1_0) + / domain4; + let total_sum = total_sum + *constraint_coefficients[4] * value; + + // Constraint: cpu/decode/flag_pc_update_regular_bit. + let value = (cpu_decode_flag_pc_update_regular_0 * cpu_decode_flag_pc_update_regular_0 + - cpu_decode_flag_pc_update_regular_0) + / domain4; + let total_sum = total_sum + *constraint_coefficients[5] * value; + + // Constraint: cpu/decode/fp_update_regular_bit. + let value = (cpu_decode_fp_update_regular_0 * cpu_decode_fp_update_regular_0 + - cpu_decode_fp_update_regular_0) + / domain4; + let total_sum = total_sum + *constraint_coefficients[6] * value; + + // Constraint: cpu/operands/mem_dst_addr. + let value = (column3_row8 + + global_values.half_offset_size + - (cpu_decode_opcode_rc_bit_0 * column6_row9 + + (1 - cpu_decode_opcode_rc_bit_0) * column6_row1 + + column5_row0)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[7] * value; + + // Constraint: cpu/operands/mem0_addr. + let value = (column3_row4 + + global_values.half_offset_size + - (cpu_decode_opcode_rc_bit_1 * column6_row9 + + (1 - cpu_decode_opcode_rc_bit_1) * column6_row1 + + column5_row8)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[8] * value; + + // Constraint: cpu/operands/mem1_addr. + let value = (column3_row12 + + global_values.half_offset_size + - (cpu_decode_opcode_rc_bit_2 * column3_row0 + + cpu_decode_opcode_rc_bit_4 * column6_row1 + + cpu_decode_opcode_rc_bit_3 * column6_row9 + + cpu_decode_flag_op1_base_op0_0 * column3_row5 + + column5_row4)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[9] * value; + + // Constraint: cpu/operands/ops_mul. + let value = (column6_row5 - column3_row5 * column3_row13) / domain4; + let total_sum = total_sum + *constraint_coefficients[10] * value; + + // Constraint: cpu/operands/res. + let value = ((1 - cpu_decode_opcode_rc_bit_9) * column6_row13 + - (cpu_decode_opcode_rc_bit_5 * (column3_row5 + column3_row13) + + cpu_decode_opcode_rc_bit_6 * column6_row5 + + cpu_decode_flag_res_op1_0 * column3_row13)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[11] * value; + + // Constraint: cpu/update_registers/update_pc/tmp0. + let value = (column6_row3 - cpu_decode_opcode_rc_bit_9 * column3_row9) * domain14 / domain4; + let total_sum = total_sum + *constraint_coefficients[12] * value; + + // Constraint: cpu/update_registers/update_pc/tmp1. + let value = (column6_row11 - column6_row3 * column6_row13) * domain14 / domain4; + let total_sum = total_sum + *constraint_coefficients[13] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_negative. + let value = ((1 - cpu_decode_opcode_rc_bit_9) * column3_row16 + + column6_row3 * (column3_row16 - (column3_row0 + column3_row13)) + - (cpu_decode_flag_pc_update_regular_0 * npc_reg_0 + + cpu_decode_opcode_rc_bit_7 * column6_row13 + + cpu_decode_opcode_rc_bit_8 * (column3_row0 + column6_row13))) + * domain14 + / domain4; + let total_sum = total_sum + *constraint_coefficients[14] * value; + + // Constraint: cpu/update_registers/update_pc/pc_cond_positive. + let value = ((column6_row11 - cpu_decode_opcode_rc_bit_9) * (column3_row16 - npc_reg_0)) + * domain14 + / domain4; + let total_sum = total_sum + *constraint_coefficients[15] * value; + + // Constraint: cpu/update_registers/update_ap/ap_update. + let value = (column6_row17 + - (column6_row1 + + cpu_decode_opcode_rc_bit_10 * column6_row13 + + cpu_decode_opcode_rc_bit_11 + + cpu_decode_opcode_rc_bit_12 * 2)) + * domain14 + / domain4; + let total_sum = total_sum + *constraint_coefficients[16] * value; + + // Constraint: cpu/update_registers/update_fp/fp_update. + let value = (column6_row25 + - (cpu_decode_fp_update_regular_0 * column6_row9 + + cpu_decode_opcode_rc_bit_13 * column3_row9 + + cpu_decode_opcode_rc_bit_12 * (column6_row1 + 2))) + * domain14 + / domain4; + let total_sum = total_sum + *constraint_coefficients[17] * value; + + // Constraint: cpu/opcodes/call/push_fp. + let value = (cpu_decode_opcode_rc_bit_12 * (column3_row9 - column6_row9)) / domain4; + let total_sum = total_sum + *constraint_coefficients[18] * value; + + // Constraint: cpu/opcodes/call/push_pc. + let value = (cpu_decode_opcode_rc_bit_12 + * (column3_row5 - (column3_row0 + cpu_decode_opcode_rc_bit_2 + 1))) + / domain4; + let total_sum = total_sum + *constraint_coefficients[19] * value; + + // Constraint: cpu/opcodes/call/off0. + let value = (cpu_decode_opcode_rc_bit_12 * (column5_row0 - global_values.half_offset_size)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[20] * value; + + // Constraint: cpu/opcodes/call/off1. + let value = (cpu_decode_opcode_rc_bit_12 + * (column5_row8 - (global_values.half_offset_size + 1))) + / domain4; + let total_sum = total_sum + *constraint_coefficients[21] * value; + + // Constraint: cpu/opcodes/call/flags. + let value = (cpu_decode_opcode_rc_bit_12 + * (cpu_decode_opcode_rc_bit_12 + + cpu_decode_opcode_rc_bit_12 + + 1 + + 1 + - (cpu_decode_opcode_rc_bit_0 + cpu_decode_opcode_rc_bit_1 + 4))) + / domain4; + let total_sum = total_sum + *constraint_coefficients[22] * value; + + // Constraint: cpu/opcodes/ret/off0. + let value = (cpu_decode_opcode_rc_bit_13 * (column5_row0 + 2 - global_values.half_offset_size)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[23] * value; + + // Constraint: cpu/opcodes/ret/off2. + let value = (cpu_decode_opcode_rc_bit_13 * (column5_row4 + 1 - global_values.half_offset_size)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[24] * value; + + // Constraint: cpu/opcodes/ret/flags. + let value = (cpu_decode_opcode_rc_bit_13 + * (cpu_decode_opcode_rc_bit_7 + + cpu_decode_opcode_rc_bit_0 + + cpu_decode_opcode_rc_bit_3 + + cpu_decode_flag_res_op1_0 + - 4)) + / domain4; + let total_sum = total_sum + *constraint_coefficients[25] * value; + + // Constraint: cpu/opcodes/assert_eq/assert_eq. + let value = (cpu_decode_opcode_rc_bit_14 * (column3_row9 - column6_row13)) / domain4; + let total_sum = total_sum + *constraint_coefficients[26] * value; + + // Constraint: initial_ap. + let value = (column6_row1 - global_values.initial_ap) / domain15; + let total_sum = total_sum + *constraint_coefficients[27] * value; + + // Constraint: initial_fp. + let value = (column6_row9 - global_values.initial_ap) / domain15; + let total_sum = total_sum + *constraint_coefficients[28] * value; + + // Constraint: initial_pc. + let value = (column3_row0 - global_values.initial_pc) / domain15; + let total_sum = total_sum + *constraint_coefficients[29] * value; + + // Constraint: final_ap. + let value = (column6_row1 - global_values.final_ap) / domain14; + let total_sum = total_sum + *constraint_coefficients[30] * value; + + // Constraint: final_fp. + let value = (column6_row9 - global_values.initial_ap) / domain14; + let total_sum = total_sum + *constraint_coefficients[31] * value; + + // Constraint: final_pc. + let value = (column3_row0 - global_values.final_pc) / domain14; + let total_sum = total_sum + *constraint_coefficients[32] * value; + + // Constraint: memory/multi_column_perm/perm/init0. + let value = ((global_values.memory_multi_column_perm_perm_interaction_elm + - (column4_row0 + + global_values.memory_multi_column_perm_hash_interaction_elm0 * column4_row1)) + * column9_inter1_row0 + + column3_row0 + + global_values.memory_multi_column_perm_hash_interaction_elm0 * column3_row1 + - global_values.memory_multi_column_perm_perm_interaction_elm) + / domain15; + let total_sum = total_sum + *constraint_coefficients[33] * value; + + // Constraint: memory/multi_column_perm/perm/step0. + let value = ((global_values.memory_multi_column_perm_perm_interaction_elm + - (column4_row2 + + global_values.memory_multi_column_perm_hash_interaction_elm0 * column4_row3)) + * column9_inter1_row2 + - (global_values.memory_multi_column_perm_perm_interaction_elm + - (column3_row2 + + global_values.memory_multi_column_perm_hash_interaction_elm0 * column3_row3)) + * column9_inter1_row0) + * domain16 + / domain1; + let total_sum = total_sum + *constraint_coefficients[34] * value; + + // Constraint: memory/multi_column_perm/perm/last. + let value = (column9_inter1_row0 + - global_values.memory_multi_column_perm_perm_public_memory_prod) + / domain16; + let total_sum = total_sum + *constraint_coefficients[35] * value; + + // Constraint: memory/diff_is_bit. + let value = (memory_address_diff_0 * memory_address_diff_0 - memory_address_diff_0) + * domain16 + / domain1; + let total_sum = total_sum + *constraint_coefficients[36] * value; + + // Constraint: memory/is_func. + let value = ((memory_address_diff_0 - 1) * (column4_row1 - column4_row3)) * domain16 / domain1; + let total_sum = total_sum + *constraint_coefficients[37] * value; + + // Constraint: memory/initial_addr. + let value = (column4_row0 - 1) / domain15; + let total_sum = total_sum + *constraint_coefficients[38] * value; + + // Constraint: public_memory_addr_zero. + let value = (column3_row2) / domain4; + let total_sum = total_sum + *constraint_coefficients[39] * value; + + // Constraint: public_memory_value_zero. + let value = (column3_row3) / domain4; + let total_sum = total_sum + *constraint_coefficients[40] * value; + + // Constraint: rc16/perm/init0. + let value = ((global_values.rc16_perm_interaction_elm - column5_row2) * column9_inter1_row1 + + column5_row0 + - global_values.rc16_perm_interaction_elm) + / domain15; + let total_sum = total_sum + *constraint_coefficients[41] * value; + + // Constraint: rc16/perm/step0. + let value = ((global_values.rc16_perm_interaction_elm - column5_row6) * column9_inter1_row5 + - (global_values.rc16_perm_interaction_elm - column5_row4) * column9_inter1_row1) + * domain17 + / domain2; + let total_sum = total_sum + *constraint_coefficients[42] * value; + + // Constraint: rc16/perm/last. + let value = (column9_inter1_row1 - global_values.rc16_perm_public_memory_prod) / domain17; + let total_sum = total_sum + *constraint_coefficients[43] * value; + + // Constraint: rc16/diff_is_bit. + let value = (rc16_diff_0 * rc16_diff_0 - rc16_diff_0) * domain17 / domain2; + let total_sum = total_sum + *constraint_coefficients[44] * value; + + // Constraint: rc16/minimum. + let value = (column5_row2 - global_values.rc_min) / domain15; + let total_sum = total_sum + *constraint_coefficients[45] * value; + + // Constraint: rc16/maximum. + let value = (column5_row2 - global_values.rc_max) / domain17; + let total_sum = total_sum + *constraint_coefficients[46] * value; + + // Constraint: diluted_check/permutation/init0. + let value = ((global_values.diluted_check_permutation_interaction_elm - column2_row0) + * column8_inter1_row0 + + column1_row0 + - global_values.diluted_check_permutation_interaction_elm) + / domain15; + let total_sum = total_sum + *constraint_coefficients[47] * value; + + // Constraint: diluted_check/permutation/step0. + let value = ((global_values.diluted_check_permutation_interaction_elm - column2_row1) + * column8_inter1_row1 + - (global_values.diluted_check_permutation_interaction_elm - column1_row1) + * column8_inter1_row0) + * domain18 + / domain0; + let total_sum = total_sum + *constraint_coefficients[48] * value; + + // Constraint: diluted_check/permutation/last. + let value = (column8_inter1_row0 - global_values.diluted_check_permutation_public_memory_prod) + / domain18; + let total_sum = total_sum + *constraint_coefficients[49] * value; + + // Constraint: diluted_check/init. + let value = (column7_inter1_row0 - 1) / domain15; + let total_sum = total_sum + *constraint_coefficients[50] * value; + + // Constraint: diluted_check/first_element. + let value = (column2_row0 - global_values.diluted_check_first_elm) / domain15; + let total_sum = total_sum + *constraint_coefficients[51] * value; + + // Constraint: diluted_check/step. + let value = (column7_inter1_row1 + - (column7_inter1_row0 + * (1 + global_values.diluted_check_interaction_z * (column2_row1 - column2_row0)) + + global_values.diluted_check_interaction_alpha + * (column2_row1 - column2_row0) + * (column2_row1 - column2_row0))) + * domain18 + / domain0; + let total_sum = total_sum + *constraint_coefficients[52] * value; + + // Constraint: diluted_check/last. + let value = (column7_inter1_row0 - global_values.diluted_check_final_cum_val) / domain18; + let total_sum = total_sum + *constraint_coefficients[53] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/last_one_is_zero. + let value = (column6_row7 * (column6_row0 - (column6_row4 + column6_row4))) / domain9; + let total_sum = total_sum + *constraint_coefficients[54] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones0. + let value = (column6_row7 + * (column6_row4 + - 3138550867693340381917894711603833208051177722232017256448 * column6_row768)) + / domain9; + let total_sum = total_sum + *constraint_coefficients[55] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit192. + let value = (column6_row7 + - column6_row1022 * (column6_row768 - (column6_row772 + column6_row772))) + / domain9; + let total_sum = total_sum + *constraint_coefficients[56] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones192. + let value = (column6_row1022 * (column6_row772 - 8 * column6_row784)) / domain9; + let total_sum = total_sum + *constraint_coefficients[57] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/cumulative_bit196. + let value = (column6_row1022 + - (column6_row1004 - (column6_row1008 + column6_row1008)) + * (column6_row784 - (column6_row788 + column6_row788))) + / domain9; + let total_sum = total_sum + *constraint_coefficients[58] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_unpacking/zeroes_between_ones196. + let value = ((column6_row1004 - (column6_row1008 + column6_row1008)) + * (column6_row788 - 18014398509481984 * column6_row1004)) + / domain9; + let total_sum = total_sum + *constraint_coefficients[59] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/booleanity_test. + let value = (pedersen_hash0_ec_subset_sum_bit_0 * (pedersen_hash0_ec_subset_sum_bit_0 - 1)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[60] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/bit_extraction_end. + let value = (column6_row0) / domain11; + let total_sum = total_sum + *constraint_coefficients[61] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/zeros_tail. + let value = (column6_row0) / domain10; + let total_sum = total_sum + *constraint_coefficients[62] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/slope. + let value = (pedersen_hash0_ec_subset_sum_bit_0 + * (column5_row3 - global_values.pedersen_points_y) + - column6_row2 * (column5_row1 - global_values.pedersen_points_x)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[63] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/x. + let value = (column6_row2 * column6_row2 + - pedersen_hash0_ec_subset_sum_bit_0 + * (column5_row1 + global_values.pedersen_points_x + column5_row5)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[64] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/add_points/y. + let value = (pedersen_hash0_ec_subset_sum_bit_0 * (column5_row3 + column5_row7) + - column6_row2 * (column5_row1 - column5_row5)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[65] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/x. + let value = (pedersen_hash0_ec_subset_sum_bit_neg_0 * (column5_row5 - column5_row1)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[66] * value; + + // Constraint: pedersen/hash0/ec_subset_sum/copy_point/y. + let value = (pedersen_hash0_ec_subset_sum_bit_neg_0 * (column5_row7 - column5_row3)) + * domain10 + / domain2; + let total_sum = total_sum + *constraint_coefficients[67] * value; + + // Constraint: pedersen/hash0/copy_point/x. + let value = (column5_row1025 - column5_row1021) * domain12 / domain9; + let total_sum = total_sum + *constraint_coefficients[68] * value; + + // Constraint: pedersen/hash0/copy_point/y. + let value = (column5_row1027 - column5_row1023) * domain12 / domain9; + let total_sum = total_sum + *constraint_coefficients[69] * value; + + // Constraint: pedersen/hash0/init/x. + let value = (column5_row1 - global_values.pedersen_shift_point.x) / domain13; + let total_sum = total_sum + *constraint_coefficients[70] * value; + + // Constraint: pedersen/hash0/init/y. + let value = (column5_row3 - global_values.pedersen_shift_point.y) / domain13; + let total_sum = total_sum + *constraint_coefficients[71] * value; + + // Constraint: pedersen/input0_value0. + let value = (column3_row11 - column6_row0) / domain13; + let total_sum = total_sum + *constraint_coefficients[72] * value; + + // Constraint: pedersen/input0_addr. + let value = (column3_row2058 - (column3_row522 + 1)) * domain19 / domain13; + let total_sum = total_sum + *constraint_coefficients[73] * value; + + // Constraint: pedersen/init_addr. + let value = (column3_row10 - global_values.initial_pedersen_addr) / domain15; + let total_sum = total_sum + *constraint_coefficients[74] * value; + + // Constraint: pedersen/input1_value0. + let value = (column3_row1035 - column6_row1024) / domain13; + let total_sum = total_sum + *constraint_coefficients[75] * value; + + // Constraint: pedersen/input1_addr. + let value = (column3_row1034 - (column3_row10 + 1)) / domain13; + let total_sum = total_sum + *constraint_coefficients[76] * value; + + // Constraint: pedersen/output_value0. + let value = (column3_row523 - column5_row2045) / domain13; + let total_sum = total_sum + *constraint_coefficients[77] * value; + + // Constraint: pedersen/output_addr. + let value = (column3_row522 - (column3_row1034 + 1)) / domain13; + let total_sum = total_sum + *constraint_coefficients[78] * value; + + // Constraint: rc_builtin/value. + let value = (rc_builtin_value7_0 - column3_row75) / domain6; + let total_sum = total_sum + *constraint_coefficients[79] * value; + + // Constraint: rc_builtin/addr_step. + let value = (column3_row202 - (column3_row74 + 1)) * domain20 / domain6; + let total_sum = total_sum + *constraint_coefficients[80] * value; + + // Constraint: rc_builtin/init_addr. + let value = (column3_row74 - global_values.initial_rc_addr) / domain15; + let total_sum = total_sum + *constraint_coefficients[81] * value; + + // Constraint: bitwise/init_var_pool_addr. + let value = (column3_row26 - global_values.initial_bitwise_addr) / domain15; + let total_sum = total_sum + *constraint_coefficients[82] * value; + + // Constraint: bitwise/step_var_pool_addr. + let value = (column3_row58 - (column3_row26 + 1)) * domain7 / domain5; + let total_sum = total_sum + *constraint_coefficients[83] * value; + + // Constraint: bitwise/x_or_y_addr. + let value = (column3_row42 - (column3_row122 + 1)) / domain6; + let total_sum = total_sum + *constraint_coefficients[84] * value; + + // Constraint: bitwise/next_var_pool_addr. + let value = (column3_row154 - (column3_row42 + 1)) * domain20 / domain6; + let total_sum = total_sum + *constraint_coefficients[85] * value; + + // Constraint: bitwise/partition. + let value = (bitwise_sum_var_0_0 + bitwise_sum_var_8_0 - column3_row27) / domain5; + let total_sum = total_sum + *constraint_coefficients[86] * value; + + // Constraint: bitwise/or_is_and_plus_xor. + let value = (column3_row43 - (column3_row91 + column3_row123)) / domain6; + let total_sum = total_sum + *constraint_coefficients[87] * value; + + // Constraint: bitwise/addition_is_xor_with_and. + let value = (column1_row0 + column1_row32 - (column1_row96 + column1_row64 + column1_row64)) + / domain8; + let total_sum = total_sum + *constraint_coefficients[88] * value; + + // Constraint: bitwise/unique_unpacking192. + let value = ((column1_row88 + column1_row120) * 16 - column1_row1) / domain6; + let total_sum = total_sum + *constraint_coefficients[89] * value; + + // Constraint: bitwise/unique_unpacking193. + let value = ((column1_row90 + column1_row122) * 16 - column1_row65) / domain6; + let total_sum = total_sum + *constraint_coefficients[90] * value; + + // Constraint: bitwise/unique_unpacking194. + let value = ((column1_row92 + column1_row124) * 16 - column1_row33) / domain6; + let total_sum = total_sum + *constraint_coefficients[91] * value; + + // Constraint: bitwise/unique_unpacking195. + let value = ((column1_row94 + column1_row126) * 256 - column1_row97) / domain6; + let total_sum = total_sum + *constraint_coefficients[92] * value; + + total_sum +} diff --git a/src/air/composition.cairo b/src/air/composition.cairo new file mode 100644 index 000000000..f578a175e --- /dev/null +++ b/src/air/composition.cairo @@ -0,0 +1,81 @@ +use cairo_verifier::air::global_values::{EcPoint, InteractionElements, GlobalValues}; +use cairo_verifier::air::constants::{ + PUBLIC_MEMORY_STEP, DILUTED_N_BITS, DILUTED_SPACING, PEDERSEN_BUILTIN_RATIO, + PEDERSEN_BUILTIN_REPETITIONS, segments +}; +use cairo_verifier::air::public_input::{PublicInput, PublicInputTrait}; +use cairo_verifier::air::diluted::get_diluted_product; +use cairo_verifier::air::pedersen::{eval_pedersen_x, eval_pedersen_y}; +use cairo_verifier::air::autogenerated::eval_composition_polynomial_inner; +use cairo_verifier::common::math::{Felt252Div, Felt252PartialOrd, pow, assert_range_u128}; + +const SHIFT_POINT_X: felt252 = 0x49ee3eba8c1600700ee1b87eb599f16716b0b1022947733551fde4050ca6804; +const SHIFT_POINT_Y: felt252 = 0x3ca0cfe4b3bc6ddf346d49d06ea0ed34e621062c0e056c1d0405d266e10268a; + +fn eval_composition_polynomial( + interaction_elements: InteractionElements, + public_input: PublicInput, + mask_values: Array, + constraint_coefficients: Array, + point: felt252, + trace_domain_size: felt252, + trace_generator: felt252 +) -> felt252 { + let memory_z = interaction_elements.memory_multi_column_perm_perm_interaction_elm; + let memory_alpha = interaction_elements.memory_multi_column_perm_hash_interaction_elm0; + + // Public memory + let public_memory_column_size = trace_domain_size / PUBLIC_MEMORY_STEP; + assert_range_u128(public_memory_column_size); + let public_memory_prod_ratio = public_input + .get_public_memory_product_ratio(memory_z, memory_alpha, public_memory_column_size); + + // Diluted + let diluted_z = interaction_elements.diluted_check_interaction_z; + let diluted_alpha = interaction_elements.diluted_check_interaction_alpha; + let diluted_prod = get_diluted_product( + DILUTED_N_BITS, DILUTED_SPACING, diluted_z, diluted_alpha + ); + + // Periodic columns + let n_steps = pow(2, public_input.log_n_steps); + let n_pedersen_hash_copies = n_steps / (PEDERSEN_BUILTIN_RATIO * PEDERSEN_BUILTIN_REPETITIONS); + assert_range_u128(n_pedersen_hash_copies); + let pedersen_point = pow(point, n_pedersen_hash_copies); + let pedersen_points_x = eval_pedersen_x(pedersen_point); + let pedersen_points_y = eval_pedersen_y(pedersen_point); + + let global_values = GlobalValues { + trace_length: trace_domain_size, + initial_pc: *public_input.segments.at(segments::PROGRAM).begin_addr, + final_pc: *public_input.segments.at(segments::PROGRAM).stop_ptr, + initial_ap: *public_input.segments.at(segments::EXECUTION).begin_addr, + final_ap: *public_input.segments.at(segments::EXECUTION).stop_ptr, + initial_pedersen_addr: *public_input.segments.at(segments::PEDERSEN).begin_addr, + initial_rc_addr: *public_input.segments.at(segments::RANGE_CHECK).begin_addr, + initial_bitwise_addr: *public_input.segments.at(segments::BITWISE).begin_addr, + rc_min: public_input.rc_min, + rc_max: public_input.rc_max, + offset_size: 0x10000, // 2**16 + half_offset_size: 0x8000, + pedersen_shift_point: EcPoint { x: SHIFT_POINT_X, y: SHIFT_POINT_Y }, + pedersen_points_x, + pedersen_points_y, + memory_multi_column_perm_perm_interaction_elm: memory_z, + memory_multi_column_perm_hash_interaction_elm0: memory_alpha, + rc16_perm_interaction_elm: interaction_elements.rc16_perm_interaction_elm, + diluted_check_permutation_interaction_elm: interaction_elements + .diluted_check_permutation_interaction_elm, + diluted_check_interaction_z: diluted_z, + diluted_check_interaction_alpha: diluted_alpha, + memory_multi_column_perm_perm_public_memory_prod: public_memory_prod_ratio, + rc16_perm_public_memory_prod: 1, + diluted_check_first_elm: 0, + diluted_check_permutation_public_memory_prod: 1, + diluted_check_final_cum_val: diluted_prod + }; + + eval_composition_polynomial_inner( + mask_values, constraint_coefficients, point, trace_generator, global_values + ) +} diff --git a/src/air/constants.cairo b/src/air/constants.cairo new file mode 100644 index 000000000..a42656530 --- /dev/null +++ b/src/air/constants.cairo @@ -0,0 +1,40 @@ +// Recursive layout +const N_DYNAMIC_PARAMS: felt252 = 0; +const N_CONSTRAINTS: felt252 = 93; +const MASK_SIZE: felt252 = 133; +const PUBLIC_MEMORY_STEP: felt252 = 16; +const HAS_DILUTED_POOL: felt252 = 1; +const DILUTED_SPACING: felt252 = 4; +const DILUTED_N_BITS: felt252 = 16; +const PEDERSEN_BUILTIN_RATIO: felt252 = 128; +const PEDERSEN_BUILTIN_REPETITIONS: felt252 = 1; +const RC_BUILTIN_RATIO: felt252 = 8; +const RC_N_PARTS: felt252 = 8; +const BITWISE_RATIO: felt252 = 8; +const BITWISE_TOTAL_N_BITS: felt252 = 251; +const HAS_OUTPUT_BUILTIN: felt252 = 1; +const HAS_PEDERSEN_BUILTIN: felt252 = 1; +const HAS_RANGE_CHECK_BUILTIN: felt252 = 1; +const HAS_ECDSA_BUILTIN: felt252 = 0; +const HAS_BITWISE_BUILTIN: felt252 = 1; +const HAS_EC_OP_BUILTIN: felt252 = 0; +const HAS_KECCAK_BUILTIN: felt252 = 0; +const HAS_POSEIDON_BUILTIN: felt252 = 0; +const LAYOUT_CODE: felt252 = 0x726563757273697665; +const CONSTRAINT_DEGREE: felt252 = 2; +const CPU_COMPONENT_HEIGHT: felt252 = 16; +const LOG_CPU_COMPONENT_HEIGHT: felt252 = 4; +const MEMORY_STEP: felt252 = 2; +const NUM_COLUMNS_FIRST: felt252 = 7; +const NUM_COLUMNS_SECOND: felt252 = 3; +const IS_DYNAMIC_AIR: felt252 = 0; + +mod segments { + const PROGRAM: usize = 0; + const EXECUTION: usize = 1; + const OUTPUT: usize = 2; + const PEDERSEN: usize = 3; + const RANGE_CHECK: usize = 4; + const BITWISE: usize = 5; + const N_SEGMENTS: usize = 6; +} diff --git a/src/air/diluted.cairo b/src/air/diluted.cairo new file mode 100644 index 000000000..1b95f232f --- /dev/null +++ b/src/air/diluted.cairo @@ -0,0 +1,48 @@ +use cairo_verifier::common::math::pow; + +// The cumulative value is defined using the next recursive formula: +// r_1 = 1, r_{j+1} = r_j * (1 + z * u_j) + alpha * u_j^2 +// where u_j = Dilute(j, spacing, n_bits) - Dilute(j-1, spacing, n_bits) +// and we want to compute the final value r_{2^n_bits}. +// Note that u_j depends only on the number of trailing zeros in the binary representation of j. +// Specifically, u_{(1+2k)*2^i} = u_{2^i} = u_{2^{i-1}} + 2^{i*spacing} - 2^{(i-1)*spacing + 1}. +// +// The recursive formula can be reduced to a nonrecursive form: +// r_j = prod_{n=1..j-1}(1+z*u_n) + alpha*sum_{n=1..j-1}(u_n^2 * prod_{m=n+1..j-1}(1+z*u_m)) +// +// We rewrite this equation to generate a recursive formula that converges in log(j) steps: +// Denote: +// p_i = prod_{n=1..2^i-1}(1+z*u_n) +// q_i = sum_{n=1..2^i-1}(u_n^2 * prod_{m=n+1..2^i-1}(1+z*u_m)) +// x_i = u_{2^i}. +// +// Clearly +// r_{2^i} = p_i + alpha * q_i. +// Moreover, +// p_i = p_{i-1} * (1 + z * x_{i-1}) * p_{i-1} +// q_i = q_{i-1} * (1 + z * x_{i-1}) * p_{i-1} + x_{i-1}^2 * p_{i-1} + q_{i-1} +// +// Now we can compute p_{n_bits} and q_{n_bits} in just n_bits recursive steps and we are done. +fn get_diluted_product(n_bits: felt252, spacing: felt252, z: felt252, alpha: felt252) -> felt252 { + let diff_multiplier = pow(2, spacing); + let mut diff_x = diff_multiplier - 2; + let mut x = 1; + let mut p = 1 + z; + let mut q = 1; + + let mut i = 0; + loop { + if i == n_bits { + break p + q * alpha; + } + + x = x + diff_x; + diff_x *= diff_multiplier; + let x_p = x * p; + let y = p + z * x_p; + q = q * y + x * x_p + q; + p *= y; + + i += 1; + } +} diff --git a/src/air/global_values.cairo b/src/air/global_values.cairo new file mode 100644 index 000000000..5aa1abd1b --- /dev/null +++ b/src/air/global_values.cairo @@ -0,0 +1,53 @@ +#[derive(Drop)] +struct EcPoint { + x: felt252, + y: felt252, +} + +// Accumulation of member expressions for auto generated composition polynomial code. +#[derive(Drop)] +struct GlobalValues { + // Public input. + trace_length: felt252, + initial_pc: felt252, + final_pc: felt252, + initial_ap: felt252, + final_ap: felt252, + initial_pedersen_addr: felt252, + initial_rc_addr: felt252, + initial_bitwise_addr: felt252, + rc_min: felt252, + rc_max: felt252, + // Constants. + offset_size: felt252, + half_offset_size: felt252, + pedersen_shift_point: EcPoint, + // Periodic columns. + pedersen_points_x: felt252, + pedersen_points_y: felt252, + // Interaction elements. + memory_multi_column_perm_perm_interaction_elm: felt252, + memory_multi_column_perm_hash_interaction_elm0: felt252, + rc16_perm_interaction_elm: felt252, + diluted_check_permutation_interaction_elm: felt252, + diluted_check_interaction_z: felt252, + diluted_check_interaction_alpha: felt252, + // Permutation products. + memory_multi_column_perm_perm_public_memory_prod: felt252, + rc16_perm_public_memory_prod: felt252, + diluted_check_first_elm: felt252, + diluted_check_permutation_public_memory_prod: felt252, + diluted_check_final_cum_val: felt252 +} + +// Elements that are sent from the prover after the commitment on the original trace. +// Used for components after the first interaction, e.g., memory and range check. +struct InteractionElements { + memory_multi_column_perm_perm_interaction_elm: felt252, + memory_multi_column_perm_hash_interaction_elm0: felt252, + rc16_perm_interaction_elm: felt252, + diluted_check_permutation_interaction_elm: felt252, + diluted_check_interaction_z: felt252, + diluted_check_interaction_alpha: felt252 +} + diff --git a/src/air/pedersen.cairo b/src/air/pedersen.cairo new file mode 100644 index 000000000..54de76fa7 --- /dev/null +++ b/src/air/pedersen.cairo @@ -0,0 +1,1042 @@ +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +fn eval_pedersen_x(point: felt252) -> felt252 { + let mut res = 0; + res *= point + (0x43869b387c2d0eab20661ebdfaca58b4b23feac014e1e1d9413164312e77da); + res *= point + (0x4cec4cd52fab6da76b4ab7a41ffd844aad8981917d2295273ff6ab2cce622d8); + res *= point + (0x295046a010dd6757176414b0fd144c1d2517fc463df01a12c0ab58bbbac26ea); + res *= point + (0x60105b3cb5aab151ce615173eaecbe94014ff5d72e884addcd4b9d973fed9fd); + res *= point + (0x233eff8cfcc744de79d412f724898d13c0e53b1132046ee45db7a101242a73f); + res *= point + (0x6f753527f0dec9b713d52f08e4556a3963a2f7e5e282b2e97ffde3e12569b76); + res *= point + (0x549a83d43c90aaf1a28c445c81abc883cb61e4353a84ea0fcb15ccee6d6482f); + res *= point + (0x4259be645aaf0a661e7877276fa5559ed7d04349f577595702efed3050402c5); + res *= point + (0x71e67bd6a0b1b8518cb06837a78b92ab3dec98c4989f946285042655ffe516e); + res *= point + (0x19b7924c29a944ecb61165a663d76d84e5ce44b4617fdbca8ff02fbdea6deba); + res *= point + (0x70454f9541d96fc1552f984330389ff616cf80eaf699ba2e82b77f43fd163a); + res *= point + (0x479c09d33c38f1c8f73247aace507da354ae87ca5cd4aa096bd3a6229e3006d); + res *= point + (0x6fcf0e32e3e99f51d8cdac9c19cc25179eb97f2757844fa0c72e7c3bf453e4); + res *= point + (0x4ccee6b6ecd4ea8733198e95935d13474d34cf54d7631fde59720e40378e1eb); + res *= point + (0x627cb37206e5ee9da20c04a92cc765e3bd3f3d4e42ad4de0d709f366d446d8e); + res *= point + (0x4183c04ef7d778f11e57b44c1a7f354c4497f1e3d420d3fa9f9c27c4bb58759); + res *= point + (0x1e2c5c3fb2b47ea8cf33099c610f6132a5dd7099d29b02f4a041fe5947ff53b); + res *= point + (0x4d44944716e0e13728fa8b84fde421f0f66a120ed2b7cfcf59f5ff6718b8b6c); + res *= point + (0x394d0eed011068acc2f55f541c4d113a9c0afe7269cd7d9711aa7e8be661a60); + res *= point + (0x52b5bdbcf28603ba60abcbf52bd4f7b4988ce0b4e2346e4875a3f117d4143b4); + res *= point + (0x5975b93cee7a147a93cc98aabbb713f151924c4ede3306bb5e14e5e4d5d5c05); + res *= point + (0x787053fc3649b17965b9e6ef5e05e024cdc188e90aef1cbf13ba78542a0407d); + res *= point + (0x7cbef72611c8e1e08e52ca202382a8545bc7fe124ec080058988e45771e3b40); + res *= point + (0x32bd55700baf7283995407f470139326a670d60a5d5428904596584629a053d); + res *= point + (0x3485ad12aa365fac51a6296931abdcb54fa848c587cfbfe5bdbad2d6f6d3bd3); + res *= point + (0x7f9850620a3435695ec7a6d9378cfe218ab0e5fa674cdc572fb9c197b0dbd25); + res *= point + (0x1c7c40b6e4cd3d473e8f84b8fa63610ac6c7e3f4f0017f3ed84eae8f042bf15); + res *= point + (0x1e3e1d970342085c482175cf60d93e1cc2cf96dec12f1d839b9b829cc957b7d); + res *= point + (0x2d1547488e174e0a8662decd2cf020dd40718f070c84cf36bfa261aa90f814); + res *= point + (0x31b8dd40040d22aae383c1e628e427f7aa4a7b0c3a83f815fd7ae2b36864af0); + res *= point + (0x5efc7dfab3ad0b3f01e313c50ced95363d8dbaa9f91f801d6f1f00869467a16); + res *= point + (0x724a3072c9f315cba63e5d99034b3218ff29a9bbf04155060ebdd6c848a652); + res *= point + (0x2a0c1eade4037c10729bdc8a8f38bb5bf359078eedba633047377a09b6cde4d); + res *= point + (0x6aacb14e31ebb5066e78eb597842812d7ad137880a6dd0d065c4acee231b7c3); + res *= point + (0x468b88ba32ca1eac6c8d3196eea0561e25770818221ed0da3ae749e2a302e); + res *= point + (0x5b52f487f8c3d78fb6ea4be227325a7386c7e95cd5f9b72710cfcc870cbba59); + res *= point + (0x2bec10dd6a541c12555ff040b5949407713b4227867f53a435e80847b7932f0); + res *= point + (0x41e1c8870eea4b7f4308e8173f97482d80afd055f07b1a058f182a775aef593); + res *= point + (0x126a03f3c5cbe523484111d915d6d7eab5edad02a327a383171be09597336b4); + res *= point + (0xa8db86341624832893780e36fe1f60490da5768f9aeb2a5803240f29ec5a2); + res *= point + (0x751a8c7382e8fc0141b4ec5bf37fa457ab8301640b58cfc3b6a0b8d1a12bec2); + res *= point + (0x5e56f3654b68256095b54a7868763aa3ff60a98ea3508039def82d2098d8a6d); + res *= point + (0x60a9a4ccb72bde44d8a6c5f1d7b9303cc32013ef621bce1b8af413f00e77ef2); + res *= point + (0x4efe82f8cacf9761cac9fefb6c13c1afdaed68ee650c37684bfce323070e480); + res *= point + (0x40c43992a86359c71f5b8051d84d1fd6971eb36ab486f321a1fc50a52a02a44); + res *= point + (0x538392c6ca2c04b5096aa69392b76ff109aabe165df488f3d1a8e5c4022db64); + res *= point + (0x2b783063fa1948abfa91d79d225d52ed2ddd11bf20fc388b1ec00fdb5867921); + res *= point + (0x1ec66f3f326120e659b78867bdfd7dac4dd3f1a92ffeaf46d39725de341afd4); + res *= point + (0x5f4ed6b86202d76686a0b4c1efdfc93c46dce1b843c7181d1db1f8cd4d6dfb); + res *= point + (0x34b9f6e8d5debbb4aea334310dc8d8075f896e7eb9f1c09788c7ec62ccb6116); + res *= point + (0x4e57c6677d3bd56b425a3b3a92517344d4875e1710667e3dee1954395269af); + res *= point + (0x1c5110241881e087e201d211da338d8377dd228afbd84850b76f3e5dfeb9361); + res *= point + (0xa64b536ff29309d613af1c27c7229c3f6c583471c6b589b25026db08d3767a); + res *= point + (0x3f6f9a9c3f6e175b59fd8e4268a6ae5734034fb1d7c43f97ef474b75ba80cc8); + res *= point + (0x775ad15685181f15e34a6b0036c16fc8d1a9860ced1cc5ece39d19a6add939b); + res *= point + (0x7775ec7b0ee9812c8df83957c5b46c316fdac82a2d736d4a6eea6124abc5849); + res *= point + (0x41f320f863037e381ff83f2c9f1a8ae2802fc22cfea674d9cfd10171da6dea8); + res *= point + (0x67649ac75ea692acb3aa4432d48de15aacfa347a37afdf489cc7e954e4ab100); + res *= point + (0x7fd8c6108133b8109f4058192bd614b5de2c50afe7ac08a7bb0e0b12ef04e4f); + res *= point + (0x57f8ef270683ea78b167dcbe5bb122a79ba760c95f8103dc4c6e7788fb1ac9c); + res *= point + (0x6dc0d996fc95036c8cfa408fb12793bf8a4773d698f55085c2ccbc906c6d2d0); + res *= point + (0x6713ddde3f2da61b676f5e4c52177bfc8c1576bc97ab3c48f08ff02d26cc03e); + res *= point + (0x16b450dd2bb4712f6412b35603aaa02e7345124e5fd13e919c269f3874970f9); + res *= point + (0x5f81b087ad750a0ebddd5239bb3682c84d88326b4679a24890f5fec98df45a); + res *= point + (0x33f4151b710663772765df7f95b3710c3e8e81bacdbe3729b0a43b6d19e428c); + res *= point + (0x5d122cd95f43fb6fc2373ef7e66072140f0f20d552f186faff2622b55a3e063); + res *= point + (0x9b478a0767cca2c6f9b4268bffc9e907eb69b32f8ff7b43fc24edd38a88ec2); + res *= point + (0x597cee65bc7c6f0faa3e0aa1958897acf7fd4e4e69569f5d18254b0b8c09aab); + res *= point + (0x218bc11c668ef7ae5f04a16dc9933c5bc41c194a439d0af802568e598c54630); + res *= point + (0x3394eac0b3787b323686cddaef3af972d7fbbd75940bf7f682b8fe3676cd46b); + res *= point + (0x4aeb3836ccb2a9ebf9f1c5b6ee3c42f66c8059cc55188335a47a3583d986018); + res *= point + (0x5db68a5c4527fff0ebf61fe064888b0fb6e277cfecca6d206986293256f31f); + res *= point + (0x63372394d373e7a2f2fa6405509da05fe9cb546ea2742ac0716bccf50ad9227); + res *= point + (0x22d4ed1a29943bc16343e01eab25e45adf74b6a7072e4e26aa8d141f2cac5ca); + res *= point + (0xf8ea3b2c0b72747301b2778cc071cb9d2e09bbdd7a386b7931582ab412dbd1); + res *= point + (0xf78d4b72e0f5f55913884d0714674dd6f534b211ec5dcdba419347828c7c35); + res *= point + (0x5142430fc3f872dd6fefb7e9804e3e63714f71a2f43b155cebc53671f964af); + res *= point + (0x72fe5010e70102306b21cc388b7f2ab8b0324b84654cf98032b83a81099e72e); + res *= point + (0xfd959b09bb704fe63c73e2331f8e76dc1fbf85c2dc9dcaa0e8108664f7f988); + res *= point + (0x4180556f79a47df725eca2c2f65389e27281443847a7d9e84640e6d589182f7); + res *= point + (0x2dc12726f7f06ef1adfb10747e5d4ef8052e4e57bad9bb10529d7994ef91035); + res *= point + (0x3c62720cac42a262b58765d7c0588231c5c2c9ce9d48f0fd547575289ede8c8); + res *= point + (0x5744178090cdd56ae12fdd51b74bc097f23f735b7ca16e415a1854597b1caf8); + res *= point + (0x597cbefb648f47e763b9b1be8c3f815a0e8b65d0101e11b5bedc380c10e9f4); + res *= point + (0x78e66ae8b3ef57289d92561dbe4ef72f4ee551d5cad363720a78d104a89163); + res *= point + (0x3cb89319d8172da012c036c40116fd325d65af69f80a1df8f56ec890e920592); + res *= point + (0x29d152196b7ea7446182efe778a2db796f5fab17286405953476ac97f94a96a); + res *= point + (0x6348748d43d48acafb8ce688f25a1245df86dd20c3a96c5c85cfc0960ca2fa7); + res *= point + (0x3609fff81e15da2a88036d1c2d28814035ce829430fabcc3986c08acdc2d44); + res *= point + (0x3241fcabfd99b666b151970558fb59fdfca47ded4caf2af4b15839767edb190); + res *= point + (0x3f61241934753ca9c4f4210885b87863abdc8637d4dafe5da4bfa5e0206988e); + res *= point + (0x6a16c0b648c72c8d718d53099cb11725ee09fe1b49487d8f55f307a6a265920); + res *= point + (0x43ef0fbc56a0a46c7099f5e6d6550a77e1ac023e2201f01bde0a3f5fb0f16a5); + res *= point + (0x1f6bf768424619cc2d34c01cbf4e137b6cc33a4a5a3db0bc704f790f86ad67c); + res *= point + (0x49eac48d453d5de07fe3f4bdb5aac21e7fe69858afedfbeb0daf175459dd9d7); + res *= point + (0x2a390a6737563e9edc22b0b0cce94a67adc10db18d6f978c826f24b8848c6df); + res *= point + (0x23e127bf290465acfb7500962d426be5241f0e8c6f844d25aa8e262df6e70cb); + res *= point + (0x5e51a00b7437caee2acdb81781212bc3d1c397b477ec784d1a7b304c9f8c687); + res *= point + (0x6e52308f62433fe92ca9064e06aa17d793d3ad7bedb9590c8bb9edd3272fbae); + res *= point + (0x7aa1d2348e13a031dc4fa20d453fcd59eead9adbccc3ea64997d09a0f58216b); + res *= point + (0x1c02d3ffc30c7172a132ac604ad28e89466845c139dba509b896c997ee4ce8a); + res *= point + (0x3ea018d81f9118cb5cf251d6c795b4ca4aeeb28d6ea5464fb4807d219453728); + res *= point + (0x62c2fa993dee607ef195fb6620051b4df127d933de3a417d21de3b0c6dfdc95); + res *= point + (0x2fd6fab5c4d0e6bd5bf5b950632e2dfc3be19c9a80e3bf8934e878003b0816a); + res *= point + (0x12f2b0b280b64cb9f6bd77cd5103b7668ae42e5d40ae156607c69043b4da5a9); + res *= point + (0x51a3ba83e3f68b2df85f3b9e770b5294312fd634fa48ace215a029fdb5593); + res *= point + (0x56f19df91009289c7f5304026cf6d2c26541cd4caf867b2d2ea8a954560ed7b); + res *= point + (0x362dd19b8207511079a352fad991df9582315ca2539ed4da5cbb5b82e414fc5); + res *= point + (0x2dd7ddf328b439b3047a93c6fff6ef901946438cbb55a4c1fa1848f80baf2ce); + res *= point + (0x2120274511adcc680703d33146477a31c42684b5163a628eb3f84258ae78786); + res *= point + (0x11076126b67298371103d89e76ec2fbe30b28c5de422e61d3fade2e190450a4); + res *= point + (0x1868ebbc59cb1c69b32ea2b3a7ce3f87b680731b96a42403878df0a0e4bb3e2); + res *= point + (0x5b7abf66fda1917e0e1d44924cb73d713b5fc16b3a64bd4857d089adfd6a814); + res *= point + (0x13df9c113e40f246d806089e437629de52f8a247ece912785004efcafd4ea94); + res *= point + (0xbdcc31feec5ca8cfbf7227269d1e120132c51307ec03cc2d59c471e2510a24); + res *= point + (0x3b2efe16624d8d0a1beeb037b02f0a4f7e11eb3859852cea1f83ab1752a4099); + res *= point + (0x596104fc8bded038e39f0de5e80a2f2b65fd39fa4ab7b3453bbe8a40e06a317); + res *= point + (0x5fec9e8e9ad35ec1091706f4f39c0e8a610f58be6c987c2327ce0794af7cb7c); + res *= point + (0x5fb45888a7861e18a320bff7b0baee50ef9cbe1b06c78a5a16a6fbda3c6b77f); + res *= point + (0x2c15afc87ef81cb58ec29c7dd81b4cfe291e5d33a7b36126289a8ebc1af4eb4); + res *= point + (0x1f90c3eb7ed36bec79f803ab1884e5455581110ab713139cdb5207561a89a34); + res *= point + (0x7c537f749e37ed15d7e5d5d0f88686c5d02242b6c487ae2c5606d2c7de986b6); + res *= point + (0x4db0795b76ed3b5cf3cbc23bc47d20abe9b9f76a2731f2774e6dd5ecd6eea05); + res *= point + (0x3a7ada56cb16708c6eee7af3688765728c706a16baf61d0582186a3717ef552); + res *= point + (0x4c9b9f2c154c6a8cb1fbf50793787d215f2857d042b21c6f5e2740732cca567); + res *= point + (0xdf2e87cea7f46ab09a5011d8afca4e7cb962e008fc991ea16d85c472dcf3ef); + res *= point + (0x4df83db997cffc8598b838a9c8373bfff5e109d71ee3bf2a18dc0e621e93d2d); + res *= point + (0x17eb7ae4a950bce2abe1e7165594eaa60be7b75cefd8007425a735264a1371a); + res *= point + (0x6c8258350c092e7b5cf658a6bed95d620afe0563482911a1435a93bcb0d5beb); + res *= point + (0x554563c23e6ec8a4497d670e81940a92ddad53c27e7bbc18de74d2b3734d824); + res *= point + (0x6c9568c4a9f64874e71c88cc80576e4083f6d0649f66929612a9bb99bd958e1); + res *= point + (0x14e46f8471beb6479fadac1286dc86683c659bf1c77dc96bcb303d48c115d7e); + res *= point + (0x5eb4774b76a39af609243ea0ca61eaf03255a02d90be9a83901debf64875f0b); + res *= point + (0x3317e8a32e8f82246423237d2a4039eba358a76adb8065751b6d7939fadb85c); + res *= point + (0x6cfe464b2a4d4e77c09e0beceb4e368bd93aae5efaddbb92e003afc508fcb33); + res *= point + (0x3b69a8579df2cea96435a07c81ae1d9f8a5e0e52433335c3e7ad81b76789788); + res *= point + (0x3f26981ddcd3549baf47e3f1242b0bb90d6b7f426ba71d2ce628ceb801f3734); + res *= point + (0x40d8fb43bbc7e5c35e4b57fef4e8351ffb118c9d92346f97ff7cb48b0170eff); + res *= point + (0x19eec9d276c006f19cfa904a4e2ead857e99000d16e897dc8dc955c57615d54); + res *= point + (0xcfff274a78e56ec27e29d01f2e900bd226cdb493a83358f9b807235c9aa407); + res *= point + (0x13d4454abb9515f00c3daa6034ed3759ea722a953679c4f857511141b87da93); + res *= point + (0x2ea5039159478e68762063624b0f396cb7f1bbfe8c1a159f65f0f663f219136); + res *= point + (0x40508ab9b5b8d885f85750bb659071d6cc04639f43070b94a802d41723bd0f3); + res *= point + (0x40a9f47d93280a641e7f903b1e608cb443ed5d59f24cde6b92c6631cab1e009); + res *= point + (0x5a5085cb551c472af264b5de50ebb7b4bb04539c9afac1339f903b943578eea); + res *= point + (0xa89bb9df4a46c56f2f40748d826d50285082118f8995f5e7638a05ec117c47); + res *= point + (0x5950e4370508dbfa764621025e9341994a3ac21848f3e39d02370b193ba6937); + res *= point + (0x6f20da2f1a25f1fab33e7856067226784ad992f8bb53249ee7bb17e86c82070); + res *= point + (0x42271e06f205c1bfc9f9d9411bf835f43941c88aa3dc75f044a0143faa4d5cc); + res *= point + (0x411f9def562556de87d47af60354512d9a1261152e7f4636038699d468fc2bb); + res *= point + (0x66490371a5dfa3fb85bf3f088b89614b5e56cafc263eec39dc4a1bb39e03433); + res *= point + (0x6d49bd35b4e4aa46b7098d306632014b4fbfd84892d6997b58d9463a0ea2c05); + res *= point + (0xa9c2bf87d58d3f72d985b4b1129f0a1664caac1ee26a15675d1a5086de3a79); + res *= point + (0x46df5faa750270394a4253e63ba3e437550ee216ebf8ddbbd7304940c85ad02); + res *= point + (0x6e5bf767f3b0646dc16377f3bb7c17db6069555e100dd2215eb20c4d29fb1c3); + res *= point + (0x5d9acf8582d4ccc017af36a8a9863e4383b63893d3fb5d81f7fabf4ba3d1023); + res *= point + (0x6933ce3f88628188f7a1b1be5b0506dedadd9559c4766be0e7db1ace3adb592); + res *= point + (0x40ba0e2f504aa0e9972018d91be21f56bde16361282915563796c750f8936b7); + res *= point + (0x6fd73eabd21a86dd8094dd0ebb5924b1aab0753a0d251571ea93f83ab4bd519); + res *= point + (0x2761e32194ddef695d1837c8a3f48a3773ae392b5633bfa0c1451e51e33b69b); + res *= point + (0x5519091c464bab5646294ae41d087ddcef8bd0508a94a07890fa07220bdaad3); + res *= point + (0x3b160cef807b72e95938852093a3a633e72b61e0afad5099201885b54be4098); + res *= point + (0x7692b996dcfecd35db6aa22de10144724c478f85a328ab893c6fbadf43d7a9e); + res *= point + (0x3512eb8a3bbded6fad1c19190d857629efc56f93fb4aa527e2958dfcce12153); + res *= point + (0x591ad3fb7ab83f8d9fcf184ab793baf3db128cda0de1618932851108771cf0d); + res *= point + (0x5f7da39edb0781ca1f96af191cf4c70fe0c121b7b2c92f09b49503bb070dc99); + res *= point + (0x4a94669a4901cb5527124a2dc7ff6c278d540da41a95e819d0ca10269f7b380); + res *= point + (0x20a06257ccfa90a74adf9bb1130a8385b8c91bc61e18acc30843463e5abaa2); + res *= point + (0x7e3c052c620ef7fcf180898d28e39348e96e92ed0634dcae3f5fc64be5094a6); + res *= point + (0x578dfc700a95a564b41ba8f33b885ad04209bf5169a4046f603a3d84f792d6d); + res *= point + (0x796c9b073e2c56f55601eb1f6147d028553275e9fb792f0b76007c9710459c7); + res *= point + (0x8c2c75a2fe00432f77ef57e906f264ea76c439e0c4cb19e87867a6ebb34d0a); + res *= point + (0x525fee2e2cdb7a293f50f630a840d5cf5f29a158eadd6fa9d0159951712d19a); + res *= point + (0x7991462c103abfc3bc31427227b1fb82f7fdf2be1b39316f46e3baef2fcf588); + res *= point + (0x46d1e806178137e82ea97c54d8c15dd45c2a9a0082b18aeb9f849158ffc0ee5); + res *= point + (0x25a127bbf961fe2b5bd9facbda706223206c40acff003152cbb3b28e9668030); + res *= point + (0x1e3d7c65a8f40b6f8aab1635e3b78d0f798746532f08771267a9b6149632a5a); + res *= point + (0x25fc8ba8ab421b6dacf2ce03263e037374e4d61c6ce26422fbcb2e755c0d9c4); + res *= point + (0x48294f41052135cca94fcf88cf236437b8a55370c3de81fb0d781aa7b0f8eca); + res *= point + (0x8c5762a12210a7fdc96a7d3aa966476d3b28650e7c49fc90f95e49a80d4324); + res *= point + (0x4ffe8275d3344b4ae2f7d9992d68598e50f365c0b8a721d723841485fc25c0d); + res *= point + (0x2959a6947bc4eee0135bbd0a6f2053b62317a1718bcceecbd507417d31e8806); + res *= point + (0x77efd8893058f8e00863205582a5e274c344b9af63b9c40ddd92c97c33b52ea); + res *= point + (0x73796a0ce0fe851bc22b99faded48a24a21745bb62603e750f78b854d7c32c7); + res *= point + (0x2d2e43c0ad60d4265774479258211274ae32b5e151aacf6f8ac1b7708076f09); + res *= point + (0x22b5eab11c9e1e6b8d64d5db4b12502fdf0899497f72ee1a27c8797b617f76d); + res *= point + (0x703c768145191a10344e5ca400be8fd249e653d564015d46fcd7096cb723a0); + res *= point + (0x4159f8056bde7fd4f72615f7bdd0bb6408256b8b216ca52fee253113d9d007c); + res *= point + (0x5fde2cdf0d23d5649e3aead1b2b90ca0309715a029654e8984e43de7bde7b06); + res *= point + (0x50372d2aff2ebc566505a564d971c6491095e009d9887899aee0b5017fcb877); + res *= point + (0x3333c3d925d8c58b9e4e533531e93046039577cf0e57d011c7ce87c6ef1a835); + res *= point + (0x575fb11a4d7e3876ae4c86b80b4b9530e0d3e9db218f4d5644f612348f8f002); + res *= point + (0x3481879ec47fc8cfabf38ffaa75311c787b7006e7f9def35e96454263bba4aa); + res *= point + (0x5c1e733995aad208f0697e4d2a6e28bec9fddc3e30bd033f2f50a83927baef1); + res *= point + (0x2edf44b1f59efb0f36c0fce5edbb7576c89cb9f191300fc5e0240def1b88b9d); + res *= point + (0x1d46036b736e06016c817d2b51a0918189881a4f1b7c71d556db583df762d37); + res *= point + (0x258ef77b90879282ccc2ffcea5052cad266d77b75db36b7996e5fe7638e9b00); + res *= point + (0x4219a0a13e09662f3ec712da51b36967947f6d5a09d8044e3005a7f0ab45915); + res *= point + (0x18d0f552fd62f81b6076265c7a3a0b81f6bd37152a2f16c71210021ecf68468); + res *= point + (0x31abb6310a44d65ac8c308011d4afab938fdacfbaec14c62b808452310b799b); + res *= point + (0x1765a9eca4f4551f177b35089f8befc808613bbcd971a47d485b1c220d0bbb4); + res *= point + (0x7fd44af0ef24f061aa7dd5bbde15098dfc3721790ee9bac2caa71cca714ebf0); + res *= point + (0x566edfbe3c59cbd43838ee245edfebe292c7163f79b1454b03ef3cf8af23c10); + res *= point + (0x14d01a0c81aa61c5a238243e78afe80e5d0d7bf528c3d05a343d0f4470d2b0a); + res *= point + (0x38445d5f2de7993c48c9da8e77a87dbe289dc0428b1e4ca87e30b2376535543); + res *= point + (0x324db878e3842c25a78e94453c98434c54b41955db62234b0ec5ddde6641556); + res *= point + (0x184f23c10c726d4a7036c39466db02c4fe7c3d40bade571fe07acaa282f4c07); + res *= point + (0x7fb1cbd7a48f2d44a148bd4d17ccd47c438f4f1b45a02945cf4312afa0d6f95); + res *= point + (0x20d2002cba899acc7d333031e0977d8df94557ca0749bef6c38b72dbcd462f); + res *= point + (0x75bd5b63008c2e005df64ca189ecce11c060f0df6903011a3d95cf9f7b48878); + res *= point + (0x548724b5683cd6427513b4c4f84a6d888b9a03843bc0dbdc501b8752d99ada1); + res *= point + (0x38441dfe93fd3133faf52208f3263d4ecaca0643bf9c9d4bc952c86cf280f7a); + res *= point + (0x182e50e36b753ff5f95f2bc47a6aac8c6f2e5c3975476252a7c29250eefb056); + res *= point + (0x2593b010eb6fe0f64833e4f22f6854c063085e0dd393226e6b5fb20ea7f432d); + res *= point + (0xcc060a8b007b2dd0efa786afa5edcb512d83ddcba8ed69c27ccef5769deb23); + res *= point + (0x672717b74bc3dca9e53494681a5ffa02edbb0290de1c5209843a16964df7a3); + res *= point + (0x53774852c8f84d21eec107e1da7a2ab3f4b5ceba6479d1f902ad404e7dde329); + res *= point + (0x96de7b9a7eac739df4d13902971804aaf40f5559d18593be0daac0ff86c636); + res *= point + (0x725601ed4fcfdaa392b91e8ea982fc57f1874378ab8d6b55301b3d4b6efd802); + res *= point + (0x7bc4fea0ea687295d72735a62a19c1a160a1b9a19342717b527f94770aca77); + res *= point + (0x3dfab578cfc7a1581212074e0969db9accb619a043dd7194a253af67ef3698); + res *= point + (0x44090861421dbb6b4a325a6832e02986be80f7ea475313ae01a3215c3510346); + res *= point + (0x7384363b4495aacafd81d0a139a66afd3243309395e3444fb3f1496832240a9); + res *= point + (0x4f6ea70b9090971f8de7071f27b0d036b112211403e0547fb7b7903704f295b); + res *= point + (0xd55dad93e837d31e8f120398e09b83ca68f160c16043e1c65d033a19adbc30); + res *= point + (0x6cc09dc2faf0903dbf5121b97ef058300b18efcc30c25f55de752d395b568a9); + res *= point + (0x2b2091e41b10140bea196a1cc28d7f6db6ae1b55d1f115d882c321221a32eb4); + res *= point + (0x11b19b3abd2b297728768027b1370566bd845bfb6f49197a76255c1d8c661f); + res *= point + (0x3236ab2e0e0b1b013c2100283e36fe75521bd50091f1c73deb165e86616d80a); + res *= point + (0x7351448e92ce6914278e73ceeb080e280c146dbcc21cb35af8d2c7e5560aa7d); + res *= point + (0x100a89bccb889f183c2a6ced12bab8ef86403230ae6b23def0b784f73ff296f); + res *= point + (0x31e49312e1d59acae36bf3562443259500039a7a77d9a57a44cbbb4a80932e3); + res *= point + (0x273647256f95d2e5f98bd7830191abd89dc4ab241fc7fa12b27e16a6bd423c3); + res *= point + (0x424396bedfddf4192963ef0f87b3989a99f277fe2c60756a4a60fae4d6dfa31); + res *= point + (0x6e3a0355459b8b7c35837f3f19f0d8954907326cb08d7d084f2ed0f4b2af8f5); + res *= point + (0x2d88caa65f47db103fb1ca354bf50c93f24bca5001598f716b6c9e5c51d1d2); + res *= point + (0x2dca037a615e8cf99f8614f437e953c5625b9b57d95f16c174f63346e31c5da); + res *= point + (0x5800bf15808a39f1acfbb193af1ab0c22f18d9738753bd3cd2aeea81982409e); + res *= point + (0x4ad97a9b0ab95abc1b8fcff31a48e18fb2391ac95baaacc62125bd87fd75e13); + res *= point + (0x5ba49d41f62b6d6903fc455bf02bca54becb6ee7f39650fcd0b717ac396159c); + res *= point + (0x959c7bf3885d75ab3ca9480101ff64d62c9f138d35f63c137009c1b3eb39f3); + res *= point + (0x6da06ce868c140c8ff9ec1eb0323fe2c8b35b46c8d4f5a27727450e87ebd906); + res *= point + (0x1bf01c19527dd1d9094c44e3acee4d1ec8c4192026b6f996776294cc9dbc4a8); + res *= point + (0x40d1ae7e7bcddc520ed8c0fd736e9b5147d278ed1b720abf76439377023abea); + res *= point + (0x2f26fb29017b5ab80328de8488db547e47c44c0d56f30e330354d5b980e50ad); + res *= point + (0x72bcdfbdd09f13eeb0c01565dc6a79999a9642dbcb0c570e3e7621ca94df215); + res *= point + (0x140ed138dfc5b5417b25a4512bb991f3fd04cf750e082fd4fb82cc15b645835); + res *= point + (0x40ffb20c2a3dba0a0d8b6aa51ccaa1b690aa08670ceee556d76053cd671d522); + res *= point + (0x283c74c8066141911634401af10106c29dd77458d059ff3b2dd7aa796b2a559); + res *= point + (0x593df80dd238cbdc6398146502310a5cb459b0e7d79fa9bee5cc389385c95b3); + res *= point + (0x669bfada09faa64c005321d60752662598d69c517e9ffa462dc1b1af42228d1); + res *= point + (0x70cc78b821b198e72f8feeb8f31d81e5a4854de3575a62909e0bb51cee921d0); + res *= point + (0x68539d0ccd1737a8b2e540f9165638f86f6c4e44943455d311999b0b3684b7d); + res *= point + (0xbb867c323532bde3d5b0e08b1b7531a95a2a1706132dcd8ebb7063cd1b1bbb); + res *= point + (0x751a2c218f4feffc61e90939c4d2672a263d3b33528c7c6eb40042640f45146); + res *= point + (0x6473d78fc37e48379ef8a9d57e3e92cf4fdad3a1bcc170dd177dbc51c4dc62c); + res *= point + (0x7218f86344ea46cdcc372a22a14663105eef03bb0de9da9bfcd10818d36ba28); + res *= point + (0xaa17b17cdb757833dd4b1670371ef55345debfb2c1b6bdfae64d8759e04349); + res *= point + (0x38cb4173a2b057da41d5d30b55f6d11f25effdc69c14843cc43a9ab269630f0); + res *= point + (0x4350a29d7b4b242b20b68f6eabd75b758d8631c192b7da5032181b71740b96b); + res *= point + (0x42518069a18922e90fa2fa8fe9bf5e2371a40ea88c25d247e6a73a007105dd9); + res *= point + (0x7f43f7128a1b46f8ab168a06df9d0cade82a3193eec2d51e2b83f4f0c7fabd9); + res *= point + (0x6e694d9385207d7cc8a7cdbf90eb4ed3be49cabc0e6b8d0e69172d73f4a5c11); + res *= point + (0x2782ab60e8e9c6cccd40f438a2d2814ef39f50f02bbeb790bc6df78d75af42b); + res *= point + (0x259f8eeaf6cbdabd37b9de029661bdcb219245a7599207d3df08c7cc452a13d); + res *= point + (0x9345d2e4fc86ae78c4879ecc3adf9e6c482044052bc3738618247b60f069ad); + res *= point + (0x4419f27879dacd62144bde4f904890c6d5b312282335a57cf1b04b403bddbea); + res *= point + (0x581755fd25823d2f3b07ac5d8dd1bd5b26eab362cec3f9e03573a2b03f62ab9); + res *= point + (0x37622de79f6252ff6bb76900db06504434856faf33c59a1b2e39a4fa60ed143); + res *= point + (0x2c4ffe18ae93ab53ff6d7d01a7b5bdc5b08dc8d144e0b917f47e60e3cf723f3); + res *= point + (0x42ca1f8224d317275c78ca7762a78e6c51978afe1abcbf535da6d299c799c1); + res *= point + (0x6403910df189d75aca61c604de3b0802a4ec2ffadb0ff60f1a01f363d66ea67); + res *= point + (0x44094080f29bf84d3d5849f264713647289e9af1534ec38d1a7c3d2d2f1ab64); + res *= point + (0x3dd2900899d2219ea16fc41413af028057f0c2a674e1cc65032fe4dcb062d4d); + res *= point + (0x5a612887264b1ff8e5239b3e04143dc30d0a80cef1c880fe52ee2d5009092b1); + res *= point + (0x5ca2e5676dde96127ca85ff6ac82a8fb35b45651b88bcdbfab7ae5298d427c8); + res *= point + (0x4b135ec421e9138d09c709a5d92ba70e6944cd44a7eb7f705ab3612de315ac); + res *= point + (0x152b3265b01fa9ce0cdf58c17cd14c2cf3e3fafba140db9e27da4fdde7d3c0d); + res *= point + (0x55554f904554d2f262d1db49d7c515414870717c829b73d6c439260a8bba3da); + res *= point + (0x3e2b9e4151827bb0d04858df547978536215dc06143674d0d2e788dcdc9c36); + res *= point + (0x2c30d5e07853079c9f11624e2431795e2bd8b4bebd8cac92f158306b45b0549); + res *= point + (0x4e922a3c7df1c668f86b866cf0c07ee4658e7754f6fc0fb62cb297bb6960320); + res *= point + (0x35b787fb9889163a9fb5ab831838f19092aa4ef8d8dabb299045740959573d4); + res *= point + (0x2d847968e995dcfcecc6ef98ab27f9f1db36b14ce3ba81b80cc92cf19750f88); + res *= point + (0x6785d833096c9d9d06034ba4d7f8d71481d4b680b63693d9fa24ea10d3511cf); + res *= point + (0x5617f72f8d0da5d7cafeef9269395ee34f921f5cc8d1a4f4c0292a83cb0b9bb); + res *= point + (0x6a1373cca7777e3cfacc6502ca9bc645678445d98acf3d6f5ca6c82cab53174); + res *= point + (0x5b07a69abcc274ea09eb67f2f6036b492db1f9b7e0a3497d8f3920de22b3b4); + res *= point + (0x74399a1effe3a13a8effe952dd57142c254ebe807a56f13521da38984a0b55d); + res *= point + (0x6a399f5bede4f507c7251a7ccd110e21173729f5f9a57eb16a27203d3c5e731); + res *= point + (0x13102ce3fef387b552a6b8967f788cc8f8502ef0f2ec293d2b872328f78b6c9); + res *= point + (0x2233376db0eee71ed0bc6ec0de23782ca9e244a06b8e515b2855b522259eda4); + res *= point + (0x6319176edd9fe726efbcc70108b516e26152cb56329b842a1e14adc2a3e47b2); + res *= point + (0x12e828f63839dc0dd62bc23385c0bdd5b11e7b6de2cddeccc47f85027c9862f); + res *= point + (0x1b5bfb21e549706eaf5c771448f91d1ce03498029ff4159d8cd11f4b6d523a8); + res *= point + (0x223b2c9fcd5a1d4b0f7decaab98bdf87e5083865ef9b6562a261fc75009e725); + res *= point + (0x6856abcc37696eadf09ac823f589a05b034ef8f86e41d2c6222f039707017fb); + res *= point + (0xabbe74553aa10ee20ec6f0f49f73281124ca34d0b71c2e80160f37d3ae0345); + res *= point + (0xf7043785f78a94a68b669cb366c00538eafb8e87b5380c68518d4e23922d6f); + res *= point + (0x43a4dbc140986d44a7099720e13ec46817f0131dd109a48fbbcf190671f35d6); + res *= point + (0x7fb8438581e1ae31877119b91ef1ea28181ba8c0a89eb356313c8a910295d7c); + res *= point + (0x125399adcf39aaf7962e3be41c6f9c7691e45c2c31b937e26257d94b5454985); + res *= point + (0x3a3c97667e93fa5cc0531c8a2f6d9f84c4f683133b8941fe1382ca8f6f2fe0d); + res *= point + (0x253548b05c44cb4d8f2d97641773cf812f709663fe8f492f5a77bfbc8477d79); + res *= point + (0x3e828a46091dc07cbbbb0dcbf390e4b5cc44d086b0ba74051fff237f7d6a74a); + res *= point + (0x74a80f191573d77481059c14f56764dd2c11571b2736d355efa299c400f0377); + res *= point + (0x76169700b631b19086b8b1737e23f1c59cf1428075904c80db724383d3c6b5e); + res *= point + (0x7febfa3ce41434e03eccb6be0099dc31d90e36558dfb6f9d21b3e0be41472b4); + res *= point + (0xaee16ac845b8bdb7d9c1c85ca7b0e749a7c47229ba24ba097b4b6b8151cc4d); + res *= point + (0x31cac8c51732d8aad5bc41c9a6440d482c2c4967e75a571c31b2d9aaaa64068); + res *= point + (0x203db741e5e80c19c2bea387e3091420b918fe1142bcf2bc13ae7e098282fda); + res *= point + (0x2449d2be3af1fcd8984a9f857309ab5e0e5c010680e33b03a194c6e902a553c); + res *= point + (0x40246dcd91afc0098ab9568a5c97d54e09065c551bc9d26ba0ab6a00089bec); + res *= point + (0x50cdaac85b8d8bbf55a920bf8d213e333eba5f2bd92e92c61f3946617222ade); + res *= point + (0x65dbe95ea2b7d1894854b235f2cc66e910fd2791ff09b92366c7685c652a8c7); + res *= point + (0x18f3259c8451dc5007e94efcc6e90c6951543474925fd28ff35e56890bfb66); + res *= point + (0x69021f5cefc75ce473977c2ceae2e7c66a84bb3d734eebf4bf497e56eb69959); + res *= point + (0x4ded7eedcfca4ee336fa075aef6a017beab322cf7ddf83bccfba05f1c93cad); + res *= point + (0xdcc0df28639fd96570d93a6d1df1cb1dcf6db8a259ab092b34cdb411895aa2); + res *= point + (0x2333165fa7f9414f082253b8451638fe1e9da3ba8c1246723dbf9995e49d017); + res *= point + (0xc8b65a737b5605606028a064d168ccf32d8d87fcb55c6c853fd95ae0961410); + res *= point + (0x71d72b0c23e31d703f0210ecb2b28994ad828417531a15a17a1fd401daca2cf); + res *= point + (0x211c3e223a3c9c4a024b490a819254ee133ef9740a4026eb3a036bb9e5c6581); + res *= point + (0x621692ad7ad27517f4de4e528e1271719cf5b344d463c86b9cd8424a4fc274f); + res *= point + (0x5ab65084f4ee8261bfd290e2d5608fde744be92da2eadd5f2fb909ac3d14818); + res *= point + (0x5896811c73c991f479c7af6238b51252178dcf4371c297326bcceeb8ee454e2); + res *= point + (0x453705ada0d5db6b0afb289b29db6c9acedb01e742cb0d68705d07f8dfcfaae); + res *= point + (0x168f97539fdebde7280f4d33f7d5b469cca77495efd4660f31b7d8018f7f89e); + res *= point + (0x7829c898e33552459e8fff13c01f1e0d9f5b098f0de7161cbf97da52914bc38); + res *= point + (0x5b23dd8ead53bea28246af5a3a63daabf41e7987fe61255d97f2a57bb6d14eb); + res *= point + (0x7b631dfaa76643b5f46a069b8c40038f77f088374320add0ac3c9924a12f153); + res *= point + (0x2408fff139dae5eb756ea03ef15a2484f582f7ab27ccaa09fa8154f3bf0024b); + res *= point + (0x28aa32bfd8c8d7ffcb0b5dadfcfd1b6bbd69b02de9ac1bee786da98ce76c8e1); + res *= point + (0x33eb39eae1db6ea48126be6b300b31f6bbe275845822f9eb293e9f7ac38a777); + res *= point + (0x3e549a3d3849a09d8f1c50f84f7caa4aa0a5b8ef6f957dafcd13c7c90e4ea11); + res *= point + (0x2f5e865731de5068f289b616b39c2294284c111540abfdbb33a39780eb0bceb); + res *= point + (0x4e51def182a5bd5672ced3106f19ecd94b760dcfc68e66a3656d0b5db19165f); + res *= point + (0x42f46c19b87a82522476372ae65817f8d53f263674a040531bb37935b289893); + res *= point + (0xf0bd4817ef6ef818a35ca3678f88abb078678a1364539bd7886dad527cb28d); + res *= point + (0x501f0235f18b49889497cf7c91fe0a1f81d74da8cb1e88bcfca9127392aabfd); + res *= point + (0xc11cd155f0a514a5a419d10ffa72405817256ffc8d580b9d3ab002f596b2ff); + res *= point + (0x9f712ae0384a87901ad44f53eee9e7c39544893d10b891a92e87e4d78e8374); + res *= point + (0x2d511bed457c57d7354252189efd19e4f5c3496c1dbe1f1408ff79c8cb97025); + res *= point + (0x6c8d7abe5c83db80647ff904bdbf25bd0e979607d2310ffbefaa1edb7ae1bb9); + res *= point + (0x46e747695d9d234e15781125d05b85ce3cb01d676ef8fc45a939d5e6d4e2e56); + res *= point + (0x21c86da8be11246b29f17d5f7f3566c20712711e03eba57f0ecace8c4355418); + res *= point + (0x7b851f4004fd9f20561e3755d7c89528ddefddbbbcbaa9293e416c0dfbb95d1); + res *= point + (0x31587ae13086228663118a1fbfad6d65bb9741d5682abfb43c7524cc6c240e6); + res *= point + (0x2ef1cb499e790f2de6129225457520b560c1c3120457e742957d1148bb934ca); + res *= point + (0x781fe3d95c096c6df1c9ced110914917e26d0860da4bd769e4682a17540768b); + res *= point + (0x7cf92bf7e933187b6ea01019ed1c2d9936e53a9ea89724e00e36672dca1e36); + res *= point + (0x290b573a86b30d59fd1301b7985a68fd9bf9dfca5451179bcd13d10eee988aa); + res *= point + (0x4d3987a0850d8159f9290a8ae8cf99a0ece9961d22135b584d8fc742d42c15f); + res *= point + (0x6247162754e5af6a0efa837daba678811cd749e92d91acf35d732aaf4bfb4f3); + res *= point + (0x1e3df9ca8b80529441770e007a27cda52e54307e4f3370a83705e0f3ffc86fc); + res *= point + (0x25579cd0082839ce295d9bdb24140a8f2fe19f7d582a4993a88639a0347a522); + res *= point + (0x70181ba88ba8d19c0220225ca0112845e23ed7609ffa4f2aea3cd40a40eef30); + res *= point + (0x481c8091e40139c67f7e69737f83a6c868e582526afd50b548bcfa5ec2e83f9); + res *= point + (0x1a758f2faad6702cac573f8ee11d83977ca75744f52d650a6dff79bd6c5caf3); + res *= point + (0x5a87e6f4731da56e8b078bdea4cc3f1fa2059943de95ba404ab38addce3d6db); + res *= point + (0x62a78aa9e73bc6da0a8536da8dd43311ccfb52829e89e9e94f3b413efb8ff93); + res *= point + (0x4cb8044c471e8cdc896ac725744d1a6942bcb26d50b3641e2a95f57b0e7dddf); + res *= point + (0x57d63baf011722f5c5a9c4c60899bd918c3287302c97e91fc6f9f8ba089cb97); + res *= point + (0x60de66fa4cc5d53fcd9d027cc06945a96de2f9b4f7d0c81c53a7567fde886dc); + res *= point + (0x794e6f83556e5ffee6d83daf40a067363b22e157cdd970366757d5d6a02dbc9); + res *= point + (0x1dcd10514fdded828639c9c21d0c8064647947e9ced01014ba8943b1d81bd12); + res *= point + (0x7cf749a9a9177ecfa46b901ce91a8ebe103f8920d83713df80efb7fc8868346); + res *= point + (0x1ecd644cdd8b92b3c042932407033c073c7da5f3a8726210a443f10af466ff5); + res *= point + (0x55b74b3af769611aa4c4fc71b1abed4396b218a9d5884844c937bc38b30bf8e); + res *= point + (0x4fc4e265c8471510fe6f0dc99d7be1108eab6200b0845dab07c5a126c79919b); + res *= point + (0x37edf969a82e9364a741858bfca74b30e86b1b69b4f33bb4a31666f4b2e7c10); + res *= point + (0x2a3ca69d295e5e750b4db8367227f9cb347b3693251ba9761a22d411de1c41c); + res *= point + (0x7e9f729b710f0fb173b36a6ee9611a9d309a9dc69a776c08dfe63c64c528a45); + res *= point + (0x1e2c3057002cdd12b80fb157887fc066b41436bbb71e328bf79ed2799947c49); + res *= point + (0x32124f76e477a3c6f5f4346f8abc19cd481b6f43088ccd1c3e8c634bd90cf); + res *= point + (0x5007d334256950aba31d4bedb5decc0ba6ab62a09c41baa8ab8d0eb4cdc170d); + res *= point + (0x3a06f0e39b3afd46934c41a79a317f220c6321664cbe236ffe1c191ee0b2c85); + res *= point + (0x18db208640b40e1acf69b256f0cf86c76f381ee79fa0bbea47fed2c95b5467c); + res *= point + (0xa0c5ba0b916bdf79b70c0d23013443f65bd087aaca62088b0d1f7009dd2d70); + res *= point + (0x5dd2afd2e8b09f86360d183e2700f71a4fb5e458c61823ece1a4e60200b82f3); + res *= point + (0x5b3102b46125dd26f3ae75c22cb8be10a3c98f269a2e91ce7d595d25c77e6aa); + res *= point + (0x2c489389378216a8f4a24999efae5d41af3bf123b10601d2efb419999f329e9); + res *= point + (0x28bb7956a08b64ed0ed089f0219b05b282eb25c107731d88867f7a78c3e387e); + res *= point + (0x450e38572d5b45eba95a4368d52056640cc18213b3065bb7b373a05561cd44f); + res *= point + (0x6931414c4f1e51dd287a8273a71ff946d1502d29539815c6652e6b71c95d013); + res *= point + (0x48fdfbe3980d1df8db00fd59b4b529abb0569c82a25c6b23186de11aee23a40); + res *= point + (0x680f30c7e737040028b548f49d2110d8889aa8dec6afe1de989e3f1f0c1c84b); + res *= point + (0x8955f2b26c2c91645402ea61e0b3bd091758afa740b4478e3fd2d97b7d5729); + res *= point + (0x62796f07255aabe16df1ca5ebe7f7be4eb1e9b688defe3044b1fb8eb56765a3); + res *= point + (0x29f85ec8df7c753f09bd36309e6d7d65f5d5c327d4c80ca33eca932da5eea0c); + res *= point + (0x40f21a24062575a80e5a6b6fa209f04178fce24323888c3fc9a083c6cfffe71); + res *= point + (0x29eeec3cf3ff9267792e170045fcbc1358ad5b9c28b97db6f4cb5a131dd1e57); + res *= point + (0x6d82291b429009057a7d89082c7c3ffeade1cbb4598b6bd1322c2e2d3c6819f); + res *= point + (0x78ffe33137f03476882656c458a984b78bfe509d0ed005657860541fdd16506); + res *= point + (0x13f6d5bd19a25ef48bb5a89c64894e9351380c31e98fcb8404c490081665acf); + res *= point + (0x36d9f7e5746b465ccd284ac21d5cec14258587d22189b4f85ea87f9b4d7c2ef); + res *= point + (0x54730884e1c5c7ff5bff889e8e5846f7e552f07beedb27035c0eaebfe676023); + res *= point + (0x7344cd22ecc8029fc605bc46e5f2f60c2910130290257210f9db71f26dfbdcf); + res *= point + (0x6a60ae65aaae41d02d6ad44360c269051a870c66a87e430eabd1c2c5dd8261f); + res *= point + (0x639a281c19217bb79dde39d86549ffeaa0694283fa876ab39fa6b663869ac9); + res *= point + (0x48a07a1f3adb4348f65ca07f7e1ad0b70a6024c4934df5724c35f1930befc90); + res *= point + (0x527d59fcf4e21663d7e921cf93b705e95fca41d9d2f88720800586e03bdc283); + res *= point + (0x1b07576ead1fa791e38995e423ee788587adb512c1bda749fc0869ac6b40c6b); + res *= point + (0x7b59c1f0252efd3b471c3047a2060ccb98cb86148c1b1893af4f86384821b04); + res *= point + (0x56e48833c5707aaa1e38a0d644765251c038ac3f89ed4d58fc3b24d03a83e77); + res *= point + (0x14d1da51db79b82ff5fc48e18ad84a98b1390d8e61e1580ef5c6100d49da80a); + res *= point + (0x6ade2f8ff114a1c0a0f108286f0f0e820073e7fee989a85fe11a97b972f077e); + res *= point + (0x20268b11ea1f54c737a14073b8bd83a6151aa30b0d51182446adc72aa2bef83); + res *= point + (0x937368e9df8289ef2d93e806914cc9ac730750d1ecc6ccf6c4aa6e6788d35c); + res *= point + (0x297d16ecee6310efbcf8a2946e1f03e23ce1eaf88fa6279dced371db9dbc299); + res *= point + (0x74d40da7c08b8fbd488137dcb60906f2004a26faf06e6ee4dbe1feceb94d98a); + res *= point + (0x5669aa7f25c6cefb4a3e1f5491dc50af7c44ca9f8405864906b353c4c3529b6); + res *= point + (0x4a5077d73c41429dcb66a5557cd392c5e8b64f4f93507e5e7b8f1cbe29a309a); + res *= point + (0x5974550418ba46ba346cb87069b6c17f9a6d57ce7554827c8191072b4ff8357); + res *= point + (0x6fb7a7f6c760b606b4f7cefa186540604099bd229b954096179a12ccd50e323); + res *= point + (0x4fe2139f7019584c7f395a18bfca2f5ea89a9300bf208b9dc73686c76e724d6); + res *= point + (0x4b45d3cd223171c9e2e8030a3983c2e4b6ed61a560db3a8da8a2bf1da05ae2a); + res *= point + (0x223dbf6f82e6f2b2dce8397a7a6d00c8fe38fdd8463fe7612c1a90bb76a16c9); + res *= point + (0x13e7cbf6809b1c282b1716db08a549825b9e1f24479288cf615c6557249f675); + res *= point + (0x13b2e8b26fec1c97c5fac659532830270b08cc6861df86b3f3b4894175551d9); + res *= point + (0x34a45f657061a57b808e337faed21f722e6298262a2df69d6bd34ecf2e29243); + res *= point + (0x372a448e249504e459982c7d114b3c79270419467208096cfa6a96f3e5de755); + res *= point + (0x5d62087a11238dba183191a31e686ffea34bd393310e7a2b11c75d63ec340); + res *= point + (0x5f25fb2b70ae9e334bd288d6768a7b3b6b2f4672cb671f6b0ebd781134609d3); + res *= point + (0x1025bf3b6ef4dc8e3637f4dd1cda0ea30ebba8c30ce5638b5f9b5291faa0036); + res *= point + (0x7d2b1bf76ecca560b7409dee16ead5b2b3691ff75ef8fe5a844306a7e29b252); + res *= point + (0x7cb9fc14dc4bbad427efdb3f5821fc9dd10fe8595577e39645ab9f62e6fa50); + res *= point + (0x6f61949d4cbc8298879b470d1fa9aec82261a8099c448dfa4379a597ab01d03); + res *= point + (0x336d1ccaccbef10084bc4a18f8c86f699642878a2b5d5af3a3fbe7a773e6904); + res *= point + (0x354e8d015485a06adadbf43a6bad63e9330c4070fbf2a704c166e1d278c8d4c); + res *= point + (0x45526e767c14a531fbc10f287b2a4203e18daad8a4883a1900a63dccc1a18f6); + res *= point + (0x688bfd9b23436077dd139ccf0a7286444429f3a2457ce7e2cc939be2172921e); + res *= point + (0x5dd26663ad2931b249bcf054211723be60b5b46de16a61928c0a9326874f3e0); + res *= point + (0xaeb2689fd195377c86c55bb52ba2ee27c7c5395d8163355a3c04135b43333a); + res *= point + (0x73ce15dc2409ac614aba33d14c4ad294a3a8136eec69e8b34b0b14b92eb240f); + res *= point + (0x73a3905fdf4a2f53d66ca4cb99ca729e776ce66d9a474fd71da35b3fa949d34); + res *= point + (0x1d60249bd6492637249efa94de232264fa23d62153d7a36e99aaede0be5d842); + res *= point + (0x728595451b9c3918b04e7ce1637804c1df21495ad8f188eb46a5f1796e2e3c1); + res *= point + (0x5dc73d8837d2fd0c754ecd371e94f0af344396efdb4337a8c7c2a0755838f46); + res *= point + (0x7dd917167308b602914680880c9c8c8519f34be930ccafbaca3d126a30c4a45); + res *= point + (0x1950cc259cc77027d5c86ea77f51a34cd30ad768676d77a0503f36f797eb4af); + res *= point + (0x4d5df514fa9a8bd7515039e59bea7a1a1381a76f475a7dea23549106a7df8e2); + res *= point + (0x1d74577e412af12fd886706cdce3c238f2761d096043a084c20d2bd087ad4e6); + res *= point + (0x7871f7217ff1c7b739678e28908c4222f492ebf866cbcc410148ad1d143de0f); + res *= point + (0x59a88072f92b384925c9091497269ba9f8226c24f740e928e410ae0bfb9350e); + res *= point + (0x19c90daa3645b62f461545c7c38ce5bf8b5cdad399f417e0abbaf2b2df0ca64); + res *= point + (0x53b86dc3cb8ef3d5920ea35c40e2d05496e45245eca4e0d058e2a0e2d583dfb); + res *= point + (0xe00c78bcfc271dcc6556cb1cf6501e16d20b188c7412681c0b2ae0f2cbae05); + res *= point + (0x36ac6cfd4f2ef6be5b1e83cf9e36e894b2575a8f4690c14484a17c222ec3c00); + res *= point + (0x32cad92232ea7886b829887e6ca4ae084800803277076107b1078feb66e95bf); + res *= point + (0x38269de0c80a2d8f4bef1d5e76805d1e412fef7b18886279e98c57a0fe64627); + res *= point + (0x217df85b26b6b3bfc67bec919866b6e146621c30685a31e8c93eaa27d5dbaf5); + res *= point + (0x4ee32b2ff29b0918618f173c4e5dc3b606a1ca2e0eb989257e0bf78dd2e9589); + res *= point + (0x2d51937feb119772693523625e23756d172e996d1cfb82a258580bd51c15e33); + res *= point + (0x7c2468c14a7ea994c89e2e4ddd6d2d624b67a96e7ccec4f27a5e0122531291c); + res *= point + (0x602aca232b11ad63241b5f401c368acb1e9cfd4e5fc8ae699491d9c51b4db18); + res *= point + (0x39c92f0c55d99aa6b082d21129a9402e6b0fe38a639a8140d76ebee9dc45877); + res *= point + (0x4fff8b45f7ede0580424c4e2c75213c4c42ec6c68266c8d5d750a2863bd474a); + res *= point + (0x3ba2c93d59d6a361b9ac28d93e54d775b040bd7fca9ac72339ea4388c533dda); + res *= point + (0x6d567c1dbb663fb2fd92140cf66ea33a19cda580d18c10fe56a62e5bd3f47b1); + res *= point + (0x2781266a2070c9d3f045010a32c98ce3e0765446e3ee20eacd73a0dc0c7c2c2); + res *= point + (0x7dcfd5001e21e030b006d54c7fe0f7ca97a2c18d4e00ba92c005705a4f0563d); + res *= point + (0x2fe4c112d7bfd4ad5f81ecdc4b30cf73aa51df4e4ba6d255a0e3eee283aff46); + res *= point + (0x2433d40f2b8f9461b5368cb396f7604999a735414d3537ed6f1451f1fe93cb3); + res *= point + (0x72f959288185bd36ca4e23472ed7a2577f8e5f0ef0c0d5df6f63e60f40ba307); + res *= point + (0x4c5592288cc342232d76c80e858c08ecbfde64b747637ccc9a2734e90f85264); + res *= point + (0x48ed57151b6dc68b039dc327f79bc2c26db62ff957809c5538360facc04d9c3); + res *= point + (0x5ebd9b268cc66bb85a5e67a6b9d5fdbeba8b3672491068ef43b688a3a043a33); + res *= point + (0xdf6c1013f3076e6044f0a7032e0bf80833f3c7d9eb0c3eb1f3c2a37314d19a); + res *= point + (0x5f0cb66613216a1339c1cd15239b7f03c1d4b9098a931f65ae50b877f861880); + res *= point + (0x5d5fbd560f7bf1e97190f888fa43b32db1e8070f046d6016b536b94d1473a57); + res *= point + (0x33381003a653f0327cbdd8a11252ffe714e1061ee214329cb99e667c835af97); + res *= point + (0x7b86849a979796096f7d7b46eebaf00913a082c638c5b2bfdedbcd78c480272); + res *= point + (0x5f27bcacc10845ad41cb26244112faa8b91d46d97024445f50ced796ac5a93e); + res *= point + (0x31cdca47c96b32e99077a96aa5cd73ec9c4da04212667805c82dff3e498f4ed); + res *= point + (0x66a032c182ae70dd4487897d0c79dd860a25d21c61e3aeef8b9fa45349dee89); + res *= point + (0x148523eabde5554538a1114351f3d8730d4a4d003311c7b57ce9e709afeeca5); + res *= point + (0x62ea67803c421a4bbdc672d556bca219fd24e7145cb3e9113a625eeb4459254); + res *= point + (0x2c2c70075ac99cfe68a7354ed29842c5207bbdbd09dbbd225ea93d0c07fd9f6); + res *= point + (0x48b0cc6241c99407bb346db57db9cf82b2e66d1fcc1d756889a4f4b4bb8b396); + res *= point + (0x506f990d7037060dea08ed53c5b17483ca8a7c58f94ba5e64fae258be4c78ed); + res *= point + (0x777be5852ea7798899d4750e9decd1430bdad6a8b0d1827a7a89ce6f1afd89a); + res *= point + (0x689fb22cd95d6f1868a4e3cd6ef1bba9f974931f76153e73038ff5ae7d09018); + res *= point + (0x560fef0ed77bc94e16b9d9a21bec0ceadf81b26fe683b9c74b31e2d72a4c92e); + res *= point + (0x28c74f03f409c942d16a773fde01b3f0bec544b42c1d46944db6253561e1ac2); + res *= point + (0x4d62e1ef04cb039a58dd8cb8c37dceb78b10fd84bbec6302c964b899a957d02); + res *= point + (0x44094c265809e3d5765071826547999dce8ba7058a7c1b1301294d8291949c); + res *= point + (0x4e0f90743d3df3d3c4aeb80e7f6db457620430ff28475c6194c757f81927dc5); + res *= point + (0x2cde734d2a82619ba69ca4f5ca5035f699a1e34b47560d761780546c9b04d44); + res *= point + (0xf09069dc6a2745587b447ae03ebd6524aa9757f1090a92dc5e7ce8db848195); + res *= point + (0x5522f48902001bf41de34be900783ac957fd867cca0f35666ca491ea89d8fb3); + res *= point + (0x5b4be8af83915fd955ba32de729f6f2aef6c76501d82ee325d72d620bce8b7b); + res *= point + (0x78e74ffaf944c363f3fc42cedaea8a9a450ebaac98bf1327590a11e064bd76a); + res *= point + (0x6ade7c482d201c23145e3890086b22ab0d43495f5c83b1672316c10ca52af0b); + res *= point + (0x79c066efe4c22c6e9e097e84401e183d3c45c645d986ed640a8faf8fd4dd096); + res *= point + (0x21d59ca7451d83d78ab4d9d17a662367ac84b555866ae92d036d71de22872bf); + res *= point + (0x6d100d3db14939bb442e5f5ce6a05939f201837007331536440a57c2bf2b609); + res *= point + (0x7e5bc177982061f124cbe521c713c24438aa021fe6928d82452e44f6cdcd631); + res *= point + (0x179e4b1e4817460085d47376a1971fdcb0287408cc7d11fb62cc3785772249c); + res *= point + (0x2a7cd1fb12f896bff4d3db49ee74a51e970e3e386c2c8e7622412a6156a300d); + res *= point + (0x3c5581c15733dcc4d548aa0a6e648e075e9be412680a76a556f91ae5f01e44e); + res *= point + (0x4a4eb8f57c99e931a666de76c20173adcde82ff59fd8ecaf8b8c05e29b63fc9); + res *= point + (0x58fa31f9a4a7e8b238898eb1296ec55e3e2000a48a2edc8e65d260d31bfd7bf); + res *= point + (0x2c37f85ac7b1aab52ce3d28bfc65c65b7d4ffd000757c07fc493d183b7bb582); + res *= point + (0x461b788a24347588e4f8d4f2d66640f31d6b580223a21919ccef9480987db1f); + res *= point + (0x47c3222376f8f18dc6e82eebaab03fcf4c425acd901a7bf9841a3aba54b82a6); + res *= point + (0xbece573771924d045b75bb992a87b26ab067a0f2dba4d1a9efbe5029963533); + res *= point + (0x67c2a0e19b59921666716fe2b3f9c7f59c4da17d993956eb87eece7ef542269); + res *= point + (0x8940bc9dc45fd06ce4046337963c849324bbe5f82632b94972c0ccb205480d); + res *= point + (0x38bff358ccfd92418537a9b9858df499d2c44404c1886b109edb14c897e74fa); + res *= point + (0x533a5a2ebd098297604e96118f2007ddd12af50edd525e9e5a0b154e620b2e5); + res *= point + (0x312411292b7fe7eee015fcfaab65b611bc2b9f9498489fc3c1452862902bbf); + res +} + +// Evaluates a periodic column at a point. +// A periodic column of N values yields these values on the subgroup of size N. +// To simulate a periodic column with 2**k repetitions, one should evaluate at point**(2**k) +// instead. +fn eval_pedersen_y(point: felt252) -> felt252 { + let mut res = 0; + res *= point + (0x62b07622f501888a668440d9b856be4b0c3bf12a401fc2bebaeab4a7e1684ad); + res *= point + (0x75a127d817aee244517479bab5c4bfc2a0035d43d673badaf64d8adf94353bd); + res *= point + (0x14f3359ce0d2891d1bc2b6f4d2d6dd71fe22925b8a09f66147db095a9d4983); + res *= point + (0x2d6129632b4fc43e4142abf55fe2d1f3e79dfa01c73d8fb56a465dbd07a9682); + res *= point + (0x5115ade709c058be5dc6f406794062642086e431bab03c9a86d53c79aa83db4); + res *= point + (0x29f6aa5fc92eab8b8b9871c8449c1f617b808ea9860717f3e5e1678672ec565); + res *= point + (0x7e08f9d222cc0764fb5ca69e51ad4cdb7f1b612058568a142bc7a4cdd0e39c4); + res *= point + (0x54c5dff0aed23c07edcd958ee3690e617011b87a5fec541725237d4ebf34382); + res *= point + (0x2b7d501bedc4e7c604b0e55dd2d8166fa39a541efc24d81d8464fabfef3fa37); + res *= point + (0x68e1d50b4d0570e357eac7bc742ec26dac1edc5b179989c7ae8d31791639103); + res *= point + (0x707c572424682b685a1ba90dfd7e56f86254862d86e20b5a2d3ca85fe0017ad); + res *= point + (0x2cd9a093ece61e554b2bdde3ec474900e4412775ad25456e5be6e11df7b9fff); + res *= point + (0x7492aa940f34a027f8fb3700f29cf628c1d05d1675cb7865509f20617a90b2f); + res *= point + (0x55e928ba557ed7fe0ecde6d1fbb83d112e6b06a087b4013b9c425fa36eb0415); + res *= point + (0x3cdb28a913a41d597915de055aecc59f2b13079d3d8b33ab0a075eeddb1bf8e); + res *= point + (0xfd48fb35400aaaf57d130b6143b241db8af174cada72ede8f2fac4ec6688d2); + res *= point + (0x133b6505a6afd2e5fada0e53ea51c012e4935ea6d2d02caaa15ffc50a45079b); + res *= point + (0x2d2d27711772cafff2cad828dd78d8b213e317e8939cf79164ae64dea577d61); + res *= point + (0x60ac57e328ff6938a17d43e6137a55399b95459be60fe980ed8960edaeee10d); + res *= point + (0x7b056cb6f172b25e3555d6b1422ff769fd4c07258fa16b03609f0e374012ed4); + res *= point + (0xd21afb1901f1b3ad66587a7fb97ee06662edc3bc8c8d32b48625a135ba23a9); + res *= point + (0x7784c2e140072fd26e95911df38f9a337107750a72b9ce05a21a0f781b92dba); + res *= point + (0x7c1667b8d44d288c4f5150d01c5206d4d5868497630745b6916466c8a5b1228); + res *= point + (0x491c2243a95c44528b86167a4418ff9d93a04bde8dd7a5d2b19ea579d295312); + res *= point + (0x6aebd7a9279eba43cb1c0b14bb723dde464a86cac92518ca16ae27a8684d9cf); + res *= point + (0x709be747b0a69a9523680ff69e6bfea4637bd570ce5c45256b39ff695557da6); + res *= point + (0x47275cd67ff3b7637ed55ced299a6142a821ab466a897f1eecfc8bca557269); + res *= point + (0x58ccfd44df4e339c65e1423eaad47210f2e16aa6530d3d51f38b70e5eb3a623); + res *= point + (0x28218a1bc7586b71ec1989082b8f7ab0efba14569c6f6e5d7aeee1964ab6d70); + res *= point + (0x660bd8049bd301d093aab9ae530bedc37467d4ff0a12c89d689d61ef9b9546a); + res *= point + (0x4dd38543d129d0a71b1836c6e2eae47fde5d572e32ee9a5791f7ee823eab4db); + res *= point + (0x8509234000e130c8828328ae4997d5116117716cca9490e6e63f30b7df699); + res *= point + (0x62ad4d764ed0072a7649425270e2b210421c77d3ce98e2587ea5440a591ecc0); + res *= point + (0x66c5222dc133e37dfa0566c49d107852d978eb7454489d3b2ada8de022125d8); + res *= point + (0xe4d1f1f1f9b379bea473f76bc8f3c4d530335e2d6bd782b42324872767b628); + res *= point + (0x6ac2f92bc4c04fd50ebd3e336b53b866e790ace39838aa96a4b791011455b29); + res *= point + (0x59d753a23735a336c50466f5ccaab3671230fbdaf55101530e5f562a5efcaf5); + res *= point + (0x166b26359c51d067955874f5612eb70806d7b8d5de4d8e0a75e0d57b39b1846); + res *= point + (0x2dd27ce7910e44ee00ec3335bd79429846a70d92d482adf81b36a9ff1aaa30a); + res *= point + (0x45970c86c25bc9a68f2e2a34969faa2134c95b19230fcfe7436c98f537539eb); + res *= point + (0x539cd2c1a28df263709cf0eadef73a600f563ab3d82c27692b1424814cc3e15); + res *= point + (0x31eb3b57e6844e3efc1e3975ea393476d8aace5f43ca62b09314c90b8ae9688); + res *= point + (0x47359c8dd2b86e4f634a9a50950abde25942877bc5db93d62bf43d2886692e4); + res *= point + (0x2d8ae7b28c8c3acc8bef3d4c2a9f5ef1323748de693a9a1ad3ff8601116b165); + res *= point + (0x4538fc863186b4babe3b424b4111251bb1e20ba5516be54160cd560ec0d5a3); + res *= point + (0x559548517b1025ad61020be3e252b6ddbf1d5d53043231f8850c0da52b8268a); + res *= point + (0x3132d42e4a928c08a972e17b2c3b500dbcadbe6190b2e7f5b58300a0c8a38c6); + res *= point + (0x5b02adb78afd4e219642a1fc38b2ef9f63926841ccfda072ac17326d3d50f3c); + res *= point + (0x75971517855ffbc9657dab30657ed1e3797307bbec1ffe136cb0d8a64ed6eea); + res *= point + (0x174a4710688db61da7559255caebf641a268b4df53d45de5e8156d36b4b2ab0); + res *= point + (0x295fb60eec46a40a33b1a9532427b42e224c0ac6c50e3c1c5d17c2c16651a25); + res *= point + (0x2037a7d08a1c4fa4d5d4f53436a252302840007c09163026637e9cdddc958f0); + res *= point + (0x7e9e1c3d4bd3231686c235a495f737a9ec3d633331a95d85e17e90f99a08af5); + res *= point + (0x218da336adf8608530fdf8320c4edc00631d36c8726430732038a369548cf56); + res *= point + (0x78c7b0512cae47833eb6bf01c1075aafca19eef9b32e37f4f9a9eff315637c7); + res *= point + (0x628226c46fe0bfa8aa36074ed0785cb16461ee2945ecee9deaa6399bba2742c); + res *= point + (0x2eb6bd70a00ec26418d347df1a444f7ba0972416103f00c771e0f3d50bd8e5); + res *= point + (0xdf82eebd6cde9b50958606c6ff83c855c43ce9613fec366c7792cb456ea913); + res *= point + (0x4221572cf29651f508bab9eb82545b17cf6f9efd0416b65262e5491ad408e39); + res *= point + (0x1d5fc46deed0eb9b56cba1d2bf8075227504aaf6ab1330b346cc3cb84a07cc8); + res *= point + (0x55ee57d4096ccf0260baa2a1a2639978d965a786e4fc917cb2426f8a99591d2); + res *= point + (0x21706619a453a544bee0ccaceda9fe69f860c894b36bc9cb7ea4455dd88a9ca); + res *= point + (0x76ea16625d0cf0c04f096ac7d6eacafd00809ef1d1a3cf5e37dc2a13a02d303); + res *= point + (0x6d0d885e8d2530c7a324f7b2ef47db35aa8162289a4420a54f13a82b871d850); + res *= point + (0x471bb97187c83c0e7b51ab70022147e8d8ebe25d4081907e7d1bee8d6c6581f); + res *= point + (0x12b9157240a237f319beefb6019bf0de1897b9e2d8e5536e3a21d8f9fd689e7); + res *= point + (0x2ef7f1dfebad70ef549da1a143c838cea27749807efcb1a0a29cfab16420928); + res *= point + (0x519de0df91b17442a8f60b512297d69a1b516f70f67d76eb9c287f06e37c55c); + res *= point + (0x2a45de0b79a4e9c53d47f6126d35b1d050775d5fb17f3c3dc22c7b6476608c0); + res *= point + (0x27e3cfc87448bc0392a0d6c1b1aa06626636fc703bbcf3717fbe6f0759c4855); + res *= point + (0x77a45066995089dbd4072d6817397ce0c7e92b53d19338e9bd7549e954bd961); + res *= point + (0x3139ae970d95891aa70cbbf6f172223e07eb521a5149b7e0c9202793f6dbdb); + res *= point + (0x25dd21ff92e6f1075df6b5ddb2b774ff963b1b84a985261b1e94ca9eedaa49d); + res *= point + (0x13eb9f5362c087af5ee758bf0b589c0e34af337b3c06c788573534e96de30b7); + res *= point + (0x6a39a27be962632e0bfb245f65a4d70912d1572e39003d63def5f45bbcc8f7); + res *= point + (0x2c11fa8c0ba68518942f1c686dafd32aa26545886d28cdedae00071360df674); + res *= point + (0x7ce49a9b8d374e1174ae6ccea7cae8d743404552253f7ec854317722a5efffe); + res *= point + (0x6bf518769635f9fa39c1258844d4f62e5fc00b70792944da0a939990492313b); + res *= point + (0x6123efb57144c151864b4f717a44cecc667fb2ebc47bf24bda4f7d0ef8f550f); + res *= point + (0x2c29d0056cfe7325567a9f2d09d917b37a45aa3cefe20b78c4bda2942af59bd); + res *= point + (0x76914b565dab13e76053b7a74c24c005b0930011e48ab26db44b6b49a1e7ae5); + res *= point + (0x648c35904fdb8bbf9c0bc9288319c248e17974fbb6616a70acdac004878bb9); + res *= point + (0x1cc7ec07c4e1e6626b5263044071687d0ad34ad4d08996a213380e9b728585b); + res *= point + (0x154a5ad294d41caedd8d927eac226dea1e2b78f6ed0a6901a00e45ae0ad78f6); + res *= point + (0xbd5fd7dcc1ce2bcd7f7415a22115f0c846d16ac7458e6c531e7e44dc664962); + res *= point + (0x2b2b08bfc4c3d5941538b2eda43b3cd009656cf83b6b23be56b3041df3dbb0b); + res *= point + (0x5e48cfc304417473eb4e587942a76921fb007d8b11ce648d36828e8cbb5d595); + res *= point + (0x79c11c262fc2efc9aceafe4a5886713151352e60c4db45826e0e343cc5919a9); + res *= point + (0xe2acacfba8f832e4e3cffb6ecf4675df678403610fe91363172229444ac0c0); + res *= point + (0x6dbd918c7623bb07b05ca515146ddd7193373250e0836062fd1c430e2b7894a); + res *= point + (0x61b210c04a0899fe2a3dc53348507d6f53d4cd3831644e4630eb40564ee5b47); + res *= point + (0x1e3816f2a6a4900b65d140d144225a8a81cb3ea22f56de3cbcfe3944fc0e898); + res *= point + (0x3c99839cb11fecd878ab9efd1d2ed2a718f6e0df4caac1a070de06ddf1a6091); + res *= point + (0x567205f3e5ec69ce7962918c41ed0309c3ddfd85fc92702ce1c207b282f17c2); + res *= point + (0x10382fdec78a18047041629179e18ec7dd067bed125bf5fe83f13d637a8ff67); + res *= point + (0x43aeb91e6f453d372353d9814a85c21617e6c934c694a0b06100e1e9aec4087); + res *= point + (0x2b6a2e9d453e19e3d766f24cb7c6753f84adca0f75f7a871092688bb5ba0d37); + res *= point + (0x1f3e3e61713ab64544b28dfcaf4da25b64e625048ca55cc783dff614f5796d0); + res *= point + (0x364cf25e248a3f2fc2106025945389328c0ef37848a59ff2afdc685c0854822); + res *= point + (0xf9762bf5620ec90d711f12cbe600f29906fcdcdea4f17cf51ffad2e07887e2); + res *= point + (0x78e4cf312ec50466bfea965b655e9514d9d69bf0bae566fc88187fe730f70); + res *= point + (0x8981cc99962f20f8814162568d9d7edb7fcc637fc6907a98b1d1eece9811c6); + res *= point + (0x4e28bfd662fc5e09399fc49a49a622a7e845631244b9472df8c91c4a703321a); + res *= point + (0x3085800be446839854dfb7bd9ea67ff139267fb5268faaf153db26b00368630); + res *= point + (0x787a6c80d5a23f91cb91d2508633cce6125da76e797ed460256933a4e6a24b7); + res *= point + (0x5ad768a2e70b4018e505bb5f6f44d249d9f5ba5f126106cde9be7726cf5c0a3); + res *= point + (0x58afefb8e3180356e33794e20db869aba4bd4e5dfc795f8089d6f123025179b); + res *= point + (0x4f62f4d968964e4908d16fb9412f8d10eb82e14e83f3e094a02470f27eae006); + res *= point + (0x5ffa0d51bff335ad53cfe99165aa64f5ac1b01c360bd0101856537fb03da5ed); + res *= point + (0x43fa3aa05db6331941265719fc1ee057d9f3dc81704f81c2ce7faece0fe86c6); + res *= point + (0x1e836012f5509ea2f3dfdd474e9e4a96f6924e6619924ee4c6870a5294e26a9); + res *= point + (0x41052d90f803f015bee5bd1a5f6e2f78f30439ecbe39861cdaebaa8f7c56371); + res *= point + (0x16f6ec82023f48ea80196121afab584b9bce7f01e9515d0a3b489d68df3e2a9); + res *= point + (0x4b7236fb7f8b72b2d369effbee5b4bebe7d2205ed72f9831b41c711680cbbf2); + res *= point + (0x6620ec871e8a2c03933d0621b13e7f357b7349ea16bb549e7e15e2652692252); + res *= point + (0x5b553a6606a3f01d862af22a3309a6df0aadec753fd1e0321b0eb08504c1f12); + res *= point + (0x17a1bf17777a3b56a76df412810d05c9e222027aca604791694d3b020ea40cc); + res *= point + (0x64fecb621f4dc18fa1b66152f28bdd15b7b12d495c496e77016bf3b979e4b1b); + res *= point + (0x7e31ce22d2a3d776ad90e008ce82c594dab9ff2c42708f4f0676000cd86891a); + res *= point + (0x43530eaa364a9df353dcfc154bae168e0fa9b51a3362c6cb351d47bb7f6b829); + res *= point + (0x35fea15e2101714f172da73da6ddc2077ebd42ada067e7879bba8c2ee1d9db1); + res *= point + (0x4509575b94136d744c8679c3028b0db514688db5338c4bcc9f50ccd7d15c95f); + res *= point + (0xf8bd8807280892ca46c092b74f845d90f3a6b61b197a0594fa30686ca41a5f); + res *= point + (0x51443fc9bbe11d787df4afc59f4366629cfb3a14c80cda1caa1ce6107fd063f); + res *= point + (0x22cf3cd9fc0103158f7de369046ac0cff77c44c3f9c6ca942616fe7d59d6231); + res *= point + (0x14714592154025f15704e279d2db4c70f545137269ccbd82c11fba275bacc85); + res *= point + (0x1d44a3f67a1142e7922f4329f775fec5f8bd2d32ef8ab41a00821e76fbaa89f); + res *= point + (0x2d9f309e84716b322c26aa86a3fe3cb6ff230e0968dfc58b869268c751e510d); + res *= point + (0x64ff5a81d9e22197bb59e8cb340a0f44e22e226fed168f8b125d850bd727b7b); + res *= point + (0x2cf1eefdbf254a549ddf4069288ea075d9aae074aac7853005b57c37c2039e5); + res *= point + (0x20d846afc1a11dae8646d542770f294b9c9f21f1196fba567f2f74d058ebc25); + res *= point + (0x4ce9244cd3966ce1a6fd7f8b85fb1c8751e35aa53032f8063535665ac3a69f6); + res *= point + (0x203ddf8cbfae2898d2d2f183cd0efd1c3f7db1b84b8e96e38f2b87b4bdad1bb); + res *= point + (0x37b40695420e59161b338e413a72daa6909f0e4f6f85426f8eeb6bd0dc3a1b5); + res *= point + (0x8554877281326c1c7e1f3a2f5e81341554ecea862c2677fa67ab2f88b3b03f); + res *= point + (0x619cb05e71db22ca1ef274bd0a7cdaf4fb79b3015b96f44814b490f048d2af0); + res *= point + (0x66af1f51f840c438b502c2a5ab689f9b38c2c96df36988710951bf185cb8501); + res *= point + (0x5486125e0ed23fdc42a4f8c96cb08d934b6f3b429c4af5f8396618e978e9811); + res *= point + (0x41d785e118be2d27a159ed5216de66a84873e1f62088726d9607c6443a14090); + res *= point + (0xa6117e45c1c561307d63895569d34fd7e3f2b2ea088dec37dc3a5527deffd4); + res *= point + (0x3bfe2f1e8df44829fa27a78c46c223c7e64bda85be60d8a3a5d0e7d36c20e29); + res *= point + (0x3daea06a4a96480c4f7fff1082d95836964b63c14281ef942fa9a9890d8754c); + res *= point + (0x3678ebeaffc3e64d76141f41be973ff36e8398a6aa0385eddaa0c4183e3646); + res *= point + (0x5cc1da57cf1059231e195a26b1323599c95f98e4b302d6e6f4bd41180b56d35); + res *= point + (0x4f4cd7f9fd5b694cc5ea6154d0738cdbac3978ce74a7314bcafea3dbc1da61d); + res *= point + (0x77bdb42e999e93273fa3cbb7ae7160522231680eccc4d38c1b8a83d2a0420a7); + res *= point + (0x4e1cdd107e3116b4ff22720938a201eed2ea0b499bfde301562f5e39a42b066); + res *= point + (0x513bd3eda9403f4167249972ce4947f3ac9e9da03a7b9ef557a65645b9616be); + res *= point + (0x23d7ed01587af3b9aefeae8a627c6401d36245cafa9367631036d2bd7c47e26); + res *= point + (0x1ec8c3c39ec4705944ffa8b3b9b61f73c9ad759cb79a107dd93a125685f5119); + res *= point + (0x4d0db05514a8c0f152a8664579c004fb738cd3790214984bc3f21f31d494361); + res *= point + (0x2bc791bd7e68342116218ed9bb657b8b54e550022e39af11ce55b29ae49218b); + res *= point + (0x7ea13011e0dce5c917be4cd36c8931f5969852109a16d7c5142e8fb3c8b7650); + res *= point + (0x11a9029a5c07557ec347592ba7181acafbaf0f0c5c9e81d7e995a4de57fe566); + res *= point + (0x359506efbff0e2b81d91cd6a5f808a6c65255e1bf06cc03dbaba94758b3acfd); + res *= point + (0x491899cb7600abb42ac8cd91f2c775ec410469573f57c1030ed1582327eedb8); + res *= point + (0x7a42c4e98f014e50dba6b25fc32401b7695fadb7bf271fe0a763712ee545c2); + res *= point + (0x2f7d26f183c54146bd83514f5459bfd95ac635649d74225c2168a8e7baec082); + res *= point + (0x3ab952be650de0c679ddc0a35bac2907a6e58303059d4edb914e74c67d05226); + res *= point + (0x2b7f9df93ba787a9a5a7a0a3b5daba02e2ce65df16ada37575735697eda6c1d); + res *= point + (0xb04ac19a9f1483b8ee3b763be73814c9621fb3d23e6d874d9093d999d3d4eb); + res *= point + (0x4f4df07e55d3ebf0ed955bd9f7c34de001f09a92c1ead17b0c1a485d48a4329); + res *= point + (0x1522043741ba933948d7298114b71322258a3d4e7cf2496590c35683dbe2a7c); + res *= point + (0xb489643a1aa2c181b4739d45582e2576a6f9bd51c81d300ebdc3a58b79bb2); + res *= point + (0x4db70c63a1dac4e5ddde15e3626d009683aa8ea14face2c3fdb6ec97c8a86a); + res *= point + (0x309bca858a0f9fc5a468a57981c9c6b7c79636b1f31284938d1c6a21f006a33); + res *= point + (0x625a1fce22a9fb7717107b137a0f5ea4ca059008f5cc6fdfb5cb5bb1734bd17); + res *= point + (0x6ae2e00f7827692b0d20f483d3c71594f61d50846b52abfee39f6697513c0d0); + res *= point + (0x4b5acbaa0f7e360885677439654649256829cdd6d4a6c7ffa904a0683fb5fe7); + res *= point + (0x66a63b8ed2255586855fb30333ce0e2ff4eb2b4cd5d2125d8d20cd3fcfc1d04); + res *= point + (0x55351e9d60f58241736330de978242e4e40c4209a7879d7ae3823c148abd82a); + res *= point + (0x588747248358bf8bdbd990996cb43468c89909cad0f8230cc939538b9b331df); + res *= point + (0x67801dffe217a1a64e0b12f405157af52025266fcc391fddaebf3b6c7ab79a9); + res *= point + (0x411556b9c89186a2f9f79e55d045295790b28af97fab64e77777e3828532be5); + res *= point + (0x5c01501e6a113ccca7cc9c723b1fad6ba60ec5b0a85b7d09c72120d3f733bd5); + res *= point + (0x5b0d578cb7aa59ba02b0bb894848b745440c0cf562c2e635312c9bfc305e169); + res *= point + (0x3013a9c6094ab0086b1397621f93ac07bf45574ea26b09d3e4587afffe995ca); + res *= point + (0x7d9c679179dfab605ca04e1993b37ddff490c440665005698a47c442a1cc10c); + res *= point + (0x4f6e24500755d20ec5f28480a41a0cf23baa1aa24202382e9f4ec8ec6d7596); + res *= point + (0x4e0a6e0c26f85c74373782bd2924f3bc0f6b4a2914c4f7f8850a79eab580566); + res *= point + (0x6caac68bec6ce4eff4f74c1f33dbc027165cc02cec8f69e9470ff99c0b132c3); + res *= point + (0x1c867fa9ae031469be012c4f201ed3ad56573a22891351012ad1f7d300361f0); + res *= point + (0x1761abb092f6c4e3eda770480fb4ab095e786bc3f1b1f960bc4c95232308b3a); + res *= point + (0x4a35c4582c91999a39b553248bf2a39ae5825204085a9e98bd6ddab3bfcc0a4); + res *= point + (0x6a4efc048a81614dede6c4f6181253e84f20d4a4f95f973147ee3fcd72077fa); + res *= point + (0x65c14f7de75359a40c5f244f78b2920b61087fdbbf59aa507644d94f5bd210); + res *= point + (0x9be8b219ca1684dfbef720a3e9f034b319e2d233aed85063924fc60aedf20e); + res *= point + (0x7352e8793ed3f6283e492544b2944d6fea715980d8884f6821574d36868b0c7); + res *= point + (0x65c04013accf25a2cd1d9eb98689d71694ffb20dced009df5b9af167602b4c2); + res *= point + (0x679bf3101f8b2112eefab47d7372f0297507511c7cceb4478f2baf0541740f5); + res *= point + (0x162e6e8431b7280f8401ca08922c5452c7237132efe3a481a71b5c97183e9d0); + res *= point + (0xd9da926adbb5ffa493c54223f97fa1b0d141129d8736bc4f5768426c7e82a2); + res *= point + (0x711628cee8d673863e18f058cf82551ca8351486b9b210873b4e18447e11408); + res *= point + (0x6f6131c193cd7b3fdb4d0848df70474ba9e80529097311cd7c13e322205a1c0); + res *= point + (0x2512f776d1b3d212be7c2adce1cfa083d1b2b9af1c6f3cc424b266bfa19aa06); + res *= point + (0x400330fb079fb4cc8671ea9a996de8f5442f20b9b9a3bc9df8b81e01506c5ad); + res *= point + (0x40cfb729788e16fa80b7d937f0088157d18ff2cf7c79b748d0e150c896d348f); + res *= point + (0x59786091e2d824242c7aa5dde34ffbac99f6a9a1aa5ecc8a395aa13e8aa55af); + res *= point + (0x4adf53e64235d5327822ee3e584674af053e496c5d92a6c8c43e1e8e7d327fb); + res *= point + (0xfe9d827d7e6387c7228d92f78574add4ceddddac1fbe71dec1258220c08402); + res *= point + (0x37f1342e071f8a087c1405692443305d28d4c11b84d92bd7dedc563fc3ad329); + res *= point + (0x74a39339d1d708a9ea407f03d8b0e5ab103c3251596258b78be1bd97ad06915); + res *= point + (0x152c16cce8c1c782287b8908a790014fe3c51c57cefaef63e2c8dae5a7a5daa); + res *= point + (0x5b32dadeb15d554f39f227de4ad20600eea4b763fa4c90ffa1a41812ae43479); + res *= point + (0x3b4b0f9b88e16446a2de79c1d8c34865d5d6e581f08bbbc652ce67d8ac1d952); + res *= point + (0x44041800e20fa7a15dd9274ea8283b09c30a0d900d9c165217004e669b39d99); + res *= point + (0x5609324fa7ef5213591c8d36c59dd42df8f5f26f84468bb84f843707a5c9c48); + res *= point + (0x6235547369b594514d2fa1ca9b06fd25f9d2764fe8b099c7d9671f542a01d46); + res *= point + (0x614509129cebd380f416c4c9c7127ee7b53d878860905f047ad722a82147236); + res *= point + (0x4f847058896f8e2727ef3b4577e62d5f6a729696b8705fe217b97c73fd1afee); + res *= point + (0xfee20b19c4437f06eeffccb05b88c4e236d18f8e3518ba124ab4eec844c496); + res *= point + (0x5897638208b8e9509d1128c29af87cf30c57942d47016819435b373c0a309d7); + res *= point + (0x1fb19890707fa2e617de7dcea9ad35ce9960009f1e38aa2629c66fa5b8d5d19); + res *= point + (0x45fb29b3ac673e9f525332c8bad73d76521985406fc09398078b30339c857b5); + res *= point + (0x528d041bf152aa3a0205430412a196619b68c81d7a706fea0fc090e0cc6a105); + res *= point + (0x1e149d42cd477212ab7f01fe40f76858f09ce2bdfc397df635ed8a453714e7e); + res *= point + (0x75f781602ada44803c0ca4bc8c1bd5064700762d18c309a2b9059dcd8c3dcca); + res *= point + (0x1571843ced13a8d342b63c63abc4b83d357eb286af04380edd1eaefcef3f1f8); + res *= point + (0x304103a8d35f43cf87d50682e86e473fffd71d13e0c783e596a59a62b06402d); + res *= point + (0x2849ac77a2f5398eef51aeb8312dcef8b347b690728d4eb835bf4670301e6e7); + res *= point + (0x52a36a173c7ebc96cfc55bda4bbc73bc349657d39ebe096725e9cc4bff01def); + res *= point + (0x43e371660fff35e52cd5dc08c9c347d8f7c64a116375d0e6e3ad3512d85a99a); + res *= point + (0x76594f29261e2aa9cf4a90b58b0f79c2aaa99d63c4ff64b4806cb8cfb0df316); + res *= point + (0x4cbae4979c7a1313c2d0f68b21f5734ec83f9e1a88c78b3976a6ef84a1b6dbd); + res *= point + (0x76702a08064b5768ae2979aca07322782191172276f1bcfbc14cbaa3e758dc); + res *= point + (0x64f8c462b308a1337bca235add2482fdc3607507b2c9c0f91b9187f5676303); + res *= point + (0x2ef5951aae064a7357b1e4ed49f05f17f778f2e8735f8d17b5cfb82faf3b848); + res *= point + (0x66e2651e6f5758c334d1c1451d563b2df07b424b5d0125c739ada959479890e); + res *= point + (0xb3dd17f46d6b12bf4e5db184d6962c156bef94f9f73861e34d88503fbc517a); + res *= point + (0x19412ccd078bf5665579cbd16035a251e08f40722eca4452eedb31732488468); + res *= point + (0x719df2a50d9c3f2eb3f0336665f2980e432191e21fc49f488854b8352fd94fe); + res *= point + (0x459f095ba3b70f76e493c6afe2d4b6eebd21343f74bfe3390868612fc250fdc); + res *= point + (0xdef6a0b2b71d97a59c674c052fe23f7d000a334e180b0793b6974fe29a64c3); + res *= point + (0x74e503d57e49daf6939077c0b4a4d68e66bc2425ce53b01b48f146295476401); + res *= point + (0xd49f196e60ebea0eb13d85f05cffedff32477e83129bad30bd9dd555755429); + res *= point + (0x298215f335fb63a11d31958d950d95c909bb94e144c113cc4ecc08488469097); + res *= point + (0x6232d26f420f9b4f119e64762927b5e8a21192575b200081b0545ad4e9a2c25); + res *= point + (0x2b51d7f94ec71f3a8e3e20d766a4a7f13d08d758a686ff86dbda48026c7ec3d); + res *= point + (0x45fb08bc21969d5ca9b1ec473cc92a4ad911de8b0607ddc12b9ee98c286d37f); + res *= point + (0x70c0f7da90cd889d8df06f9774de8a9a20c88e86753506c7afd0e1f6ef15e76); + res *= point + (0x1b16d94e84ffd3ad61286f5a79d5a6f7b5b5dd6442aea9013ad21467bf1281d); + res *= point + (0x6a81925732161d4e5dc61ed6a10726027fa66d892aabbf46a477f4455072c02); + res *= point + (0x13ed29a84c4875ac188521bc40e9258e03d83c9ceb8716c6fbeed065a5df73b); + res *= point + (0x184ee38f80fa532983fa248c14c0220c2a5691836e899a5c9b83c975b03608f); + res *= point + (0x65f4a97d2b1c90582859966540e839ac2d62ad2ea960aa2af36776b2d07ce34); + res *= point + (0xe00ac968fe5a147fef45fbd626c540a194ec3dfb2c1cca7938e037349d4f34); + res *= point + (0x96935be4e41797417259166181bb646a619ef95cc8978ffeca81d141d062f7); + res *= point + (0x61c61341c83517cb7d112a76864271492473e04130ce4ce23331f7300bd8c89); + res *= point + (0x73eba0e9e52c3a93ab6dce26d5858b2d699d8401b2c43253616b5701aa803c5); + res *= point + (0x77434256511acfd027b41e03a571a9f56b0442dc675c139a2e1476fe716102c); + res *= point + (0x325f10662fc8bd38e591b0e8caa47b3fff46703656b2c5863d39c150d298fc8); + res *= point + (0x3c835256339330b1c94cad78cfefda36a949b9c8553d918f3d8547cd1805ac5); + res *= point + (0x7340540d0c9f9dd2c1142f03f408ab977afc7371934c62259fdd29f0652f8d0); + res *= point + (0x17d8ab17e403b1925b40206c11f8a6a29ed08217e1ef303906ecb354fdda1f3); + res *= point + (0x78562cbfb984ebea085472a1b004dbf86e7d99f4809a5020969246a84a9d165); + res *= point + (0x60c93d3dac2628ad796e1dc80bc0796d054c991ea23094d699bffb43a630add); + res *= point + (0x72bafd4641e6928ca65cb48e8001ee077944201f70d5bed524c69b709410d3e); + res *= point + (0x6321e76192ba31cc63bf7c526c8ebbf4df5b705f01e4151068ee3dd658aa674); + res *= point + (0x7caaf4f7b073af26c036d8bab5c74fc3f752f9ecc01041787e9ddf773596189); + res *= point + (0x66ada08fe725f364ca32c1055e1ab1216967856d6cd8762dd4ea915c2ed40e9); + res *= point + (0x5b6477413bac2f0d370c0cdcdec4cea10fd322fbcd7b202d4ccbeb0581fd34f); + res *= point + (0x35c99bed31baaf7833ca759a9bea792965a87b42171259ac51b00d872d581fb); + res *= point + (0x7ce96f5a3261a977f04ff70ef416a3d5c165100d19f551a6ac514e4d00fb18e); + res *= point + (0x1c933d3449f6241d0f9d547db9e708fc2ee3e0598be5f87b675fb6736a15c39); + res *= point + (0x687aac173963fe1e01f9e0d50eba0e95e1e8783eb21c0f6c1f45cd42408198d); + res *= point + (0x2f2f5447e274a20d9d60615f83a18b2a4db300d5e199d7c8c6c6cfb754e8cbf); + res *= point + (0x91cd6c3b8ddd8954a44e8a9cf6f7f183af8e6226849f05e6e6ebda2409e042); + res *= point + (0x282ad11848887c771898b5a32ac6ca14cc2510830454aa8e194975e308fe042); + res *= point + (0x5455d2de2d7570fbeeb431a9a21187ecc049874b64a227bb543aab4af16e27b); + res *= point + (0x2fcabf82bfd2529eac169a520cbdb2a0f8c205c5a9b1f1ac69bd3a44b25faa9); + res *= point + (0x33d4fbf9dae7a87cc13db3c95ed3976b50113f072e56a13e675e4af241bb864); + res *= point + (0x3cbf28927ecbda443555c9d51f40c294fb6688a17812cb0c85fb6501cdc0709); + res *= point + (0x4fefb86cfccbbea031f15d85033f10f92f2b6b689153e305bfa8821935979c3); + res *= point + (0x63f4ad31c4d59ee741b1b0ac99e022959df079b5b033ec7a1ecd3b4797f94d9); + res *= point + (0x6c74e3b74559e12949b8c3b55369b2d275b2920b4442c536d63f91debd61499); + res *= point + (0x45a5b88744e83d901f33da0d0de869381e7a125a6d8bd104cf72ded013ea4c6); + res *= point + (0x11243de8b4214dc3220693acfaa6b626cfc3b8c812140779af9b72dfb1b92f1); + res *= point + (0x123f50f65a68168d6b43c464270479801376ff6979b94f60252a47d9d7d34d2); + res *= point + (0x25446fd382a1b0f5350b91290b2dc35a6dabaf215d53cbb32d1732fc6ebfffb); + res *= point + (0x160d7d587f3a17673bf04189e0062c7bab764fb54ebd0f042fec72f953a91da); + res *= point + (0x1e0fcefcc1d1c5a69e81c4fdfe7de04d95b53c162a3b64b5956df8e59e1b93b); + res *= point + (0x1925470cee5111eb991ccc8b0412be603c0b8df342d7b186a3aaeddae103bf3); + res *= point + (0x2848af5bb20ab624881dc9244ea18b1d6939e14270714253a896e57cb0f63ea); + res *= point + (0x6c2a98464d6eb4038d55b57632bb283ab091eac255fd6797df41612cfe3ea1b); + res *= point + (0x31563499de399383464854a8679e0b073513c5bc46cdcc2a2107f00677e6356); + res *= point + (0x6da4d6fb1e6b2f1b42910a9dcc4702912002d7d36ac7100e19c7f298c7948a8); + res *= point + (0x3d368784067d457e43cb63b3f526e721fab153949b090a99a128c5744fab4a2); + res *= point + (0x266b63657dbde655f034c014a8fb73b77138b52eb0e17eacbf402bb90305f10); + res *= point + (0x179f2a40de3db251b95a60431e7cfe2dfa48dc8654bbf81add938e9f2f6725c); + res *= point + (0x1118c09adef545b07e209d88b0a645673a103c9e71e8f671e74c84abf1a2a2d); + res *= point + (0x6ebb7c4ee2d4212e6d7cea8c16f97c935f3bbbc2f400c9a738f1ebd37eec6ee); + res *= point + (0x41d1ca4f756c80f197ba1635314a3dc756f9d8d9406af16538643d3e1021bd7); + res *= point + (0x3129daa367a01a45fe3f0ccde215371f59c5643bfad33f4269a6478c8c8b7f8); + res *= point + (0x1fefe6ebd886640df863e5f5c25e9b42fbc10adfa7ef07d1fda0eabafa60a6e); + res *= point + (0x37e79bd72d714d3de7ed2b1ba79e345f75646bf67efd8ea3050ddb357802a3c); + res *= point + (0x24eb6fb4dbac687e35d4168b970db6e7dc76c4c886dce0d4bad2e6544b8e6c6); + res *= point + (0x6508b5fcc13191197f91407d5b1b21d321b7f311e55ede9ab8a6975308dcee); + res *= point + (0x43e46c5f1cf3b5cac9722eeee991cbcf53af25a4a355a91ea9b8a4d4754d908); + res *= point + (0x7393709fd08807a84ca44526a2b8ec97bce5aad1adf00560d04110de6d9eda8); + res *= point + (0x690c8328ca161c48f3f8f37570e42095d1a0d9e101b3ec0ddc91426fc22facb); + res *= point + (0x41354bad5cbef57b0e7eacebef8f0176f3b70992ea5a418f502242acbc4a1ff); + res *= point + (0x3475f32b5bea9dbd19ec199ef34e531b696cac0461e644ffb41a5e99d0735fb); + res *= point + (0x33cfe02e240929353f193c6d3387f1117d04f116889f38d9a196abdf986e48a); + res *= point + (0x33e7ba5f7e56065e3f8b091578e8e7a7b118116de47237fa5a97e44e97b7f69); + res *= point + (0x5526001b8a8c2c6209e40b5d380836bcf63db4ef85c25fd5b72d749b0bd36de); + res *= point + (0x64028a3945aa2866db68b304dd0d83d75ed0ba5c2f9d0b47e80d11d8da6526d); + res *= point + (0x378113f110b2404e7d185e920249519ded728cb1027fa8cc2843a588886a7ed); + res *= point + (0x5f4fd7854cf7b89a3983da1a39839d85c7331c3353b0a8cd218f7f4e1f780c); + res *= point + (0x6467afeee167ea95feb4a85c48fabb2c7067de57acd5098692855189e21c57e); + res *= point + (0x1e4bf5029043367487394808d7ee7df5ad1ad1da2c4710a1b2444ffde106f2a); + res *= point + (0x684a30c1084e8edf34a77bf8848fd2098459f5461bdf3352faf9c8801435b6); + res *= point + (0xe3f2bdc2de2b623c56390eb0044adb980766ae1a58d775e003c39724d1d6f7); + res *= point + (0x62dae59d425684ef78c1829e0454cd5e76f5d322ea8cb5ae5e911f545beeee1); + res *= point + (0x5761ff2e0a250691a66dc36d372afbd6a8016726efe0c418d7899d60d26bde6); + res *= point + (0x4dc27c76881bb820eb74814d1b69825e9048b1a3b064e603cca4bd4814b2243); + res *= point + (0x5a15d718a45959d16dd6e0b98badbb086e2a9741ac04086f078bc6951506e05); + res *= point + (0x23cf69cfd7730dd096fd485b2d8bdfcd89ca6004689bcbcacbeff288f18ff9b); + res *= point + (0x4d6c233f7bf3ade219a8e3a89e12d05beb7faccbfa811ebd930c391523f7b4); + res *= point + (0x5a347e7937c7a178952905f499babbeda500a820ccfdf7f3a99589687a623e7); + res *= point + (0x43394095e27ddb7825c0671833a6ac9784f31626914c902c225f05ce42bbd9f); + res *= point + (0x66d91bcc591c880303ee4695475e8a8e402926f0c01ade8880c7b03c76998ee); + res *= point + (0x3348152349370ec1c4d753735ef255b50e54aa9a432f48a121c39b8887827e0); + res *= point + (0xfa17235a82497674de45bfa59e61a329b2d0e63eb18ab9b74aa46783e04c81); + res *= point + (0x45ffc1ad229bf52b2531afadd1c5ba120c57b34def87149880d1e5cb6c5391c); + res *= point + (0x37f5f6b25ee428e91e886127b961856d9ebc52740ceb763baa7e71371b84364); + res *= point + (0x58281d625ddb432caef06e485bc2b74cc077aea9ba5072198e76542f0c69dd0); + res *= point + (0x3e35aebb590266ea1fdd8198cf3c23c77731dddd95d488a9d9f9837e3bd0f6f); + res *= point + (0x2850977abc89355540e8abb804da7805ef88b12f40cbd9158ef330b767901eb); + res *= point + (0x72fb3298da88c470a2f93a391063810be01078c8375183b57a024c223f2f428); + res *= point + (0x53f792c81d26c122898d70ed7fcfd8f02a8f5a9ec8b9868fc4490d3a46b4e8e); + res *= point + (0xa7da81afc9f3c93366b6e161b1fc7a497d6c770fb140bf4b64e5fc707cd3d3); + res *= point + (0x26601a459facdd83458b56099975d2b7dbbc431d41b53f5dd6ca2901dfaacfe); + res *= point + (0x4a048ce90e3a1eeedd4932ff37760fd8b1dc995aff7107bd66318652efd1032); + res *= point + (0x287fed27ab81e5f721d2bd5aab0e69f53e94ce5dccc35c2dcc88e12465fadc2); + res *= point + (0x414215fbcef7f5af60f320e67a845e4a17b0a0eca39b4e18ba89fbe8a189491); + res *= point + (0x208f0c2f5a114b2342f51e919e4fe44c2a42cd06382d9edc4ef58939b249bab); + res *= point + (0x5726e3dee7bbc5e5b4f3ad65f0fb17699efb5936d50ad380785f2b10fe8953b); + res *= point + (0x6fa8562db8de26797e9c9905aa769e4881304b4f20cb64d718d271c182f44fc); + res *= point + (0x2a60396cf912573be2837653283a23702037f614e33e1c6fe2834eee9a1c7a6); + res *= point + (0x5b6b3213744858ad659c4c07c9220380d63c01f680986191c8776eb703661c3); + res *= point + (0x709a47e72cda4fdf428bb9784f02f77c700086755d4bdb5b229d1b80a2ea4e5); + res *= point + (0x75e9c821cdd2e754759306283aa4af8bdbb0ed31f4e978dc550141fd10da6be); + res *= point + (0x2adfa41f72ba3b61b9dfa6f017b19682b0b0f8cd86be3d37374aba3ce990a55); + res *= point + (0x6e313bf82c34d3af1e7fc14d811dde163ca6e57accbe476875e4a967da00b8); + res *= point + (0x78516acc9d32f4e54f8925865c91f70b210f4ebc7533fc624685b3d5daa7b18); + res *= point + (0x3b8cca1c3fb2b26b7e206802d52d2ed1c725b8f95407e3ef295a7dd9ee0d45e); + res *= point + (0x287ef69d6f69ab853e4f0d24b22e4c15169d12c41706dbeede9fb49c61179c4); + res *= point + (0x7c84837e6872bea4f0448183cecd6bb24a8574456ab91173b04b9423be8a64b); + res *= point + (0x78f890541865c12169233143f47a056a91dbd18222c5d31bfb2db19162c204c); + res *= point + (0x46cbc37eff4616daaa86160d5690f5473e24171441e29705ae564223a351c23); + res *= point + (0x309f9698e38823c05e56d073d83ea551bfa80ace08e749aa4c83031a22360c2); + res *= point + (0x1a2cd41155bbb7ceee94dbd01bd876140b1698f03b2ff8f8de3ba45b4ea14e); + res *= point + (0x10699899068f86fa3843b06693288630b9ac4b87be7b3726fdba32b41caac2b); + res *= point + (0x2762878a5f6665bee609c26e750cd886e239c31caf1508d5a2a185b58576b77); + res *= point + (0x57f7a737e643bd859d8a53e1b621c09be89fcca7b96f8e42333e46426f26a20); + res *= point + (0x7239c3b89513196e3cae91f8df8bd79f08033061ba63c089bd764644907479e); + res *= point + (0x38cb4f77410e9a33306f8a4b92b6f76bf239ba44e0ef45dab0bfcb75dfe4141); + res *= point + (0x382114ce9d712af864a253d29471a436b83ee4f7b8ae3fe19ec3ab315e18d8a); + res *= point + (0x51ceb130c1908fdcfa6896756241fca8f74ab172d98c76facb7b8b931fa8812); + res *= point + (0x4f6b918e40f8022d2bda8d53214e8fd84743bc2280231d3ae772844bbcd1aac); + res *= point + (0x2d9af4ef0d50851ae1b0cdab3587a71728eaaa4e56e67803c5ff9126e722696); + res *= point + (0x4640cb2cbc73d7c9fd2a1783122cb5ee8c68e7c04b0b647d43a35cd4961e4ca); + res *= point + (0x1b3104591a23f262051182209c0f73caa30e8631fc4413a5bf97c9d51a70abb); + res *= point + (0x2103ea7ff918748c4325a992c561b551b70fa9d97e48a52b3c157799d213693); + res *= point + (0x69fb58adef701279dddeff71e1832aea01ae10a5128a9f744a5a945b5fff200); + res *= point + (0x375e99f4993200342e6f6ad713711052d518e5dac24681b3999878bbad627d); + res *= point + (0xe051fab79733dd773d13f5bec04b1c20252df512d937f6b7352e4c4fa49cb); + res *= point + (0x5d72a87fe662c05530c3ec822f925a10c121a44c4adecf24850fa2442cb4abb); + res *= point + (0x6f2a9f716b1fa27c35675a57273feb79ffce02286bcb1e253a8e126c2cea357); + res *= point + (0x9b419422a2083bf174263351640e009b56d6e2278552f9e7ee6a6004d45524); + res *= point + (0x3dee84f905f6a06940783bc3f322a0fc22a984dd244d00a85ea3a4295558377); + res *= point + (0x3dbd68c7c5945f48515d975002a1caf1c491c6743f151df31f95c5870c90fb3); + res *= point + (0x7d52bb08c1d72a66c3e5c60f6742675ac788ec8b4f2178ff9990a04d22c076e); + res *= point + (0x107c8fc81a96a3c13d1ddf04b8bcce0450610c2ee6c127e0f47ce2ed2fa0613); + res *= point + (0x6d8f39b47e79d44503aa87a3fdf101b055f89c663bd7ec377d175280f3f8db9); + res *= point + (0x6d5a755e91ed732dcf8afd32eac3b4875843bb116430a966ef88f17aad54c16); + res *= point + (0x64035ce25716c9c7675ecce40d3cfb65ce3121439e10367fe29f2742cc02d85); + res *= point + (0x3e44a162d501fc521774c75994f4b55eb85878f5e867cacb75c7ff0b7efe941); + res *= point + (0x1b2441db55dbd9b87c45b1afba238ed28d1f2dfe9725d9a4cae3a45e3d59b63); + res *= point + (0x8b54ed775cf8f3dd5b54fcdea07e2bcefae323f6212b8f54877a60e1f8026f); + res *= point + (0x338c001d0c722d793cc14219415d61c52de28d33ab8bfe5dd31674784f2b568); + res *= point + (0x4ea62ac09b98dcc34b5437f6bdb4fb9a681dac12d1ca7090011c73259dcef4b); + res *= point + (0x6a226b1dabca8ff2fbb52f0adcf4267a47e0eed089774157f318b507361a0b8); + res *= point + (0x6ba0329f670df105c31eb665f3b6f243ab5de7ed8aa59ce9b0683e6bdfd9019); + res *= point + (0x77f62cb2f9db71ba7a9913be0a434ca045a26704681af5353b7c7860be6e774); + res *= point + (0x770018fe3435297b82b391a3bd2d09151dd3949545d0ef111cdf9fece9f389c); + res *= point + (0x4279b49402fada9fcb602f909bc138c3547baf384dfef9594e2fa488cfdf8b8); + res *= point + (0x4dabf5afe371cde17b9fa6c54c1b38d603f345c58d4f66e06fedd8948b402b0); + res *= point + (0x15296a7d071a85f1358bb157d5e62b18a11e189415c16f594a18be7276ed2c7); + res *= point + (0x79708fbce6bbe1c862e988648dd25347d60c9e0981540dd81ccaf78054a12f8); + res *= point + (0x209866f9b8d946508db2df8eb9d30f65ede2c99ec8deb2e5a1b7093e9a62416); + res *= point + (0x4ab0da9c66ca2588350bdb85cc745b4c5e7226cf7c4fb69708cddf6e8145f29); + res *= point + (0x54578b117a58f5beb0d511ba42110c4696f4fec165acfbbde208a4705045fc0); + res *= point + (0x55c9e37b0208bfbbb61e5e0e05c72111421b24b45ea53d3ddfad1cdfd243ff0); + res *= point + (0x5889b4a99416f2f954450c60492129c5f7a36f875a56dde5188318e88d6032a); + res *= point + (0x5919f2392a53f9b230145d1b5e6da28165dd1d8cc7d28d3310a805ebee721fd); + res *= point + (0x43e49d0d9bfd165776eeab9118ea672c24a055a700e35a04426abe1b236506b); + res *= point + (0x40e394412097f7c06183ae2997707604273b0a4ec1add0030bd7e115c20ca70); + res *= point + (0x6337d741eb226911e37cc48087126cdd89f00941523cda2fa5e965dc4fa25e4); + res *= point + (0x64592b7d9a6a922f5cf5f74c56e167ec000436a6b3caec299bcefea25e5fdd1); + res *= point + (0x1d608ffab983d8aa17db9385433abb0025c77e27357285448c4ff6a8438570a); + res *= point + (0x333793406d06dad0406a859ea2c203aff33e3cd906d6f04aabb0dffbabbc9c); + res *= point + (0x3b5f2338d066753b2507a39884bddc2d0c5bef88e4bc3e79288331afe9a6234); + res *= point + (0x3fa0ff20cc486bd0b43f96826c66b070a6f6e3df3359ebd2970661f9c679e2e); + res *= point + (0x62cea6c83442875da8b98083d8bb18bce5d3d431a3301afc635600578b33506); + res *= point + (0x4835c753d4b5059c1b4186516851f562e63e348f8810714cc393be9810a1de8); + res *= point + (0xc230c4af49117fa614b1d4d74ef462211a5d55537ac71564ace080dd4b325); + res *= point + (0x1917c10cc63bc9f43116c3688542cd867e1a84ce0d3e58dfb0c11c4b0828748); + res *= point + (0x13c6580dce66b35fd24183e1635fb6008a6deb6cb507bf48d531273d5b4c2e9); + res *= point + (0x6c6dbd58b8657f8588bae8a4d990e6f9b0525af4eabe87512c5f6a655c92028); + res *= point + (0x59daeadc724e9c227258a56b000c6a613db617da41bbeb694521c86323c93b); + res *= point + (0xead9e7eac2f6c388de28561955e6009f9f1ed098f70516f2bda28597c9ee03); + res *= point + (0x54600ac31d014f7241c14e5aedefdc72b839cb0e98b84aa13f031316af48648); + res *= point + (0x5370b38ea84ca67c75ab50a4cb8f23f4017175a98b23df9e1c92f92c279e169); + res *= point + (0x23ae2f35a2da5ff92426d59ce066e29a525ee1207de1c370023975b4403ac6d); + res *= point + (0x5952b292edb661874ff2d3482fb968149f09982bd7a194d2b502ee3dd32927b); + res *= point + (0x30c7ab8fe6b61574f49c3d76b3173f76816f31beb33097d425a94beab6caaa2); + res *= point + (0x4dbc9ceabbf1c8d5c679cf80d9bfc26ab696135792e83061e98b9c36ae6a4a0); + res *= point + (0x3f1908469233dcf5c433790cb3574261ed6debca41fb55b912be7cf34adc187); + res *= point + (0x51778c6b175ce13e994dc1604dac3b901990cbae0246b2cec2aecbe96dd2006); + res *= point + (0x6a91b3677713dc15cd110c71cb8e174c8ebd8d7df1a1b4120bb4b6b1683ad5c); + res *= point + (0x3cfdc71122fdfc7807b2efe35fb6c7691985d2727401eb8a8132d0e0df3cdd6); + res *= point + (0x5099f832fdec91fd27af0d221e009ed6770227d63bcee6e1802cdd122751260); + res *= point + (0x1793fa490096ddd67530e29cb3e8e9632d1885815be3f9d96375aa5946f511); + res *= point + (0x6d4bd8c4aa4a530d965180c18062d6bc440e6e70cbf0836d6af11235c7fde2d); + res *= point + (0x3d7587a79c4ae9c24934a10a9c1398c04f3915fb6889b72b361505a85db2b69); + res *= point + (0x39007630deec4a6eaf806518c109f4aff9cbfb8826d86f301e562ec560ff89); + res *= point + (0x51e4a728ecd68dc30e4a1b5867a1022af5808edafc3cb12d26d43b495528f18); + res *= point + (0x7f921548c686f600b302290f692a66e9ececa142f691f9129c7d8bd2a06803f); + res *= point + (0x42cdd4f6ecbfd891fedb9ecb6d320f6adafdb274ee15cc11ef4c0436a4e9afb); + res *= point + (0x755d64434e4e4233388c34a90438764c568353cfde4311021b45e0f369b0db3); + res *= point + (0x4b5e107dbcd02c0dbef4d3a77d66386a864d31109d0d0392847c8919d926fbe); + res *= point + (0x373a1f2fbe36dae9a5f2c2b35febe59b53869e1678c8da23bd9e92c3c2ac0a7); + res *= point + (0x53bad76d22e1525dcec248b73438d6f444caf75794c26144e26803fe2bc7736); + res *= point + (0xaeb135e456ad66bb5bb2b91a4aa429915f6f9951aa15bba78576744a698016); + res *= point + (0x111d440a13cab69043e1072b61c1736cf3901941b4c57d7602b8effa7e74b3c); + res *= point + (0x5fb8d87e82c3547e32ce316e4439d1aaf3723e4a906c91533ba8dd9631f1661); + res *= point + (0x1426a2050d240104b5c07a9cdaf7fce03c2accadb0ce98344ecb4942c434db); + res *= point + (0x929eaf221c110efdaa57970581428d66d5866fb9547aab76e89e8971efc91b); + res *= point + (0xcb3220da969b95193a25d1d4d76d1cd1ec596040a7b31da7f64164809bdc4); + res *= point + (0x3c3ea2cbc8ce544c6c98ad9053cb2c35326f4e502214e5f72c7951474b5a84c); + res *= point + (0x68892b41018bc73b541800d91f0bb2a8cd9fcfee8be13bacbaf7dff7aecdcd4); + res *= point + (0x2a652d2592f5cc1197a206db79d06e3b74a55b1d4ec03c516a6957e87345cbf); + res *= point + (0x1e0c96f0b836d1e2df4e4063d56b78f38f2ad16040d61855b0f664c066d130c); + res *= point + (0x65d167bcce20a40b78583e4dcf7e3f44663e0c595e18f48f83ea4230b207047); + res *= point + (0x1668b919fcdf512b5683880ed048853e00f456adde728427fcde63ac9f59611); + res *= point + (0x1489d6012d4c9701b63f3610034fb5bfca185c7b01222907781eb104e031097); + res *= point + (0x57ad5370b26ea1478f3fa0346d2e390e90feda8022c9820813d9ddd0f36e7ba); + res *= point + (0x522f83a59f717f37b235c05338a02630ad83c3ed307838f6e795f9705cbc849); + res *= point + (0xb6bca44a12ba7914e575f83cf8b9b8bcd4780622806901dcb9530ff9a454f8); + res *= point + (0x6fb8324456f1dc4b423220d18d40de524a27dc4f35e4c780a042f6edc95f97d); + res *= point + (0x2039c72c1c7c134fb300e82b104394f54a5b7ffe6f7f00e7c3e4ca6640841a9); + res *= point + (0x614a280377b9dc732773d969da5ddd8cc125262313eb7b2bd38b7668cdf00b4); + res *= point + (0x243a084aa8c82348102320b0ad19ede41b6bd7ffb3a7041339a13f34f6b5671); + res *= point + (0x73e8c35fa646fce6bf10c33168dcf3d2e40af17ced70b1929826d0ca4ba2e99); + res *= point + (0x64f6f50e51b19d5a90e6d2c9cfc3486dbf2b37c7f949cc4f8ac4dd988e5bdff); + res *= point + (0x1365aaaf8c72d7e9b250bd91ee2c2264362e87679abcf2df2b7a4e1eda1575f); + res *= point + (0x24a083b7cf164138ea0c468f33317d89c97b69378c906d918123f3ed5a02cf7); + res *= point + (0x25ea89f2d7ad620296fda2be181b5a6be626eade8974facd81e53df842c125b); + res *= point + (0x2d32dd179cf74693057ede607e0054fbc3e4194efd6415156f3ec909c37ead2); + res *= point + (0x3b74f537f03a28e72bae3bf1810f1a2fde1711eacd6bc64bf55f37b3bd9940b); + res *= point + (0x575b929bc0caa43939bfae95a6d5cd8d4082be7fe0934be4c08f7fd3cbe89c5); + res *= point + (0x7ab2a5ce120c251b658bfe532880535e93cbf88aa60a1b384017195e6715706); + res *= point + (0x7a7d5ce80c8498175cdd4408e08cea457517e37dcba08d0a6cd2a4defcce34d); + res *= point + (0x6475aad2a1631a6103b238548fe8a03934779ecadeaead2bc20a677c0c71c); + res *= point + (0x547ddf1021a2cbacc8081cbe3a5c89b8ae808942513cd6f6ad166b0306cee66); + res *= point + (0x653405343098520984b06f707cee84ea765ecc932783cca87058b88d0f2bbe9); + res *= point + (0x3f22422d66d77bda123b47b7f5bffe5527f95d331346f6a545c66887ad75ab9); + res *= point + (0x1b18b73effab8a483156d16e87be4dfce1250333eafc784d76c6ee145978c48); + res *= point + (0x2843bf3d789d84faebdd6ceb0eed3ec0acd959732178b00b4242eb5cff0ef3a); + res *= point + (0x592d2fbca1f86935e587f6cfdacd0a221237bd378e2d1cbadc3d168c7a1756c); + res *= point + (0x4c35c95cf7170d2ab6b9b6e3c1be66dba2de170638f27975fb5ec12c36a45d); + res *= point + (0x405f9011670f0f202814795cdf0251b665e8f39991dfe2282a1dd2acdbaccb1); + res *= point + (0x43b4be816239e45b4d22123c840717fe3e8f6ce53238fad4ad56e27c85f3e9); + res *= point + (0x3a2c1769a49e0632c149dc9d3f30306f9d9cc00cdb426d58b2741c804c51af4); + res *= point + (0x422c03b47f25f698d3dfbb02556367c97b7d8e2657af2e45ebc61845aa2c52b); + res *= point + (0x5a47f80b2d6e8c8e89f08c23e4eee09ae23882290a4dbdc5d0b09e713297124); + res *= point + (0x2059b2385d435959cedebbb68ab5c484441832a20d67889ff9974057cdbf874); + res *= point + (0x6b735de6be3ab4aa1425c328c838ba09dec586718729f1e172554cac036483b); + res *= point + (0x3c05c93a63aad66725d8d25e62f76199a1e9f5743577777caa05832f4e79acc); + res *= point + (0x4245e03d0378593b2d4230b945a2a147b36ebfdf368f0dd5fc22e3b31ac1186); + res *= point + (0x4de104ea20937d5d6cb02c4ab4d7c4d03ab2eb16d1b837ccf0c2a05ea2873b1); + res *= point + (0x48876d457eaebe03383add02eb4c0c49a09923757428595a4f3ad6299d69cba); + res *= point + (0x6d6ed610ff1347a9252bf835af9666acc415b28796d968ab76353cdc1181733); + res *= point + (0x1da9b14257c5c5cbc1a97aff87690dfa51e82af9a11eaf5cb2538f595ea2105); + res *= point + (0x416057baac3a1780d7d25b192188b9b3981bdcab0e2dffb2fd95456a5313201); + res *= point + (0x1706af2f962881d86f167571fcbb909b6f1e4fa386fca8d87b674335196f44b); + res *= point + (0x6d9c76938c974418e62166285ade6564712e6a263357e11d70f3e1f2ae531e8); + res *= point + (0x771fefe011becb392f5c379dc9e902c41be8f1069ae3c5e0bf6016b7b1b3f55); + res *= point + (0x40cbcae9364d8af8b767a72b260793922cf1ba2a03fedfc60d4eab1d5f00042); + res *= point + (0x274b54e6342ced28b28c62edbc8a6cdb44d1530e0fba56e4940e55d806f437f); + res *= point + (0x77273f7030b86a46aee79ed44f0968feb0ffccfa0964ffff141e693fd0fb6d1); + res *= point + (0x4dbe5188f23eedad88bab99323be5ac9bf747525c23d4c0665334dafd1f0c6); + res *= point + (0x3410d8b91297b00cf8d438bea18b9ebd55ae441a2f6bac6623a15e43ad64d4d); + res *= point + (0x4195cb2f46ca4e1ef5d93ab3a5decbdc9e74d0bb81d56abcf59304ecf79863c); + res *= point + (0x6581a70ec64b4268a4741b4f7de866050d31b69005c782630f4bdc51a1650b2); + res *= point + (0x754535ea8702292678b57fbde36c97454994bed59e0d0e13cf8a6c3ef7a0324); + res *= point + (0x71034c062fdc1b61e812617b037c5dd1e80d158a92bdae7ccaec162fff4edd3); + res *= point + (0x297d52739d69b228b057588496920930df6ada28e5e2a431b65502750a5bad7); + res *= point + (0x446d7e2595a1940ab7f6dec4c9f78953de9c0f4c67a130b55f1894779e73ac3); + res *= point + (0x5b0a8465067d8f43cac5dbc1145110e1e79e0f32ba1d59d2514405a0a806860); + res *= point + (0x5bdc50def36283e003e9ccf2f1bed188326bec8bed554815f9e49062ed6da4a); + res *= point + (0x3b591c6de6700576abbe4b4544de71cd3266a5dbb70740762d0c16a863bead8); + res *= point + (0x7fe75f49544ac3cf237a17e58179851f5b3e7420330e5861ec505291d9a0380); + res *= point + (0xe09e3870dab755cabbeac23076891b510207da569b75bf32d3f63c8ce08460); + res *= point + (0x66bb11e034bb55410211b7cd410cf076db77f008bd93f0dc938f089e853f0ee); + res *= point + (0x630cb6b8bcbe79e58025a699d489116a875f287fef6f1677b497b8702c3777d); + res *= point + (0x46ebc0bdf94c2f85023a0c1b29d229ef7a23e173d310b814f72c73904f6a5f9); + res *= point + (0x3fdf21da099da6c005b076001c5a95f2fe26aeff47e2cb9e8e52166a22b643e); + res *= point + (0x6c647f1e5e8e93fda4bc0ae5d513cb60558e2b44bf885484161bbfb5e093969); + res *= point + (0x688dbf5c443560c219afd8c54a0b26bdc9284925f2cc0adc889c1de024d6ecd); + res *= point + (0x3c782f4a1a6d94adf1448fd7feef975f47af9c79bbf7e2d74940673704b828a); + res +} + diff --git a/src/air/public_input.cairo b/src/air/public_input.cairo new file mode 100644 index 000000000..789c3c192 --- /dev/null +++ b/src/air/public_input.cairo @@ -0,0 +1,61 @@ +use cairo_verifier::air::public_memory::{ + Page, PageTrait, ContinuousPageHeader, get_continuous_pages_product +}; +use cairo_verifier::common::math::{pow, Felt252PartialOrd, Felt252Div}; + +#[derive(Drop)] +struct SegmentInfo { + // Start address of the memory segment. + begin_addr: felt252, + // Stop pointer of the segment - not necessarily the end of the segment. + stop_ptr: felt252, +} + +#[derive(Drop)] +struct PublicInput { + log_n_steps: felt252, + rc_min: felt252, + rc_max: felt252, + segments: Array, + padding_addr: felt252, + padding_value: felt252, + main_page: Page, + continuous_page_headers: Span +} + +#[generate_trait] +impl PublicInputImpl of PublicInputTrait { + // Returns the ratio between the product of all public memory cells and z^|public_memory|. + // This is the value that needs to be at the memory__multi_column_perm__perm__public_memory_prod + // member expression. + fn get_public_memory_product_ratio( + self: @PublicInput, z: felt252, alpha: felt252, public_memory_column_size: felt252 + ) -> felt252 { + let (pages_product, total_length) = self.get_public_memory_product(z, alpha); + + // Pad and divide + let numerator = pow(z, public_memory_column_size); + let padded = z - (*self.padding_addr + alpha * *self.padding_value); + + assert(total_length <= public_memory_column_size, 'Invalid length'); + let denominator_pad = pow(padded, public_memory_column_size - total_length); + + numerator / pages_product / denominator_pad + } + + // Returns the product of all public memory cells. + fn get_public_memory_product( + self: @PublicInput, z: felt252, alpha: felt252 + ) -> (felt252, felt252) { + let main_page_prod = self.main_page.get_product(z, alpha); + + let (continuous_pages_prod, continuous_pages_total_length) = get_continuous_pages_product( + *self.continuous_page_headers, + ); + + let prod = main_page_prod * continuous_pages_prod; + let total_length = (self.main_page.len()).into() + continuous_pages_total_length; + + (prod, total_length) + } +} diff --git a/src/air/public_memory.cairo b/src/air/public_memory.cairo new file mode 100644 index 000000000..262af7ddc --- /dev/null +++ b/src/air/public_memory.cairo @@ -0,0 +1,64 @@ +#[derive(Drop)] +struct AddrValue { + address: felt252, + value: felt252 +} + +type Page = Array; + +// Information about a continuous page (a consecutive section of the public memory).. +// Each such page must be verified externally to the verifier: +// hash = Hash( +// memory[start_address], memory[start_address + 1], ..., memory[start_address + size - 1]). +// prod = prod_i (z - ((start_address + i) + alpha * (memory[start_address + i])). +// z, alpha are taken from the interaction values, and can be obtained directly from the +// StarkProof object. +// z = interaction_elements.memory_multi_column_perm_perm__interaction_elm +// alpha = interaction_elements.memory_multi_column_perm_hash_interaction_elm0 +#[derive(Drop)] +struct ContinuousPageHeader { + // Start address. + //start_address: felt252, + // Size of the page. + size: felt252, + // Hash of the page. + //hash: u256 + // Cumulative product of the page. + prod: felt252, +} + +#[generate_trait] +impl PageImpl of PageTrait { + // Returns the product of (z - (addr + alpha * val)) over a single page. + fn get_product(self: @Page, z: felt252, alpha: felt252) -> felt252 { + let mut res = 1; + let mut i = 0; + loop { + if i == self.len() { + break res; + } + let current = self.at(i); + + res *= z - (*current.address + alpha * *current.value); + i += 1; + } + } +} + +fn get_continuous_pages_product(page_headers: Span) -> (felt252, felt252) { + let mut res = 1; + let mut total_length = 0; + let mut i = 0; + loop { + if i == page_headers.len() { + break (res, total_length); + } + let current = page_headers.at(i); + + res *= *current.prod; + total_length += *current.size; + + i += 1; + } +} + diff --git a/src/common/math.cairo b/src/common/math.cairo index 978aacc95..30ab6f323 100644 --- a/src/common/math.cairo +++ b/src/common/math.cairo @@ -27,3 +27,43 @@ fn mul_inverse(x: felt252) -> felt252 { // a ^ (p - 2) is the multiplicative inverse of a modulo p. pow(x, STARK_PRIME_MINUS_TWO) } + +// Verifies that 0 <= x < RANGE_CHECK_BOUND +fn assert_range_u128(x: felt252) { + let a: Option = x.try_into(); + assert(a.is_some(), 'range check failed'); +} + +impl Felt252Div of Div { + fn div(lhs: felt252, rhs: felt252) -> felt252 { + let lhs_u256: u256 = lhs.into(); + let rhs_u256: u256 = rhs.into(); + (lhs_u256 / rhs_u256).try_into().unwrap() + } +} + +impl Felt252PartialOrd of PartialOrd { + fn le(lhs: felt252, rhs: felt252) -> bool { + let lhs_u256: u256 = lhs.into(); + let rhs_u256: u256 = rhs.into(); + lhs <= rhs + } + + fn ge(lhs: felt252, rhs: felt252) -> bool { + let lhs_u256: u256 = lhs.into(); + let rhs_u256: u256 = rhs.into(); + lhs >= rhs + } + + fn lt(lhs: felt252, rhs: felt252) -> bool { + let lhs_u256: u256 = lhs.into(); + let rhs_u256: u256 = rhs.into(); + lhs < rhs + } + + fn gt(lhs: felt252, rhs: felt252) -> bool { + let lhs_u256: u256 = lhs.into(); + let rhs_u256: u256 = rhs.into(); + lhs > rhs + } +} diff --git a/src/lib.cairo b/src/lib.cairo index c1d190018..eba91d1fa 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -2,6 +2,8 @@ mod channel; mod common; mod input_structs; mod structs; +mod air; +mod oods; mod fri; mod table_commitment; mod vector_commitment; diff --git a/src/oods.cairo b/src/oods.cairo new file mode 100644 index 000000000..76a9c6f04 --- /dev/null +++ b/src/oods.cairo @@ -0,0 +1,34 @@ +use cairo_verifier::air::composition::eval_composition_polynomial; +use cairo_verifier::air::global_values::InteractionElements; +use cairo_verifier::air::public_input::PublicInput; + +struct OodsValues { + mask_values: Array, + split_polynomials: Array +} + +fn verify_oods( + oods: OodsValues, + interaction_elements: InteractionElements, + public_input: PublicInput, + constraint_coefficients: Array, + oods_point: felt252, + trace_domain_size: felt252, + trace_generator: felt252 +) { + let composition_from_trace = eval_composition_polynomial( + interaction_elements, + public_input, + oods.mask_values, + constraint_coefficients, + oods_point, + trace_domain_size, + trace_generator + ); + + // TODO support degree > 2? + let claimed_composition = *oods.split_polynomials.at(0) + + *oods.split_polynomials.at(1) * oods_point; + + assert(composition_from_trace == claimed_composition, 'Invalid OODS'); +}