#pragma once
#include<immintrin.h>__attribute__((target("sse4.2")))inline__m128imy128_mullo_epu32(const__m128i&a,const__m128i&b){return_mm_mullo_epi32(a,b);}__attribute__((target("sse4.2")))inline__m128imy128_mulhi_epu32(const__m128i&a,const__m128i&b){__m128ia13=_mm_shuffle_epi32(a,0xF5);__m128ib13=_mm_shuffle_epi32(b,0xF5);__m128iprod02=_mm_mul_epu32(a,b);__m128iprod13=_mm_mul_epu32(a13,b13);__m128iprod=_mm_unpackhi_epi64(_mm_unpacklo_epi32(prod02,prod13),_mm_unpackhi_epi32(prod02,prod13));returnprod;}__attribute__((target("sse4.2")))inline__m128imontgomery_mul_128(const__m128i&a,const__m128i&b,const__m128i&r,const__m128i&m1){return_mm_sub_epi32(_mm_add_epi32(my128_mulhi_epu32(a,b),m1),my128_mulhi_epu32(my128_mullo_epu32(my128_mullo_epu32(a,b),r),m1));}__attribute__((target("sse4.2")))inline__m128imontgomery_add_128(const__m128i&a,const__m128i&b,const__m128i&m2,const__m128i&m0){__m128iret=_mm_sub_epi32(_mm_add_epi32(a,b),m2);return_mm_add_epi32(_mm_and_si128(_mm_cmpgt_epi32(m0,ret),m2),ret);}__attribute__((target("sse4.2")))inline__m128imontgomery_sub_128(const__m128i&a,const__m128i&b,const__m128i&m2,const__m128i&m0){__m128iret=_mm_sub_epi32(a,b);return_mm_add_epi32(_mm_and_si128(_mm_cmpgt_epi32(m0,ret),m2),ret);}__attribute__((target("avx2")))inline__m256imy256_mullo_epu32(const__m256i&a,const__m256i&b){return_mm256_mullo_epi32(a,b);}__attribute__((target("avx2")))inline__m256imy256_mulhi_epu32(const__m256i&a,const__m256i&b){__m256ia13=_mm256_shuffle_epi32(a,0xF5);__m256ib13=_mm256_shuffle_epi32(b,0xF5);__m256iprod02=_mm256_mul_epu32(a,b);__m256iprod13=_mm256_mul_epu32(a13,b13);__m256iprod=_mm256_unpackhi_epi64(_mm256_unpacklo_epi32(prod02,prod13),_mm256_unpackhi_epi32(prod02,prod13));returnprod;}__attribute__((target("avx2")))inline__m256imontgomery_mul_256(const__m256i&a,const__m256i&b,const__m256i&r,const__m256i&m1){return_mm256_sub_epi32(_mm256_add_epi32(my256_mulhi_epu32(a,b),m1),my256_mulhi_epu32(my256_mullo_epu32(my256_mullo_epu32(a,b),r),m1));}__attribute__((target("avx2")))inline__m256imontgomery_add_256(const__m256i&a,const__m256i&b,const__m256i&m2,const__m256i&m0){__m256iret=_mm256_sub_epi32(_mm256_add_epi32(a,b),m2);return_mm256_add_epi32(_mm256_and_si256(_mm256_cmpgt_epi32(m0,ret),m2),ret);}__attribute__((target("avx2")))inline__m256imontgomery_sub_256(const__m256i&a,const__m256i&b,const__m256i&m2,const__m256i&m0){__m256iret=_mm256_sub_epi32(a,b);return_mm256_add_epi32(_mm256_and_si256(_mm256_cmpgt_epi32(m0,ret),m2),ret);}