inline static VALUE f_divide(VALUE self, VALUE other, VALUE (*func)(VALUE, VALUE), ID id) { if (k_complex_p(other)) { int flo; get_dat2(self, other); flo = (k_float_p(adat->real) || k_float_p(adat->imag) || k_float_p(bdat->real) || k_float_p(bdat->imag)); if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) { VALUE r, n; r = (*func)(bdat->imag, bdat->real); n = f_mul(bdat->real, f_add(ONE, f_mul(r, r))); if (flo) return f_complex_new2(CLASS_OF(self), (*func)(self, n), (*func)(f_negate(f_mul(self, r)), n)); return f_complex_new2(CLASS_OF(self), (*func)(f_add(adat->real, f_mul(adat->imag, r)), n), (*func)(f_sub(adat->imag, f_mul(adat->real, r)), n)); } else { VALUE r, n; r = (*func)(bdat->real, bdat->imag); n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r))); if (flo) return f_complex_new2(CLASS_OF(self), (*func)(f_mul(self, r), n), (*func)(f_negate(self), n)); return f_complex_new2(CLASS_OF(self), (*func)(f_add(f_mul(adat->real, r), adat->imag), n), (*func)(f_sub(f_mul(adat->imag, r), adat->real), n)); } } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), (*func)(dat->real, other), (*func)(dat->imag, other)); } return rb_num_coerce_bin(self, other, id); }
inline static VALUE f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k) { VALUE num, den; if (FIXNUM_P(anum) && FIXNUM_P(aden) && FIXNUM_P(bnum) && FIXNUM_P(bden)) { long an = FIX2LONG(anum); long ad = FIX2LONG(aden); long bn = FIX2LONG(bnum); long bd = FIX2LONG(bden); long ig = i_gcd(ad, bd); VALUE g = LONG2NUM(ig); VALUE a = f_imul(an, bd / ig); VALUE b = f_imul(bn, ad / ig); VALUE c; if (k == '+') c = f_add(a, b); else c = f_sub(a, b); b = f_idiv(aden, g); g = f_gcd(c, g); num = f_idiv(c, g); a = f_idiv(bden, g); den = f_mul(a, b); } else { VALUE g = f_gcd(aden, bden); VALUE a = f_mul(anum, f_idiv(bden, g)); VALUE b = f_mul(bnum, f_idiv(aden, g)); VALUE c; if (k == '+') c = f_add(a, b); else c = f_sub(a, b); b = f_idiv(aden, g); g = f_gcd(c, g); num = f_idiv(c, g); a = f_idiv(bden, g); den = f_mul(a, b); } return f_rational_new_no_reduce2(CLASS_OF(self), num, den); }
/* evaluate an expression, eval_err will indicate it any expression evaluation occurs */ static struct eval_value_t /* value of the expression */ expr(struct eval_state_t *es) /* expression evaluator */ { enum eval_token_t tok; struct eval_value_t val; val = term(es); if (eval_error) return err_value; tok = peek_next_token(es); switch (tok) { case tok_plus: (void)get_next_token(es); val = f_add(val, expr(es)); if (eval_error) return err_value; break; case tok_minus: (void)get_next_token(es); val = f_sub(val, expr(es)); if (eval_error) return err_value; break; default:; } return val; }
/* * call-seq: * cmp * numeric -> complex * * Performs multiplication. * * Complex(2, 3) * Complex(2, 3) #=> (-5+12i) * Complex(900) * Complex(1) #=> (900+0i) * Complex(-2, 9) * Complex(-9, 2) #=> (0-85i) * Complex(9, 8) * 4 #=> (36+32i) * Complex(20, 9) * 9.8 #=> (196.0+88.2i) */ VALUE rb_nucomp_mul(VALUE self, VALUE other) { if (k_complex_p(other)) { VALUE real, imag; VALUE areal, aimag, breal, bimag; int arzero, aizero, brzero, bizero; get_dat2(self, other); arzero = !!f_zero_p(areal = adat->real); aizero = !!f_zero_p(aimag = adat->imag); brzero = !!f_zero_p(breal = bdat->real); bizero = !!f_zero_p(bimag = bdat->imag); real = f_sub(safe_mul(areal, breal, arzero, brzero), safe_mul(aimag, bimag, aizero, bizero)); imag = f_add(safe_mul(areal, bimag, arzero, bizero), safe_mul(aimag, breal, aizero, brzero)); return f_complex_new2(CLASS_OF(self), real, imag); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_mul(dat->real, other), f_mul(dat->imag, other)); } return rb_num_coerce_bin(self, other, '*'); }
/* * call-seq: * rat - numeric -> numeric_result * * Performs subtraction. * * For example: * * Rational(2, 3) - Rational(2, 3) #=> (0/1) * Rational(900) - Rational(1) #=> (899/1) * Rational(-2, 9) - Rational(-9, 2) #=> (77/18) * Rational(9, 8) - 4 #=> (23/8) * Rational(20, 9) - 9.8 #=> -7.577777777777778 */ static VALUE nurat_sub(VALUE self, SEL sel, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: { get_dat1(self); return f_addsub(self, dat->num, dat->den, other, ONE, '-'); } case T_FLOAT: return f_sub(f_to_f(self), other); case T_RATIONAL: { get_dat2(self, other); return f_addsub(self, adat->num, adat->den, bdat->num, bdat->den, '-'); } default: return rb_num_coerce_bin(self, other, '-'); } }
/* * This is the core of secret sharing. This computes the coefficients * used in Lagrange polynomial interpolation, returning the * vector of logarithms of b1(xtarget), b2(xtarget), ..., bn(xtarget). * Takes values from the "xCoordinate" header element, inserts the * results in the "lagrange" header element. * The interpolation values come from the headers of the "shares" array, * plus one additional value, xInput, which is the value we are going * to interpolate to. * * Returns kPGPError_OK on success, error if not all x[i] are unique. */ static PGPError sInterp(PGPByte *shares, PGPSize bodySize, PGPByte xInput, PGPUInt32 nShares) { PGPUInt32 i, j; PGPByte xi, xj; PGPUInt32 numer, denom; #if !PGP_STATIC_SHAMIR_ARRAYS s_FSetup(); #endif /* !PGP_STATIC_SHAMIR_ARRAYS */ /* First, accumulate the numerator, Prod(xInput-x[i],i=0..n) */ numer = 0; for (i = 0; i < nShares; i++) { xi = HEADER(shares,bodySize,i)->xCoordinate; numer += f_log[ f_sub(xi, xInput) ]; } /* Preliminary partial reduction */ numer = (numer%FIELD_SIZE) + (numer/FIELD_SIZE); /* Then, for each coefficient, compute the corresponding denominator */ for (i = 0; i < nShares; i++) { xi = HEADER(shares,bodySize,i)->xCoordinate; denom = 0; for (j = 0; j < nShares; j++) { xj = (i == j) ? xInput : HEADER(shares,bodySize,j)->xCoordinate; if (xi == xj) return -1; denom += f_log[f_sub(xi,xj)]; } denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE); /* 0 <= denom < 2*FIELD_SIZE-1. */ /* Now find numer/denom. In log form, that's a subtract. */ denom = numer + 2*FIELD_SIZE-2 - denom; denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE); denom = (denom%FIELD_SIZE)+(denom/FIELD_SIZE); HEADER(shares,bodySize,i)->lagrange = (PGPByte)denom; } return kPGPError_NoErr; /* Success */ }
static VALUE nucomp_sub(VALUE self, VALUE other) { if (k_complex_p(other)) { VALUE real, imag; get_dat2(self, other); real = f_sub(adat->real, bdat->real); imag = f_sub(adat->imag, bdat->imag); return f_complex_new2(CLASS_OF(self), real, imag); } if (k_numeric_p(other) && f_real_p(other)) { get_dat1(self); return f_complex_new2(CLASS_OF(self), f_sub(dat->real, other), dat->imag); } return rb_num_coerce_bin(self, other, '-'); }
inline static VALUE nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag) { #ifdef CANON #define CL_CANON #ifdef CL_CANON if (k_exact_zero_p(imag) && canonicalization) return real; #else if (f_zero_p(imag) && canonicalization) return real; #endif #endif if (f_real_p(real) && f_real_p(imag)) return nucomp_s_new_internal(klass, real, imag); else if (f_real_p(real)) { get_dat1(imag); return nucomp_s_new_internal(klass, f_sub(real, dat->imag), f_add(ZERO, dat->real)); } else if (f_real_p(imag)) { get_dat1(real); return nucomp_s_new_internal(klass, dat->real, f_add(dat->imag, imag)); } else { get_dat2(real, imag); return nucomp_s_new_internal(klass, f_sub(adat->real, bdat->imag), f_add(adat->imag, bdat->real)); } }
static VALUE m_sqrt(VALUE x) { if (f_real_p(x)) { if (f_positive_p(x)) return m_sqrt_bang(x); return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x))); } else { get_dat1(x); if (f_negative_p(dat->imag)) return f_conj(m_sqrt(f_conj(x))); else { VALUE a = f_abs(x); return f_complex_new2(rb_cComplex, m_sqrt_bang(f_div(f_add(a, dat->real), TWO)), m_sqrt_bang(f_div(f_sub(a, dat->real), TWO))); } } }
static VALUE nurat_cmp(VALUE self, VALUE other) { switch (TYPE(other)) { case T_FIXNUM: case T_BIGNUM: { get_dat1(self); if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1) return f_cmp(dat->num, other); else return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other)); } case T_FLOAT: return f_cmp(f_to_f(self), other); case T_RATIONAL: { VALUE num1, num2; get_dat2(self, other); if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) && FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) { num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den)); num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den)); } else { num1 = f_mul(adat->num, bdat->den); num2 = f_mul(bdat->num, adat->den); } return f_cmp(f_sub(num1, num2), ZERO); } default: return rb_num_coerce_bin(self, other, id_cmp); } }
/* * call-seq: * cmp ** numeric -> complex * * Performs exponentiation. * * Complex('i') ** 2 #=> (-1+0i) * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i) */ static VALUE nucomp_expt(VALUE self, VALUE other) { if (k_numeric_p(other) && k_exact_zero_p(other)) return f_complex_new_bang1(CLASS_OF(self), ONE); if (k_rational_p(other) && f_one_p(f_denominator(other))) other = f_numerator(other); /* c14n */ if (k_complex_p(other)) { get_dat1(other); if (k_exact_zero_p(dat->imag)) other = dat->real; /* c14n */ } if (k_complex_p(other)) { VALUE r, theta, nr, ntheta; get_dat1(other); r = f_abs(self); theta = f_arg(self); nr = m_exp_bang(f_sub(f_mul(dat->real, m_log_bang(r)), f_mul(dat->imag, theta))); ntheta = f_add(f_mul(theta, dat->real), f_mul(dat->imag, m_log_bang(r))); return f_complex_polar(CLASS_OF(self), nr, ntheta); } if (k_fixnum_p(other)) { if (f_gt_p(other, ZERO)) { VALUE x, z; long n; x = self; z = x; n = FIX2LONG(other) - 1; while (n) { long q, r; while (1) { get_dat1(x); q = n / 2; r = n % 2; if (r) break; x = nucomp_s_new_internal(CLASS_OF(self), f_sub(f_mul(dat->real, dat->real), f_mul(dat->imag, dat->imag)), f_mul(f_mul(TWO, dat->real), dat->imag)); n = q; } z = f_mul(z, x); n--; } return z; } return f_expt(f_reciprocal(self), f_negate(other)); } if (k_numeric_p(other) && f_real_p(other)) { VALUE r, theta; if (k_bignum_p(other)) rb_warn("in a**b, b may be too big"); r = f_abs(self); theta = f_arg(self); return f_complex_polar(CLASS_OF(self), f_expt(r, other), f_mul(theta, other)); } return rb_num_coerce_bin(self, other, id_expt); }
int main(int argc, char** argv) { double lambda = atof(argv[2]); int N = atoi(argv[1]); double crude_mc,variance; crude_mc=0; double g_sigma = 0; int num_cores = 0; #if 0 double start = clock(); #pragma omp parallel { double l_sum = 0; double r1,r2,theta1,theta2,phi1,phi2; double fx = 0; double sum_sigma = 0; long idum1,idum2,idum3,idum4,idum5,idum6; idum1 = time(0)-123; idum2 = time(0)-383;idum3 = time(0)-73;idum4 = time(0)-239; idum5 = time(0)-830;idum6 = time(0)-955; #pragma omp for for(int i=0;i<N;i++){ r1 = lambda*ran0(&idum1); r2 = lambda*ran0(&idum2); theta1 = PI*ran0(&idum3); theta2 = PI*ran0(&idum4); phi1 = 2*PI*ran0(&idum5); phi2 = 2*PI*ran0(&idum6); fx = r1*r1*r2*r2*f_sub(r1,r2,theta1,theta2,phi1,phi2)*exp(-4*(r1+r2)); l_sum += fx; sum_sigma += fx*fx; } #pragma omp critical {crude_mc += l_sum; g_sigma += sum_sigma;num_cores = omp_get_num_threads();} } double stop = clock(); double diff = timediff(start,stop)*0.25; /* double var = ((pow(PI,4)*lambda*lambda*4)/N)*(g_sigma-((pow(PI,4)*lambda*lambda*4)/N)*crude_mc*crude_mc); cout<<"test: "<<var<<" sdv: "<<sqrt(var)<<" comparisson: "<<var/sqrt(N)<<endl;*/ crude_mc /= ((double) N); g_sigma /= ((double) N); variance = g_sigma - crude_mc*crude_mc; crude_mc *= lambda*lambda*4*pow(PI,4); cout<<"Monte Carlo simulation with N = "<<N<<" gives "<<crude_mc<<endl; cout<<"The variance is "<<variance<<" and standard deviation "<<sqrt(variance)<<endl; cout<<"This took "<<diff<<" ms on "<<num_cores<<" cores"<<endl; #else double start = clock(); #pragma omp parallel { /*Set up private variables for the paralell execution of this loop*/ double l_sum = 0; double l_sum2 = 0; double r1,r2,theta1,theta2,phi1,phi2; double fx = 0; double sum_sigma = 0; double sum_sigma2 = 0; long idum1,idum2,idum3,idum4,idum5,idum6; idum1 = time(0)-123; idum2 = time(0)-383;idum3 = time(0)-73;idum4 = time(0)-239; idum5 = time(0)-830;idum6 = time(0)-955; #pragma omp for for(int i=0;i<N;i++){ r1 = -log(1-ran0(&idum1)); r2 = -log(1-ran0(&idum2)); theta1 = PI*ran0(&idum3); theta2 = PI*ran0(&idum4); phi1 = 2*PI*ran0(&idum5); phi2 = 2*PI*ran0(&idum6); fx = (1./1024)*r1*r1*r2*r2*f_sub(r1,r2,theta1,theta2,phi1,phi2); if (l_sum > 1e4){ l_sum2 +=fx; sum_sigma2 +=fx*fx; } else{ l_sum += fx; sum_sigma += fx*fx; } } #pragma omp critical { crude_mc +=l_sum+l_sum2; g_sigma += sum_sigma+sum_sigma2; num_cores = omp_get_num_threads(); } } double stop = clock(); double diff = timediff(start,stop)*0.25; crude_mc /= ((double) N); g_sigma /= ((double) N); variance = g_sigma - crude_mc*crude_mc; crude_mc *= 4*pow(PI,4); cout<<"Monte Carlo simulation with (importance sampling) N = "<<N<<" gives "<<crude_mc<<endl; cout<<"correct result: "<<5*PI*PI/(16*16)<<endl; cout<<"The variance is "<<variance<<" and standard deviation "<<pow(4,PI)*sqrt(variance/((double) N))<<endl; cout<<"This took "<<diff<<" ms on "<<num_cores<<" cores"<<endl; #endif return 0; }
static VALUE nucomp_expt(VALUE self, VALUE other) { if (k_exact_p(other) && f_zero_p(other)) return f_complex_new_bang1(CLASS_OF(self), ONE); if (k_rational_p(other) && f_one_p(f_denominator(other))) other = f_numerator(other); /* good? */ if (k_complex_p(other)) { VALUE a, r, theta, ore, oim, nr, ntheta; get_dat1(other); a = f_polar(self); r = RARRAY_PTR(a)[0]; theta = RARRAY_PTR(a)[1]; ore = dat->real; oim = dat->imag; nr = m_exp_bang(f_sub(f_mul(ore, m_log_bang(r)), f_mul(oim, theta))); ntheta = f_add(f_mul(theta, ore), f_mul(oim, m_log_bang(r))); return f_complex_polar(CLASS_OF(self), nr, ntheta); } if (k_integer_p(other)) { if (f_gt_p(other, ZERO)) { VALUE x, z, n; x = self; z = x; n = f_sub(other, ONE); while (f_nonzero_p(n)) { VALUE a; while (a = f_divmod(n, TWO), f_zero_p(RARRAY_PTR(a)[1])) { get_dat1(x); x = f_complex_new2(CLASS_OF(self), f_sub(f_mul(dat->real, dat->real), f_mul(dat->imag, dat->imag)), f_mul(f_mul(TWO, dat->real), dat->imag)); n = RARRAY_PTR(a)[0]; } z = f_mul(z, x); n = f_sub(n, ONE); } return z; } return f_expt(f_div(f_to_r(ONE), self), f_negate(other)); } if (k_numeric_p(other) && f_real_p(other)) { VALUE a, r, theta; a = f_polar(self); r = RARRAY_PTR(a)[0]; theta = RARRAY_PTR(a)[1]; return f_complex_polar(CLASS_OF(self), f_expt(r, other), f_mul(theta, other)); } return rb_num_coerce_bin(self, other, id_expt); }
/* :nodoc: */ static VALUE nurat_quotrem(VALUE self, VALUE other) { VALUE val = f_truncate(f_div(self, other)); return rb_assoc_new(val, f_sub(self, f_mul(other, val))); }
static VALUE nurat_rem(VALUE self, VALUE other) { VALUE val = f_truncate(f_div(self, other)); return f_sub(self, f_mul(other, val)); }
static VALUE nurat_divmod(VALUE self, VALUE other) { VALUE val = f_floor(f_div(self, other)); return rb_assoc_new(val, f_sub(self, f_mul(other, val))); }
static VALUE nurat_mod(VALUE self, VALUE other) { VALUE val = f_floor(f_div(self, other)); return f_sub(self, f_mul(other, val)); }