⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rmath.cc

📁 TGFF省城程序
💻 CC
字号:
// Copyright 2000 by Robert Dick.// All rights reserved.#include "RMath.h"#include "Epsilon.h"#include "RAlgo.h"#include "RGen.h"#include "RString.h"#include <typeinfo>#include <cstddef>#include <set>#include <iostream>/*###########################################################################*/namespace rstd {using namespace std;namespace{unsigned gcd(unsigned m, unsigned n) {	unsigned t;	do {		t = n % m;		n = m;		m = t;	} while (m);	return n;}bool finite(double x) {	return x <= numeric_limits<double>::max() &&		x >= -numeric_limits<double>::max();}}/*===========================================================================*/double pdf_triangle(double urv01_a, double urv01_b, double slope) {	Rassert(slope >= 0.0 && slope <= 1.0);	slope = slope / 2.0 + 0.5;	double g = abs(urv01_a - 0.5 + urv01_b - 0.5) / slope;	if (g >= 1.0) {// Inverse map the tail back on itself.		double range = 1.0 / slope - 1;		g = 1.0 - (g - 1.0) / range;	}// Clean it up.	g = max(g, 0.0);	g = min(g, 1.0 - numeric_limits<double>::epsilon());	RASSERT(g < 1.0);	return g;}/*===========================================================================*/static double lcm(double i, double j, double ref) {	if (eps_is_equal_to(i, j, ref)) {		return i;	}	RASSERT(i < j);	unsigned i_mul = 1;	unsigned j_mul = 2;	double i_prod = i;	double j_prod = j;	do {		if (i_prod < j_prod) {			unsigned old_i_mul = i_mul;			i_mul = static_cast<unsigned>(floor(j_prod / i));			if (old_i_mul == i_mul) ++i_mul;			i_prod = i_mul * i;		} else {			unsigned old_j_mul = j_mul;			j_mul = static_cast<unsigned>(floor(i_prod / j));			if (old_j_mul == j_mul) ++j_mul;			j_prod = j_mul * j;		}	} while (! eps_is_equal_to(i_prod, j_prod, ref));	return i_prod;}/*===========================================================================*/static inline double gcd(double m, double n, double ref) {	return (m * n) / lcm(m, n, ref);}/*===========================================================================*/static inline unsigned lcm(unsigned i, unsigned j) {	return (i * j) / gcd(i, j);}/*===========================================================================*/unsigned lcm(const RVector<unsigned> & num) {	set<unsigned> srt(num.begin(), num.end());	while (srt.size() > 1) {		unsigned a = * srt.begin();		set<unsigned>::iterator beg = srt.begin();		srt.erase(beg);		unsigned b = * srt.begin();		srt.erase(srt.begin());		unsigned c = lcm(a, b);		srt.insert(c);	}	return * srt.begin();}/*===========================================================================*/double lcm(const RVector<double> & num, double ref) {	set<double> srt(num.begin(), num.end());	while (srt.size() > 1) {		double a = * srt.begin();		set<double>::iterator beg = srt.begin();		srt.erase(beg);		double b = * srt.begin();		srt.erase(srt.begin());		double c = lcm(a, b, ref);		srt.insert(c);	}	return * srt.begin();}/*===========================================================================*/unsigned gcd(const RVector<unsigned> & num) {	set<unsigned> srt(num.begin(), num.end());	while (srt.size() > 1) {		unsigned a = * srt.begin();		srt.erase(srt.begin());		unsigned b = * srt.begin();		srt.erase(srt.begin());		unsigned c = gcd(a, b);		srt.insert(c);	}	return * srt.begin();}/*===========================================================================*/double gcd(const RVector<double> & num, double ref) {	set<double> srt(num.begin(), num.end());	while (srt.size() > 1) {		double a = * srt.begin();		srt.erase(srt.begin());		double b = * srt.begin();		srt.erase(srt.begin());		double c = gcd(a, b, ref);		srt.insert(c);	}	return * srt.begin();}/*===========================================================================*/doubleflat_merge(double alpha, const double a, const double b) {/* Takes the integral of the convolution of the PDFs of the URV probabilitydistributions of a and b and maps the output back to a URV after a weightedcombination.  See written documentation. */	RASSERT(alpha >= 0.0 && alpha <= 1.0);	double beta = 1.0 - alpha;	if (alpha > beta) swap(alpha, beta);	RASSERT(a >= -1.0 && a <= 1.0);	RASSERT(b >= -1.0 && b <= 1.0);	double raw_merge = alpha * a + beta * b;	const double neg = raw_merge < 0.0 ? -1.0 : 1.0;	raw_merge = fabs(raw_merge);	const double height = 1.0 / (1.0 - alpha);	double mrg = numeric_limits<double>::max();	if (raw_merge <= 1.0 - 2.0 * alpha) {		mrg = height * raw_merge;	} else {		const double inner = (raw_merge - 1.0) * (raw_merge - 1.0);		mrg = height * alpha - (height * inner) / (4.0 * alpha) +			height * (1.0 - 2.0 * alpha);	}	RASSERT(mrg >= 0.0 && mrg <= 1.0);	return mrg * neg;}/*###########################################################################*/bool boltzmann_trial(double old_rank, double new_rank, double temperature,RGen & rgen) {	double cut = rgen.flat_range_d(0.0, 1.0);	if (! temperature) {		return new_rank > old_rank;	}	RASSERT(temperature);	return 1.0 / (1.0 + exp((new_rank - old_rank) / temperature)) < cut;}/*===========================================================================*/bool boltzmann_trial(double old_rank, double new_rank, double temperature) {	return boltzmann_trial(old_rank, new_rank, temperature, RGen::gen());}/*===========================================================================*/bool boltzmann_trial_range01(double old_rank, double new_rank,double temperature01, RGen & rgen) {	RASSERT(temperature01 >= 0.0);	const double temp_0_inf = temperature01 ?		(1.0 / (1.0 - temperature01)) - 1.0: numeric_limits<double>::max();	return boltzmann_trial(old_rank, new_rank, temp_0_inf, rgen);}/*===========================================================================*/bool boltzmann_trial_range01(double old_rank, double new_rank,double temperature01) {	return boltzmann_trial_range01(old_rank, new_rank, temperature01,		RGen::gen());}/*###########################################################################*/MathVecMathVec::operator-=(const MathVec & a) {	MAP(x, size()) (*this)[x] -= a[x];	return *this;}/*===========================================================================*/MathVecMathVec::operator-=(const value_type & a) {	MAP(x, size()) (*this)[x] -= a;	return *this;}/*===========================================================================*/MathVecMathVec::operator+=(const MathVec & a) {	MAP(x, size()) (*this)[x] += a[x];	return *this;}/*===========================================================================*/MathVecMathVec::operator+=(const value_type & a) {	MAP(x, size()) (*this)[x] += a;	return *this;}/*===========================================================================*/MathVecMathVec::operator/=(const MathVec & a) {	MAP(x, size()) (*this)[x] /= a[x];	return *this;}/*===========================================================================*/MathVecMathVec::operator/=(const value_type & a) {	MAP(x, size()) (*this)[x] /= a;	return *this;}/*===========================================================================*/MathVec &MathVec::flat_mul(const MathVec & a) {	MAP(x, size()) (*this)[x] *= a[x];	return *this;}/*===========================================================================*/MathVec &MathVec::flat_mul(const value_type & a) {	MAP(x, size()) (*this)[x] *= a;	return *this;}/*===========================================================================*/MathVec &MathVec::random_dir(value_type magnitude, RGen & rg) {	bool all_zero = true;	MAP(x, size()) {		(*this)[x] = rg.gauss_mean_d(0.0, 1.0);		if ((*this)[x])			all_zero = false;	}	if (all_zero) {// Do it the slow but certain way.		MAP(x, size()) {			if (rg.flip()) {				(*this)[x] = max(numeric_limits<double>::min(),					rg.gauss_mean_half_d(0.0, 1.0));			} else {				(*this)[x] = min(-numeric_limits<double>::min(),					-rg.gauss_mean_half_d(0.0, 1.0));			}		}	}	normalize(magnitude);	return * this;}/*===========================================================================*/MathVec &MathVec::random_dir(value_type magnitude) {	return random_dir(magnitude, RGen::gen());}/*===========================================================================*/MathVec &MathVec::random_pos(value_type radius, RGen & rg) {	double ln = rg.flat_range_d(0.0, 1.0);	return random_dir(pow(ln, size() - 1.0) * radius);}/*===========================================================================*/MathVec &MathVec::random_pos(value_type radius) {	return random_pos(radius, RGen::gen());}/*===========================================================================*/MathVec &MathVec::normalize(value_type magnitude) {	value_type this_mag = mag();	value_type m = magnitude / this_mag;	if (finite(m)) {		MAP(i, size()) (*this)[i] *= m;	} else {		string printed;		MAP(x, size()) {			printed += to_string((*this)[x]);			if (x < size() - 1) printed += " ";		}		throw underflow_error(printed);	}#ifdef ROB_DEBUG	MAP(i, size()) {		Rassert(finite((*this)[i]));	}#endif	return *this;}/*===========================================================================*/MathVec &MathVec::clip(value_type low, value_type high) {	MAP(x, size())		(*this)[x] = rstd::clip((* this)[x], low, high);	return *this;}/*===========================================================================*/MathVec::value_typeMathVec::mag() const {	value_type accum = 0.0;	MAP(x, size())		accum += (*this)[x] * (*this)[x];	RASSERT(finite(accum));	RASSERT(accum >= 0);	accum = sqrt(accum);	RASSERT(finite(accum));	return accum;}/*===========================================================================*/MathVec::value_typeMathVec::operator*(const MathVec & a) const {	RASSERT(size() == a.size());	MathVec::value_type accum = 0.0;	MAP(x, size()) {		accum += (*this)[x] * a[x];	}	return accum;}/*===========================================================================*/const RVector<MathVec::value_type>operator*(const RVector<MathVec> & a,const MathVec & b) {	RVector<MathVec::value_type> vec(a.size());	MAP(x, a.size()) {		vec[x] = a[x] * b;	}	return vec;} /*===========================================================================*/const MathVecmax_dimen(RVector<MathVec> & vec) {	MathVec max_v(vec[0].size(), -numeric_limits<double>::max());	MAP2(x, vec.size(), y, vec[x].size())		max_v[y] = max(max_v[y], vec[x][y]);	return max_v;}/*===========================================================================*/const MathVecmin_dimen(RVector<MathVec> & vec) {	MathVec min_v(vec[0].size(), numeric_limits<double>::max());	MAP2(x, vec.size(), y, vec[x].size())		min_v[y] = min(min_v[y], vec[x][y]);	return min_v;}/*===========================================================================*/void normalize(RVector<MathVec> & vec) {	if (vec.empty())		return;	MathVec max_v = max_dimen(vec);	MathVec min_v = min_dimen(vec);	MathVec half_range = (max_v - min_v) / 2.0;	MathVec mhr = min_v + half_range;	MathVec::value_type max_mag = 0.0;	MAP(x, vec.size())		max_mag = max(max_mag, vec[x].mag());	MAP(x, vec.size())		vec[x] = (vec[x] - mhr) / max_mag;}/*===========================================================================*/doublelambert(const double z) {/* Lambert W function. Based on code written by K M Briggs.http://www.btexact.com/people/briggsk2/LambertW.c.This method is not covered by the copyrights or protections which may apply tothe rest of the code. */	const double eps = 4.0e-16;	const double em1 = 0.3678794411714423215955237701614608; 	RASSERT(z >= -em1 && finite(z));	if (! z) {		return 0.0;	}// Cache the last value returned.	static pair<double, double> cache;	pair<double, double> current_cache = cache;	if (eps_is_equal_to(z, current_cache.first, eps)) {		return current_cache.second;	}// series near -em1 in sqrt(q)	double w;	if (z < -em1 + 1e-4) {		double q = z + em1;		double r = sqrt(q);		double q2 = q * q;		double q3 = q2 * q;// error approx 1e-16		w = -1.0 +			2.331643981597124203363536062168 * r -			1.812187885639363490240191647568 * q +			1.936631114492359755363277457668 * r * q -			2.353551201881614516821543561516 * q2 +			3.066858901050631912893148922704 * r * q2 -			4.175335600258177138854984177460 * q3 +			5.858023729874774148815053846119 * r * q3 -			8.401032217523977370984161688514 * q3 * q;		cache = make_pair(z, w);		return w;	}// initial approx for iteration...// series near 0	if (z < 1.0) {		double p = sqrt(2.0 * (2.7182818284590452353602874713526625 * z + 1.0));		w = -1.0 + p * (1.0 + p *			(-0.333333333333333333333 + p * 0.152777777777777777777777));	} else  {// asymptotic		w = log(z);	}	if (z > 3.0) {// useful?		w -= log(w);	}// Halley iteration	for (long i = 0; i < 10; ++i) {		double e = exp(w); 		double dif = w * e - z;		double p = w + 1.0;		dif /= e * p - 0.5 * (p + 1.0) * dif / p; 		w -= dif;		if (fabs(dif) < eps * (1.0 + fabs(w))) {// rel-abs error			cache = make_pair(z, w);			return w;		}	}	Rabort();	return 0.0;}/*===========================================================================*/doublelambert_ddz(const double z) {	double lz = lambert(z);	return lz / (z * (1.0 + lz));}/*###########################################################################*/void RMath_test() {	Rassert(boltzmann_trial(0.0, 1.0, 0.0, RGen::gen()));	Rassert(! boltzmann_trial(1.0, 0.0, 0.0, RGen::gen()));	for (long x = -50; x < 50; ++x) {		double y = x;		Rassert(interval_round(x, 7) == interval_round(y, 7.0));	}//	double k = lcm(1.0, 0.29999999999999999);}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -