void HSItoRGB(double H, double S, double I, int *r, int *g, int *b) { double T,Rv,Gv,Bv; Rv=1+S*sin(H-2*M_PI/3); Gv=1+S*sin(H); Bv=1+S*sin(H+2*M_PI/3); T=255.999*I/2; *r=itrunc(Rv*T); *g=itrunc(Gv*T); *b=itrunc(Bv*T); }
T cos_pi_imp(T x, const Policy& pol) { BOOST_MATH_STD_USING // ADL of std names // cos of pi*x: bool invert = false; if(x < 0.5) return cos(constants::pi<T>() * x); if(x < 1) { x = -x; } T rem = floor(x); if(itrunc(rem, pol) & 1) invert = !invert; rem = x - rem; if(rem > 0.5f) { rem = 1 - rem; invert = !invert; } if(rem == 0.5f) return 0; rem = cos(constants::pi<T>() * rem); return invert ? T(-rem) : rem; }
/* * release an inode. * decrease the reference count, write updates to disk if nessary. * also check the link count, if zero, trucate it. * */ void iput(struct inode *ip){ ushort dev; if(ip==NULL) panic("bad struct inode*"); ip->i_flag |= I_LOCK; if (ip->i_count > 0) { ip->i_count--; } if (ip->i_count==0){ if (ip->i_nlink==0) { itrunc(ip); ifree(ip->i_dev, ip->i_num); } // if it's a device file, the dev number is stored in zone[0]. dev = ip->i_zone[0]; switch (ip->i_mode & S_IFMT) { case S_IFBLK: (*bdevsw[MAJOR(dev)].d_close)(dev); break; case S_IFCHR: (*cdevsw[MAJOR(dev)].d_close)(dev); break; } iupdate(ip); ip->i_flag = 0; ip->i_num = 0; } unlk_ino(ip); }
inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) { BOOST_STATIC_ASSERT(!boost::is_integral<T>::value); BOOST_MATH_STD_USING // ADL of std names if((x == 0) && (n >= 0)) return 0; if(x < 0) { // // For x < 0 we really have a rising factorial // modulo a possible change of sign: // return (n&1 ? -1 : 1) * rising_factorial(-x, n, pol); } if(n == 0) return 1; if(x < 0.5f) { // // 1 + x below will throw away digits, so split up calculation: // if(n > max_factorial<T>::value - 2) { // If the two end of the range are far apart we have a ratio of two very large // numbers, split the calculation up into two blocks: T t1 = x * boost::math::falling_factorial(x - 1, max_factorial<T>::value - 2); T t2 = boost::math::falling_factorial(x - max_factorial<T>::value + 1, n - max_factorial<T>::value + 1); if(tools::max_value<T>() / fabs(t1) < fabs(t2)) return boost::math::sign(t1) * boost::math::sign(t2) * policies::raise_overflow_error<T>("boost::math::falling_factorial<%1%>", 0, pol); return t1 * t2; } return x * boost::math::falling_factorial(x - 1, n - 1); } if(x <= n - 1) { // // x+1-n will be negative and tgamma_delta_ratio won't // handle it, split the product up into three parts: // T xp1 = x + 1; unsigned n2 = itrunc((T)floor(xp1), pol); if(n2 == xp1) return 0; T result = boost::math::tgamma_delta_ratio(xp1, -static_cast<T>(n2), pol); x -= n2; result *= x; ++n2; if(n2 < n) result *= falling_factorial(x - 1, n - n2, pol); return result; } // // Simple case: just the ratio of two // (positive argument) gamma functions. // Note that we don't optimise this for small n, // because tgamma_delta_ratio is alreay optimised // for that use case: // return boost::math::tgamma_delta_ratio(x + 1, -static_cast<T>(n), pol); }
inline T cyl_bessel_j_prime_imp(T v, T x, const Policy& pol) { static const char* const function = "boost::math::cyl_bessel_j_prime<%1%>(%1%,%1%)"; BOOST_MATH_STD_USING // // Prevent complex result: // if (x < 0 && floor(v) != v) return boost::math::policies::raise_domain_error<T>( function, "Got x = %1%, but function requires x >= 0", x, pol); // // Special cases for x == 0: // if (x == 0) { if (v == 1) return 0.5; else if (v == -1) return -0.5; else if (floor(v) == v || v > 1) return 0; else return boost::math::policies::raise_domain_error<T>( function, "Got x = %1%, but function is indeterminate for this order", x, pol); } // // Special case for large x: use asymptotic expansion: // if (boost::math::detail::asymptotic_bessel_derivative_large_x_limit(v, x)) return boost::math::detail::asymptotic_bessel_j_derivative_large_x_2(v, x); // // Special case for small x: use Taylor series: // if ((abs(x) < 5) || (abs(v) > x * x / 4)) { bool inversed = false; if (floor(v) == v && v < 0) { v = -v; if (itrunc(v, pol) & 1) inversed = true; } T r = boost::math::detail::bessel_j_derivative_small_z_series(v, x, pol); return inversed ? T(-r) : r; } // // Special case for v == 0: // if (v == 0) return -boost::math::detail::cyl_bessel_j_imp<T>(1, x, Tag(), pol); // // Default case: // return boost::math::detail::bessel_j_derivative_linear(v, x, Tag(), pol); }
T float_advance(T val, int distance, const Policy& pol) { // // Error handling: // static const char* function = "float_advance<%1%>(%1%, int)"; if(!(boost::math::isfinite)(val)) return policies::raise_domain_error<T>( function, "Argument val must be finite, but got %1%", val, pol); if(val < 0) return -float_advance(-val, -distance, pol); if(distance == 0) return val; if(distance == 1) return float_next(val, pol); if(distance == -1) return float_prior(val, pol); BOOST_MATH_STD_USING int expon; frexp(val, &expon); T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon); if(val <= tools::min_value<T>()) { limit = sign(T(distance)) * tools::min_value<T>(); } T limit_distance = float_distance(val, limit); while(fabs(limit_distance) < abs(distance)) { distance -= itrunc(limit_distance); val = limit; if(distance < 0) { limit /= 2; expon--; } else { limit *= 2; expon++; } limit_distance = float_distance(val, limit); } if((0.5f == frexp(val, &expon)) && (distance < 0)) --expon; T diff = 0; if(val != 0) diff = distance * ldexp(T(1), expon - tools::digits<T>()); if(diff == 0) diff = distance * detail::get_smallest_value<T>(); return val += diff; }
inline RealType cdf(const complemented2_type<hypergeometric_distribution<RealType, Policy>, U>& c) { BOOST_MATH_STD_USING static const char* function = "boost::math::cdf(const hypergeometric_distribution<%1%>&, const %1%&)"; RealType r = static_cast<RealType>(c.param); unsigned u = itrunc(r, typename policies::normalise<Policy, policies::rounding_error<policies::ignore_error> >::type()); if(u != r) { return boost::math::policies::raise_domain_error<RealType>( function, "Random variable out of range: must be an integer but got %1%", r, Policy()); } return cdf(complement(c.dist, u)); }
/* * open a file. flag indicated opened type like O_RDONLY, O_TRUNC, O_CREAT and blah. And * mode only used in the O_CREAT scenary, indicated the file (inode) type. * * each proc has got one user file table(p_ofile[NOFILE]), it's each entry is also a number, * indicated the number in the system file table(file[NFILE]). when user opened a file, it * first allocate a user file table entry(aka. file descriptor), then attach it with a system * file table entry. It's reference count is increased in fork() or dup(). * */ int do_open(char *path, uint flag, uint mode){ struct inode *ip; struct file *fp; ushort dev; int fd; // on create a new file. if (flag & O_CREAT){ ip = namei(path, 1); // if file is not existing yet. if (ip->i_nlink==0) { ip->i_mode = mode; ip->i_uid = cu->p_euid; ip->i_gid = cu->p_egid; ip->i_mtime = time(); ip->i_nlink = 1; iupdate(ip); } } // an existing file. else { ip = namei(path, 0); if (ip == NULL){ syserr(ENFILE); return -1; } // TODO: check access // if it's a device file, the dev number is stored in zone[0]. dev = ip->i_zone[0]; switch(ip->i_mode & S_IFMT) { case S_IFBLK: (*bdevsw[MAJOR(dev)].d_open)(dev); break; case S_IFCHR: (*cdevsw[MAJOR(dev)].d_open)(dev); break; } } if (((fd=ufalloc())<0) || (fp=falloc(fd))==NULL) { iput(ip); return -1; } if (flag & O_TRUNC){ itrunc(ip); } unlk_ino(ip); fp->f_oflag = flag; fp->f_ino = ip; cu->p_fdflag[fd] = FD_CLOEXEC; return fd; }
/* reference of ip - 1 * if it is the last ref, this node can be recycle (ref = 1) (?) * and if this inode have no link to it (nlinks = 0) * free this inode in the disk */ void iput(struct inode *ip) { if (ip->ref == 1 && ip->flags & I_VALID && ip->nlinks == 0) { /* can not free a locked inode */ ip->flags |= I_BUSY; itrunc(ip); _ifree(ip->dev, ip->ino); // ip-> ref == 0 // ip->flags = 0; } ip->ref--; }
T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos& l) { static const char* function = "boost::math::tgamma<%1%>(%1%)"; BOOST_MATH_STD_USING if((z <= 0) && (floor(z) == z)) return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol); if(z <= -20) { T result = gamma_imp(-z, pol, l) * sinpx(z); if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>())) return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol); result = -boost::math::constants::pi<T>() / result; if(result == 0) return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol); if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL) return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", result, pol); return result; } // // The upper gamma fraction is *very* slow for z < 6, actually it's very // slow to converge everywhere but recursing until z > 6 gets rid of the // worst of it's behaviour. // T prefix = 1; while(z < 6) { prefix /= z; z += 1; } BOOST_MATH_INSTRUMENT_CODE(prefix); if((floor(z) == z) && (z < max_factorial<T>::value)) { prefix *= unchecked_factorial<T>(itrunc(z, pol) - 1); } else { prefix = prefix * pow(z / boost::math::constants::e<T>(), z); BOOST_MATH_INSTRUMENT_CODE(prefix); T sum = detail::lower_gamma_series(z, z, pol) / z; BOOST_MATH_INSTRUMENT_CODE(sum); sum += detail::upper_gamma_fraction(z, z, ::boost::math::policies::digits<T, Policy>()); BOOST_MATH_INSTRUMENT_CODE(sum); if(fabs(tools::max_value<T>() / prefix) < fabs(sum)) return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol); BOOST_MATH_INSTRUMENT_CODE((sum * prefix)); return sum * prefix; } return prefix; }
/* * Drop a reference to an in-memory inode. If that was the last reference, the * inode cache entry can be recycled. * * If that was the last reference and the inode has no links to it, free the * inode (and its content) on disk. */ void iput(struct inode *ip) { acquire(&icache.lock); if (ip->ref == 1 && (ip->flags & I_VALID) && ip->nlink == 0) { /* inode has no links: truncate and free inode. */ if (ip->flags & I_BUSY) panic("iput busy"); ip->flags |= I_BUSY; release(&icache.lock); itrunc(ip); ip->type = 0; iupdate(ip); acquire(&icache.lock); ip->flags = 0; wakeup(ip); } ip->ref--; release(&icache.lock); }
inline T falling_factorial_imp(T x, unsigned n, const Policy& pol) { BOOST_STATIC_ASSERT(!lslboost::is_integral<T>::value); BOOST_MATH_STD_USING // ADL of std names if(x == 0) return 0; if(x < 0) { // // For x < 0 we really have a rising factorial // modulo a possible change of sign: // return (n&1 ? -1 : 1) * rising_factorial(-x, n, pol); } if(n == 0) return 1; if(x < n-1) { // // x+1-n will be negative and tgamma_delta_ratio won't // handle it, split the product up into three parts: // T xp1 = x + 1; unsigned n2 = itrunc((T)floor(xp1), pol); if(n2 == xp1) return 0; T result = lslboost::math::tgamma_delta_ratio(xp1, -static_cast<T>(n2), pol); x -= n2; result *= x; ++n2; if(n2 < n) result *= falling_factorial(x - 1, n - n2, pol); return result; } // // Simple case: just the ratio of two // (positive argument) gamma functions. // Note that we don't optimise this for small n, // because tgamma_delta_ratio is alreay optimised // for that use case: // return lslboost::math::tgamma_delta_ratio(x + 1, -static_cast<T>(n), pol); }
// Drop a reference to an in-memory inode. // If that was the last reference, the inode cache entry can // be recycled. // If that was the last reference and the inode has no links // to it, free the inode (and its content) on disk. // All calls to iput() must be inside a transaction in // case it has to free the inode. void iput(struct inode* ip) { // cprintf("iput %d \n",ip->inum); acquire(&icache.lock); if (ip->ref == 1 && (ip->flags & I_VALID) && ip->nlink == 0) { // inode has no links and no other references: truncate and free. if (ip->flags & I_BUSY) panic("iput busy"); ip->flags |= I_BUSY; release(&icache.lock); itrunc(ip); ip->type = 0; iupdate(ip); acquire(&icache.lock); ip->flags = 0; wakeup(ip); } ip->ref--; release(&icache.lock); }
T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val) { BOOST_MATH_STD_USING // // Variables come first: // boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); T errtol = policies::get_epsilon<T, Policy>(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the // maximum of the poisson weighting term, we don't // ever allow k == 0 as this can lead to catastrophic // cancellation errors later (test case is v = 1621286869049072.3 // delta = 0.16212868690490723, x = 0.86987415482475994). // int k = itrunc(d2); T pois; if(k == 0) k = 1; // Starting Poisson weight: pois = gamma_p_derivative(T(k+1), d2, pol) * tgamma_delta_ratio(T(k + 1), T(0.5f)) * delta / constants::root_two<T>(); if(pois == 0) return init_val; T xterm, beta; // Recurrance & starting beta terms: beta = x < y ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm) : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm); xterm *= y / (v / 2 + k); T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((xterm == 0) && (beta == 0)) return init_val; // // Backwards recursion first, this is the stable // direction for recursion: // boost::uintmax_t count = 0; T last_term = 0; for(int i = k; i >= 0; --i) { T term = beta * pois; sum += term; // Don't terminate on first term in case we "fixed" k above: if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) break; last_term = term; pois *= (i + 0.5f) / d2; beta += xterm; xterm *= (i) / (x * (v / 2 + i - 1)); ++count; } last_term = 0; for(int i = k + 1; ; ++i) { poisf *= d2 / (i + 0.5f); xtermf *= (x * (v / 2 + i - 1)) / (i); betaf -= xtermf; T term = poisf * betaf; sum += term; if((fabs(last_term) > fabs(term)) && (fabs(term/sum) < errtol)) break; last_term = term; ++count; if(count > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } } return sum; }
T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val) { BOOST_MATH_STD_USING // // Variables come first: // boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>(); T errtol = boost::math::policies::get_epsilon<T, Policy>(); T d2 = delta * delta / 2; // // k is the starting point for iteration, and is the // maximum of the poisson weighting term, we don't allow // k == 0 as this can cause catastrophic cancellation errors // (test case is v = 561908036470413.25, delta = 0.056190803647041321, // x = 1.6155232703966216): // int k = itrunc(d2); if(k == 0) k = 1; // Starting Poisson weight: T pois; if((k < (int)(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>())) { // // For small k we can optimise this calculation by using // a simpler reduced formula: // pois = exp(-d2); pois *= pow(d2, static_cast<T>(k)); pois /= boost::math::tgamma(T(k + 1 + 0.5), pol); pois *= delta / constants::root_two<T>(); } else { pois = gamma_p_derivative(T(k+1), d2, pol) * tgamma_delta_ratio(T(k + 1), T(0.5f)) * delta / constants::root_two<T>(); } if(pois == 0) return init_val; // Recurance term: T xterm; T beta; // Starting beta term: if(k != 0) { beta = x < y ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm) : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm); xterm *= y / (v / 2 + k); } else { beta = pow(y, v / 2); xterm = beta; } T poisf(pois), betaf(beta), xtermf(xterm); T sum = init_val; if((xterm == 0) && (beta == 0)) return init_val; // // Fused forward and backwards recursion: // boost::uintmax_t count = 0; T last_term = 0; for(int i = k + 1, j = k; ; ++i, --j) { poisf *= d2 / (i + 0.5f); xtermf *= (x * (v / 2 + i - 1)) / (i); betaf += xtermf; T term = poisf * betaf; if(j >= 0) { term += beta * pois; pois *= (j + 0.5f) / d2; beta -= xterm; xterm *= (j) / (x * (v / 2 + j - 1)); } sum += term; // Don't terminate on first term in case we "fixed" the value of k above: if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) break; last_term = term; if(count > max_iter) { return policies::raise_evaluation_error( "cdf(non_central_t_distribution<%1%>, %1%)", "Series did not converge, closest value was %1%", sum, pol); } ++count; } return sum; }
inline T modf(const T& v, int* ipart, const Policy& pol) { *ipart = itrunc(v, pol); return v - *ipart; }
inline int itrunc(const T& v) { return itrunc(v, policies::policy<>()); }
inline int itrunc(__gmp_expr<T,U> const& x, const Policy& pol) { return itrunc(static_cast<mpfr_class>(x), pol); }
T float_advance(T val, int distance, const Policy& pol) { BOOST_MATH_STD_USING // // Error handling: // static const char* function = "float_advance<%1%>(%1%, int)"; int fpclass = (pdalboost::math::fpclassify)(val); if((fpclass == FP_NAN) || (fpclass == FP_INFINITE)) return policies::raise_domain_error<T>( function, "Argument val must be finite, but got %1%", val, pol); if(val < 0) return -float_advance(-val, -distance, pol); if(distance == 0) return val; if(distance == 1) return float_next(val, pol); if(distance == -1) return float_prior(val, pol); if(fabs(val) < detail::get_min_shift_value<T>()) { // // Special case: if the value of the least significant bit is a denorm, // implement in terms of float_next/float_prior. // This avoids issues with the Intel SSE2 registers when the FTZ or DAZ flags are set. // if(distance > 0) { do{ val = float_next(val, pol); } while(--distance); } else { do{ val = float_prior(val, pol); } while(++distance); } return val; } int expon; frexp(val, &expon); T limit = ldexp((distance < 0 ? T(0.5f) : T(1)), expon); if(val <= tools::min_value<T>()) { limit = sign(T(distance)) * tools::min_value<T>(); } T limit_distance = float_distance(val, limit); while(fabs(limit_distance) < abs(distance)) { distance -= itrunc(limit_distance); val = limit; if(distance < 0) { limit /= 2; expon--; } else { limit *= 2; expon++; } limit_distance = float_distance(val, limit); if(distance && (limit_distance == 0)) { policies::raise_evaluation_error<T>(function, "Internal logic failed while trying to increment floating point value %1%: most likely your FPU is in non-IEEE conforming mode.", val, pol); } } if((0.5f == frexp(val, &expon)) && (distance < 0)) --expon; T diff = 0; if(val != 0) diff = distance * ldexp(T(1), expon - tools::digits<T>()); if(diff == 0) diff = distance * detail::get_smallest_value<T>(); return val += diff; }
T gamma_imp(T z, const Policy& pol, const L& l) { BOOST_MATH_STD_USING T result = 1; #ifdef BOOST_MATH_INSTRUMENT static bool b = false; if(!b) { std::cout << "tgamma_imp called with " << typeid(z).name() << " " << typeid(l).name() << std::endl; b = true; } #endif static const char* function = "boost::math::tgamma<%1%>(%1%)"; if(z <= 0) { if(floor(z) == z) return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol); if(z <= -20) { result = gamma_imp(-z, pol, l) * sinpx(z); if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>())) return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol); result = -boost::math::constants::pi<T>() / result; if(result == 0) return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol); if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL) return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", result, pol); return result; } // shift z to > 1: while(z < 0) { result /= z; z += 1; } } if((floor(z) == z) && (z < max_factorial<T>::value)) { result *= unchecked_factorial<T>(itrunc(z, pol) - 1); } else { result *= L::lanczos_sum(z); if(z * log(z) > tools::log_max_value<T>()) { // we're going to overflow unless this is done with care: T zgh = (z + static_cast<T>(L::g()) - boost::math::constants::half<T>()); if(log(zgh) * z / 2 > tools::log_max_value<T>()) return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol); T hp = pow(zgh, (z / 2) - T(0.25)); result *= hp / exp(zgh); if(tools::max_value<T>() / hp < result) return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol); result *= hp; } else { T zgh = (z + static_cast<T>(L::g()) - boost::math::constants::half<T>()); result *= pow(zgh, z - boost::math::constants::half<T>()) / exp(zgh); } } return result; }