You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							157 lines
						
					
					
						
							4.1 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							157 lines
						
					
					
						
							4.1 KiB
						
					
					
				| // m > 0, m = 2^m1 | |
|  | |
| namespace cln { | |
| 
 | |
| class cl_heap_modint_ring_pow2 : public cl_heap_modint_ring { | |
| 	SUBCLASS_cl_heap_modint_ring() | |
| public: | |
| 	// Constructor. | |
| 	cl_heap_modint_ring_pow2 (const cl_I& m, uintL m1); // m = 2^m1 | |
| 	// Destructor. | |
| 	~cl_heap_modint_ring_pow2 () {} | |
| 	// Additional information. | |
| 	uintL m1; | |
| }; | |
| 
 | |
| static inline const cl_I pow2_reduce_modulo (cl_heap_modint_ring* _R, const cl_I& x) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	return ldb(x,cl_byte(R->m1,0)); | |
| } | |
| 
 | |
| static const _cl_MI pow2_canonhom (cl_heap_modint_ring* R, const cl_I& x) | |
| { | |
| 	return _cl_MI(R, pow2_reduce_modulo(R,x)); | |
| } | |
| 
 | |
| static const _cl_MI pow2_plus (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var cl_I zr = x.rep + y.rep; | |
| 	return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); | |
| } | |
| 
 | |
| static const _cl_MI pow2_minus (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var cl_I zr = x.rep - y.rep; | |
| 	return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); | |
| } | |
| 
 | |
| static const _cl_MI pow2_uminus (cl_heap_modint_ring* _R, const _cl_MI& x) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var cl_I zr = - x.rep; | |
| 	return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); | |
| } | |
| 
 | |
| static const _cl_MI pow2_one (cl_heap_modint_ring* _R) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	return _cl_MI(R, R->m1==0 ? 0 : 1); | |
| } | |
| 
 | |
| static const _cl_MI pow2_mul (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var cl_I zr = x.rep * y.rep; | |
| 	return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); | |
| } | |
| 
 | |
| static const _cl_MI pow2_square (cl_heap_modint_ring* _R, const _cl_MI& x) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var cl_I zr = square(x.rep); | |
| 	return _cl_MI(R, ldb(zr,cl_byte(R->m1,0))); | |
| } | |
| 
 | |
| // Timing comparison with std_recip, on a i486 33 MHz running Linux: | |
| // timeMIpow2recip N inverts an (N*32)-bit number. | |
| //   N  std_recip pow2_recip | |
| //   10   0.0030  0.00017 | |
| //   25   0.011   0.00068 | |
| //   50   0.035   0.0024 | |
| //  100   0.124   0.0090 | |
| //  250   0.71    0.055 | |
| //  500   2.76    0.193 | |
| // 1000  11.0     0.61 | |
| // 2500  68.7     2.2 | |
| // 5000 283       5.0 | |
| static const cl_MI_x pow2_recip (cl_heap_modint_ring* _R, const _cl_MI& x) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var const cl_I& xr = x.rep; | |
| 	if (!oddp(xr)) { | |
| 		if (R->m1 == 0) | |
| 			return cl_MI(R, 0); | |
| 		if (zerop(xr)) | |
| 			cl_error_division_by_0(); | |
| 		else | |
| 			return cl_notify_composite(R,xr); | |
| 	} else | |
| 		return cl_MI(R, cl_recip2adic(R->m1,xr)); | |
| } | |
| 
 | |
| // Timing comparison with std_div, on a i486 33 MHz running Linux: | |
| // timeMIpow2div N divides two (N*32)-bit numbers. | |
| //   N   std_div  pow2_div | |
| //   10   0.0035  0.00017 | |
| //   25   0.0136  0.00068 | |
| //   50   0.043   0.0024 | |
| //  100   0.151   0.0090 | |
| //  250   0.85    0.054 | |
| //  500   3.3     0.21 | |
| // 1000  12.3     0.86 | |
| static const cl_MI_x pow2_div (cl_heap_modint_ring* _R, const _cl_MI& x, const _cl_MI& y) | |
| { | |
| 	var cl_heap_modint_ring_pow2* R = (cl_heap_modint_ring_pow2*)_R; | |
| 	var const cl_I& yr = y.rep; | |
| 	if (!oddp(yr)) { | |
| 		if (R->m1 == 0) | |
| 			return cl_MI(R, 0); | |
| 		if (zerop(yr)) | |
| 			cl_error_division_by_0(); | |
| 		else | |
| 			return cl_notify_composite(R,yr); | |
| 	} else | |
| 		return cl_MI(R, cl_div2adic(R->m1,x.rep,yr)); | |
| } | |
| 
 | |
| static cl_modint_addops pow2_addops = { | |
| 	std_zero, | |
| 	std_zerop, | |
| 	pow2_plus, | |
| 	pow2_minus, | |
| 	pow2_uminus | |
| }; | |
| static cl_modint_mulops pow2_mulops = { | |
| 	pow2_one, | |
| 	pow2_canonhom, | |
| 	pow2_mul, | |
| 	pow2_square, | |
| 	std_expt_pos, | |
| 	pow2_recip, | |
| 	pow2_div, | |
| 	std_expt, | |
| 	pow2_reduce_modulo, | |
| 	std_retract | |
| }; | |
| 
 | |
| static void cl_modint_ring_pow2_destructor (cl_heap* pointer) | |
| { | |
| 	(*(cl_heap_modint_ring_pow2*)pointer).~cl_heap_modint_ring_pow2(); | |
| } | |
| 
 | |
| cl_class cl_class_modint_ring_pow2 = { | |
| 	cl_modint_ring_pow2_destructor, | |
| 	cl_class_flags_modint_ring | |
| }; | |
| 
 | |
| // Constructor. | |
| inline cl_heap_modint_ring_pow2::cl_heap_modint_ring_pow2 (const cl_I& m, uintL _m1) | |
| 	: cl_heap_modint_ring (m, &std_setops, &pow2_addops, &pow2_mulops), m1 (_m1) | |
| { | |
| 	type = &cl_class_modint_ring_pow2; | |
| } | |
| 
 | |
| }  // namespace cln
 |