FE_polynomial.h
上传用户:italyroyal
上传日期:2013-05-06
资源大小:473k
文件大小:21k
源码类别:

语音合成与识别

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // This is a part of the Feature program.
  3. // Version: 1.0
  4. // Date: February 22, 2003
  5. // Programmer: Oh-Wook Kwon
  6. // Copyright(c) 2003 Oh-Wook Kwon. All rights reserved. owkwon@ucsd.edu
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef _FE_POLYNOMIAL_H_
  9. #define _FE_POLYNOMIAL_H_
  10. #include <cstdio>
  11. #include <cstdarg>
  12. #include <cmath>
  13. #include <cstring>
  14. #include <cstdlib>
  15. #include <typeinfo>
  16. #include <vector>
  17. using namespace std;
  18. #pragma warning(disable:4786)
  19. #include "FE_complex.h"
  20. template <typename T> class CPolynomial;
  21. // friend template functions
  22. template <typename T> CPolynomial<T> poly_plus(const CPolynomial<T>& A, const CPolynomial<T>& B);
  23. template <typename T> CPolynomial<T> poly_plus(const CPolynomial<T>& A, const double b);
  24. template <typename T> CPolynomial<T> poly_plus(const double b, const CPolynomial<T>& A);
  25. template <typename T> CPolynomial<T> poly_minus(const CPolynomial<T>& A, const CPolynomial<T>& B);
  26. template <typename T> CPolynomial<T> poly_minus(const CPolynomial<T>& A, const double b);
  27. template <typename T> CPolynomial<T> poly_minus(const double b, const CPolynomial<T>& A);
  28. template <typename T> CPolynomial<T> poly_times(const CPolynomial<T>& A, const CPolynomial<T>& B);
  29. template <typename T> CPolynomial<T> poly_times(const CPolynomial<T>& A, const double b);
  30. template <typename T> CPolynomial<T> poly_times(const double b, const CPolynomial<T>& A);
  31. template <typename T> CPolynomial<T> poly_divide(const CPolynomial<T>& A, const CPolynomial<T>& B);
  32. template <typename T> CPolynomial<T> poly_divide(const CPolynomial<T>& A, const double b);
  33. template <typename T> CPolynomial<T> poly_divide(const double b, const CPolynomial<T>& A);
  34. template <typename T> CPolynomial<T> poly_modulo(const CPolynomial<T>& A, const double b);
  35. template <typename T> CPolynomial<T> poly_modulo(const CPolynomial<T>& A, const double b);
  36. template <typename T> CPolynomial<T> poly_modulo(const double b, const CPolynomial<T>& A);
  37. // GNU compiler gcc-2.95.2 cannot handle operator overloading with user-defined class type.
  38. #if 0
  39. template <typename T> CPolynomial<T> poly_plus(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  40. template <typename T> CPolynomial<T> poly_minus(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  41. template <typename T> CPolynomial<T> poly_times(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  42. template <typename T> CPolynomial<T> poly_divide(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  43. #endif
  44. template<typename T> 
  45. class CPolynomial
  46. {
  47. typedef Complex<T> CComplex;
  48. public:
  49. CPolynomial();
  50. CPolynomial(const int v0) { v.resize(1); v[0]=(T)v0; }
  51. CPolynomial(const double v0) { v.resize(1); v[0]=(T)v0; }
  52. CPolynomial(int m, const T* a);
  53. CPolynomial(const char* a);
  54. CPolynomial(const CPolynomial<T>& a) : v(a.v) {}
  55. virtual ~CPolynomial();
  56. void Print() const;
  57. T Eval(T x, T* pd = NULL, int nd = 0) const;
  58. void Roots(CComplex* roots) const;
  59. void zroots(CComplex* a, int m, CComplex* roots, int polish) const;
  60. void laguer(CComplex* a, int m, CComplex* x, int *its) const;
  61. public:
  62. vector<T> v;
  63. CPolynomial<T> operator+();
  64. CPolynomial<T> operator-();
  65. CPolynomial<T>& operator=(const CPolynomial<T>& a);
  66. CPolynomial<T>& operator+=(const CPolynomial<T>& a);
  67. CPolynomial<T>& operator-=(const CPolynomial<T>& a);
  68. CPolynomial<T>& operator*=(const CPolynomial<T>& a);
  69. CPolynomial<T>& operator/=(const CPolynomial<T>& a);
  70. // GCC-2.95-2 did not allow friend operator overloading definition outside class declaration.
  71.         friend CPolynomial<T> operator+(const CPolynomial<T>& A, const CPolynomial<T>& B) {
  72.                 return poly_plus(A,B);
  73.         }
  74.         friend CPolynomial<T> operator+(const CPolynomial<T>& A, const double b) {
  75.                 return poly_plus(A,b);
  76.         }
  77.         friend CPolynomial<T> operator+(const double b, const CPolynomial<T>& A) {
  78.                 return poly_plus(b,A);
  79.         }
  80.         friend CPolynomial<T> operator-(const CPolynomial<T>& A, const CPolynomial<T>& B) {
  81.                 return poly_minus(A,B);
  82.         }
  83.         friend CPolynomial<T> operator-(const CPolynomial<T>& A, const double b) {
  84.                 return poly_minus(A,b);
  85.         }
  86.         friend CPolynomial<T> operator-(const double b, const CPolynomial<T>& A) {
  87.                 return poly_minus(b,A);
  88.         }
  89.         friend CPolynomial<T> operator*(const CPolynomial<T>& A, const CPolynomial<T>& B) {
  90.                 return poly_times(A,B);
  91.         }
  92.         friend CPolynomial<T> operator*(const CPolynomial<T>& A, const double b) {
  93.                 return poly_times(A,b);
  94.         }
  95.         friend CPolynomial<T> operator*(const double b, const CPolynomial<T>& A) {
  96.                 return poly_times(b,A);
  97.         }
  98.         friend CPolynomial<T> operator/(const CPolynomial<T>& A, const CPolynomial<T>& B) {
  99.                 return poly_divide(A,B);
  100.         }
  101.         friend CPolynomial<T> operator/(const CPolynomial<T>& A, const double b) {
  102.                 return poly_divide(A,b);
  103.         }
  104.         friend CPolynomial<T> operator/(const double b, const CPolynomial<T>& A) {
  105.                 return poly_divide(b,A);
  106.         }
  107.         friend CPolynomial<T> operator%(const CPolynomial<T>& A, const CPolynomial<T>& B) {
  108.                 return poly_modulo(A,B);
  109.         }
  110.         friend CPolynomial<T> operator%(const CPolynomial<T>& A, const double b) {
  111.                 return poly_modulo(A,b);
  112.         }
  113.         friend CPolynomial<T> operator%(const double b, const CPolynomial<T>& A) {
  114.                 return poly_modulo(b,A);
  115.         }
  116. #if 0
  117.         friend CPolynomial<T> operator+(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B) {
  118.                 return poly_plus(A,B);
  119.         }
  120.         friend CPolynomial<T> operator+(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B) {
  121.                 return poly_minus(A,B);
  122.         }
  123.         friend CPolynomial<T> operator+(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B) {
  124.                 return poly_times(A,B);
  125.         }
  126.         friend CPolynomial<T> operator+(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B) {
  127.                 return poly_divide(A,B);
  128.         }
  129. #endif
  130. #ifdef __GNUC__
  131.         friend CPolynomial<T> poly_plus<T>(const CPolynomial<T>& A, const CPolynomial<T>& B);
  132.         friend CPolynomial<T> poly_plus<T>(const CPolynomial<T>& A, const double b);
  133.         friend CPolynomial<T> poly_plus<T>(const double b, const CPolynomial<T>& A);
  134.         friend CPolynomial<T> poly_minus<T>(const CPolynomial<T>& A, const CPolynomial<T>& B);
  135.         friend CPolynomial<T> poly_minus<T>(const CPolynomial<T>& A, const double b);
  136.         friend CPolynomial<T> poly_minus<T>(const double b, const CPolynomial<T>& A);
  137.         friend CPolynomial<T> poly_times<T>(const CPolynomial<T>& A, const CPolynomial<T>& B);
  138.         friend CPolynomial<T> poly_times<T>(const CPolynomial<T>& A, const double b);
  139.         friend CPolynomial<T> poly_times<T>(const double b, const CPolynomial<T>& A);
  140.         friend CPolynomial<T> poly_divide<T>(const CPolynomial<T>& A, const CPolynomial<T>& B);
  141.         friend CPolynomial<T> poly_divide<T>(const CPolynomial<T>& A, const double b);
  142.         friend CPolynomial<T> poly_divide<T>(const double b, const CPolynomial<T>& A);
  143.         friend CPolynomial<T> poly_modulo<T>(const CPolynomial<T>& A, const CPolynomial<T>& B);
  144.         friend CPolynomial<T> poly_modulo<T>(const CPolynomial<T>& A, const double b);
  145.         friend CPolynomial<T> poly_modulo<T>(const double b, const CPolynomial<T>& A);
  146. #if 0
  147. friend CPolynomial<T> poly_plus<T>(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  148. friend CPolynomial<T> poly_minus<T>(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  149. friend CPolynomial<T> poly_times<T>(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  150. friend CPolynomial<T> poly_divide<T>(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  151. #endif
  152. #else
  153. friend CPolynomial<T> poly_plus(const CPolynomial<T>& A, const CPolynomial<T>& B);
  154.         friend CPolynomial<T> poly_plus(const CPolynomial<T>& A, const double b);
  155.         friend CPolynomial<T> poly_plus(const double b, const CPolynomial<T>& A);
  156.         friend CPolynomial<T> poly_minus(const CPolynomial<T>& A, const CPolynomial<T>& B);
  157.         friend CPolynomial<T> poly_minus(const CPolynomial<T>& A, const double b);
  158.         friend CPolynomial<T> poly_minus(const double b, const CPolynomial<T>& A);
  159.         friend CPolynomial<T> poly_times(const CPolynomial<T>& A, const CPolynomial<T>& B);
  160.         friend CPolynomial<T> poly_times(const CPolynomial<T>& A, const double b);
  161.         friend CPolynomial<T> poly_times(const double b, const CPolynomial<T>& A);
  162.         friend CPolynomial<T> poly_divide(const CPolynomial<T>& A, const CPolynomial<T>& B);
  163.         friend CPolynomial<T> poly_divide(const CPolynomial<T>& A, const double b);
  164.         friend CPolynomial<T> poly_divide(const double b, const CPolynomial<T>& A);
  165.         friend CPolynomial<T> poly_modulo(const CPolynomial<T>& A, const CPolynomial<T>& B);
  166.         friend CPolynomial<T> poly_modulo(const CPolynomial<T>& A, const double b);
  167.         friend CPolynomial<T> poly_modulo(const double b, const CPolynomial<T>& A);
  168. #if 0
  169. friend CPolynomial<T> poly_plus(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  170. friend CPolynomial<T> poly_minus(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  171. friend CPolynomial<T> poly_times(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  172. friend CPolynomial<T> poly_divide(const CPolynomial<Complex<T> >& A, const CPolynomial<Complex<T> >& B);
  173. #endif
  174. #endif
  175. #if 0
  176. friend CPolynomial<T> operator+(const CPolynomial<T>& a, const CPolynomial<T>& b);
  177. friend CPolynomial<T> operator+(const CPolynomial<T>& a, const double& b);
  178. friend CPolynomial<T> operator+(const double& a, const CPolynomial<T>& b);
  179. friend CPolynomial<T> operator+(const CPolynomial<T>& a);
  180. friend CPolynomial<T> operator-(const CPolynomial<T>& a, const CPolynomial<T>& b);
  181. friend CPolynomial<T> operator-(const CPolynomial<T>& a, const double& b);
  182. friend CPolynomial<T> operator-(const double& a, const CPolynomial<T>& b);
  183. friend CPolynomial<T> operator-(const CPolynomial<T>& a);
  184. friend CPolynomial<T> operator*(const CPolynomial<T>& a, const CPolynomial<T>& b);
  185. friend CPolynomial<T> operator*(const CPolynomial<T>& a, const double& b);
  186. friend CPolynomial<T> operator*(const double& a, const CPolynomial<T>& b);
  187. friend CPolynomial<T> operator/(const CPolynomial<T>& a, const CPolynomial<T>& b);
  188. friend CPolynomial<T> operator/(const CPolynomial<T>& a, const double& b);
  189. friend CPolynomial<T> operator/(const double& a, const CPolynomial<T>& b);
  190. friend CPolynomial<T> operator%(const CPolynomial<T>& a, const CPolynomial<T>& b);
  191. friend CPolynomial<T> operator%(const CPolynomial<T>& a, const double& b);
  192. friend CPolynomial<T> operator%(const double& a, const CPolynomial<T>& b);
  193. #endif
  194. };
  195. template<typename T>
  196. inline void PolynomialDivision(const CPolynomial<T>& a, const CPolynomial<T>& b, CPolynomial<T>& q, CPolynomial<T>& r)
  197. {
  198. int an = a.v.size() - 1;
  199. int bn = a.v.size() - 1;
  200. int qn = ((an >= bn) ? an-bn : 0);
  201. int rn = ((bn >= 1) ? ((an <bn-1) ? an : bn-1) : 0);
  202. q.v.resize(qn+1);
  203. r.v.resize(rn+1);
  204. int k,j;
  205. for(j=0;j<=an;j++){
  206. r.v[j] = a.v[j];
  207. q.v[j] = 0;
  208. }
  209. for(k=an-bn;k>=0;k--){
  210. q.v[k] = r.v[bn+k]/b.v[bn];
  211. for(j=bn+k-1;j>=k;j--) r.v[j] -= q.v[k]*b.v[j-k];
  212. }
  213. for(j=bn;j<=an;j++) r.v[j] = 0;
  214. }
  215. template<typename T>
  216. inline CPolynomial<T> poly_plus(const CPolynomial<T>& a, const CPolynomial<T>& b)
  217. {
  218. CPolynomial<T> c = a;
  219. c += b;
  220. return c;
  221. }
  222. template<typename T>
  223. inline CPolynomial<T> poly_plus(const CPolynomial<T>& a, const double b)
  224. {
  225. CPolynomial<T> c = a;
  226. c += CPolynomial<T>((T)b);
  227. return c;
  228. }
  229. template<typename T>
  230. inline CPolynomial<T> poly_plus(const double a, const CPolynomial<T>& b)
  231. {
  232. CPolynomial<T> c((T)a);
  233. c += b;
  234. return c;
  235. }
  236. template<typename T>
  237. inline CPolynomial<T> operator+(const CPolynomial<T>& a)
  238. {
  239. CPolynomial<T> c = a;
  240. return c;
  241. }
  242. template<typename T>
  243. inline CPolynomial<T> poly_minus(const CPolynomial<T>& a, const CPolynomial<T>& b)
  244. {
  245. CPolynomial<T> c = a;
  246. c -= b;
  247. return c;
  248. }
  249. template<typename T>
  250. inline CPolynomial<T> poly_minus(const CPolynomial<T>& a, const double b)
  251. {
  252. CPolynomial<T> c = a;
  253. c -= CPolynomial<T>((T)b);
  254. return c;
  255. }
  256. template<typename T>
  257. inline CPolynomial<T> poly_minus(const double a, const CPolynomial<T>& b)
  258. {
  259. CPolynomial<T> c((T)a);
  260. c -= b;
  261. return c;
  262. }
  263. template<typename T>
  264. inline CPolynomial<T> operator-(const CPolynomial<T>& a)
  265. {
  266. CPolynomial<T> c = 0;
  267. c -= a;
  268. return c;
  269. }
  270. template<typename T>
  271. inline CPolynomial<T> poly_times(const CPolynomial<T>& a, const CPolynomial<T>& b)
  272. {
  273. CPolynomial<T> c = a;
  274. c *= b;
  275. return c;
  276. }
  277. template<typename T>
  278. inline CPolynomial<T> poly_times(const CPolynomial<T>& a, const double b)
  279. {
  280. CPolynomial<T> c = a;
  281. c *= CPolynomial<T>((T)b);
  282. return c;
  283. }
  284. template<typename T>
  285. inline CPolynomial<T> poly_times(const double a, const CPolynomial<T>& b)
  286. {
  287. CPolynomial<T> c((T)a);
  288. c *= b;
  289. return c;
  290. }
  291. template<typename T>
  292. inline CPolynomial<T> poly_divide(const CPolynomial<T>& a, const CPolynomial<T>& b)
  293. {
  294. CPolynomial<T> q,r;
  295. PolynomialDivision(a,b,q,r);
  296. return q;
  297. }
  298. template<typename T>
  299. inline CPolynomial<T> poly_divide(const CPolynomial<T>& a, const double b)
  300. {
  301. CPolynomial<T> q,r;
  302. PolynomialDivision(a,CPolynomial<T>((T)b),q,r);
  303. return q;
  304. }
  305. template<typename T>
  306. inline CPolynomial<T> poly_divide(const double a, const CPolynomial<T>& b)
  307. {
  308. CPolynomial<T> q,r;
  309. PolynomialDivision(CPolynomial<T>((T)a),b,q,r);
  310. return q;
  311. }
  312. template<typename T>
  313. inline CPolynomial<T> poly_modulo(const CPolynomial<T>& a, const CPolynomial<T>& b)
  314. {
  315. CPolynomial<T> q,r;
  316. PolynomialDivision(a,b,q,r);
  317. return r;
  318. }
  319. template<typename T>
  320. inline CPolynomial<T> poly_modulo(const CPolynomial<T>& a, const double b)
  321. {
  322. CPolynomial<T> q,r;
  323. PolynomialDivision(a,CPolynomial<T>((T)b),q,r);
  324. return r;
  325. }
  326. template<typename T>
  327. inline CPolynomial<T> poly_modulo(const double a, const CPolynomial<T>& b)
  328. {
  329. CPolynomial<T> q,r;
  330. PolynomialDivision(CPolynomial<T>((T)a),b,q,r);
  331. return r;
  332. }
  333. #if 0
  334. template<typename T> inline CPolynomial<T> poly_plus(const CPolynomial<Complex<T> >& a, const CPolynomial<Complex<T> >& b)
  335. {
  336. CPolynomial<T> c = a; c += b; return c;
  337. }
  338. template<typename T> inline CPolynomial<T> poly_minus(const CPolynomial<Complex<T> >& a, const CPolynomial<Complex<T> >& b)
  339. {
  340. CPolynomial<T> c = a; c -= b; return c;
  341. }
  342. template<typename T> inline CPolynomial<T> poly_times(const CPolynomial<Complex<T> >& a, const CPolynomial<Complex<T> >& b)
  343. {
  344. CPolynomial<T> c = a; c *= b; return c;
  345. }
  346. template<typename T> inline CPolynomial<T> poly_divide(const CPolynomial<Complex<T> >& a, const CPolynomial<Complex<T> >& b)
  347. {
  348. CPolynomial<T> c = a; c /= b; return c;
  349. }
  350. #endif
  351. template<typename T>
  352. CPolynomial<T>::CPolynomial(int m, const T* a)
  353. {
  354. for(int i=0; i<=m; i++){
  355. v.push_back(a[i]);
  356. }
  357. }
  358. #if 0
  359. // do not use <cstdarg> and <typeinfo> because they are very fragile
  360. // and depend on compilers
  361. template<typename T>
  362. CPolynomial<T>::CPolynomial(int m, const T v0, ...)
  363. {
  364. va_list args;
  365. va_start (args, m); // Although GNU compiler warns here, we can ignore it.
  366. const type_info& a = typeid(v0);
  367. if(strcmp(a.name(),"float")==0 || strcmp(a.name(),"double")==0){
  368. for(int i=1; i<=m; i++){
  369. v.push_back((T)va_arg(args, double));
  370. }
  371. }
  372. else{
  373. printf("Unsupported Polynomial type (%s)!n", a.name());
  374. exit(1);
  375. }
  376.     va_end (args);
  377. }
  378. #endif
  379. template<typename T>
  380. CPolynomial<T>::CPolynomial(const char* a)
  381. {
  382. char *t = strdup(a);
  383. char *p = strtok(t, " trn");
  384. v.push_back((T)atof(p));
  385. while((p = strtok(NULL, " trn"))){
  386. v.push_back((T)atof(p));
  387. }
  388. free(t);
  389. }
  390. template<typename T>
  391. CPolynomial<T>::CPolynomial()
  392. {
  393. v.push_back((T)0);
  394. }
  395. template<typename T>
  396. CPolynomial<T>::~CPolynomial()
  397. {
  398. }
  399. #define EPS 2.0e-6
  400. #define MAXM 100
  401. /* Roots() yields n roots into roots[1]...roots[n] */
  402. template<typename T>
  403. void CPolynomial<T>::Roots(CComplex* roots) const
  404. {
  405. int n = v.size()-1;
  406. vector<CComplex> a(n+1);
  407. for(int i=0;i<=n;i++) a[i] = CComplex(v[i],0);
  408. zroots(&a[0], n, roots, 1);
  409. }
  410. #define EPSS 1.0e-7
  411. #define MR 8
  412. #define MT 10
  413. #define MAXIT (MT*MR)
  414. #ifndef my_max
  415. #define my_max(a, b) (((a) > (b)) ? (a) : (b)) 
  416. #endif
  417. #ifndef my_min
  418. #define my_min(a, b) (((a) < (b)) ? (a) : (b)) 
  419. #endif
  420. template<typename T>
  421. void CPolynomial<T>::zroots(CComplex* a, int m, CComplex* roots, int polish) const
  422. {
  423. int i,its,j,jj;
  424. CComplex x,b,c,ad[MAXM];
  425. for(j=0;j<=m;j++) ad[j] = a[j];
  426. for(j=m;j>=1;j--){
  427. //x = 0;
  428. x = roots[j];
  429. laguer(ad,j,&x,&its);
  430. if(fabs(imag(x)) <= 2.0*EPS*fabs(real(x))) x=CComplex(real(x), 0);
  431. roots[j] = x;
  432. b = ad[j];
  433. for(jj=j-1;jj>=0;jj--){
  434. c = ad[jj];
  435. ad[jj] = b;
  436. b = x*b+c;
  437. }
  438. }
  439. if(polish)
  440. for(j=1;j<=m;j++)
  441. laguer(a,m,&roots[j],&its);
  442. for(j=2;j<=m;j++){
  443. x = roots[j];
  444. for(i=j-1;i>=1;i--){
  445. if(real(roots[i]) <= real(x)) break;
  446. roots[i+1] = roots[i];
  447. }
  448. roots[i+1] = x;
  449. }
  450. }
  451. template<typename T>
  452. void CPolynomial<T>::laguer(CComplex* a, int m, CComplex* x, int *its) const
  453. {
  454. int iter,j;
  455. T abx,abp,abm,err;
  456. CComplex dx,x1,b,d,f,g,h,sq,gp,gm,g2;
  457. static T frac[MR+1]={
  458. (T)0.00,(T)0.50,(T)0.25,
  459. (T)0.75,(T)0.13,(T)0.38,
  460. (T)0.62,(T)0.88,(T)1.00
  461. };
  462. for(iter=1;iter<=MAXIT;iter++){
  463. *its = iter;
  464. b = a[m];
  465. err = (T)abs(b);
  466. d = f = 0;
  467. abx = (T)abs(*x);
  468. for(j=m-1;j>=0;j--){
  469. f = (*x)*f+d;
  470. d = (*x)*d+b;
  471. b = (*x)*b+a[j];
  472. err = (T)abs(b)+abx*err;
  473. }
  474. err *= (T)EPSS;
  475. if(abs(b) <= err) return;
  476. g = d/b;
  477. g2 = g*g;
  478. h = g2 - (T)2*(f/b);
  479. sq = sqrt((T)(m-1)*(((T)m*h)-g2));
  480. gp = g+sq;
  481. gm = g-sq;
  482. abp = (T)abs(gp);
  483. abm = (T)abs(gm);
  484. if(abp < abm) gp = gm;
  485. dx = ((my_max(abp,abm) > 0.0 ? CComplex(m,0)/gp
  486. : ((T)exp(log(1+abx))*CComplex(cos(iter),sin(iter)))));
  487. x1 = (*x)-dx;
  488. if(real(*x) == real(x1) && imag(*x) == imag(x1)) return;
  489. if(iter%MT) *x = x1;
  490. else *x = (*x)-frac[iter/MT]*dx;
  491. }
  492. printf("too many iteration in laguer");
  493. return;
  494. }
  495. template<typename T>
  496. T CPolynomial<T>::Eval(T x, T* pd, int nd) const
  497. {
  498. int nnd, j, i;
  499. T cnst = 1;
  500. T ftmp;
  501. if(!pd){
  502. nd = 0;
  503. }
  504. int n = v.size()-1;
  505. ftmp = v[n];
  506. if(pd) pd[0] = v[n];
  507. for(j=1;j<=nd;j++) pd[j] = 0;
  508. for(i=n-1;i>=0;i--){
  509. nnd = (nd < (n-i) ? nd : n-i);
  510. for(j=nnd;j>=1;j--)
  511. pd[j] = (T)(pd[j]*x+pd[j-1]);
  512. ftmp = (T)(ftmp*x+v[i]);
  513. if(pd) pd[0] = (T)(pd[0]*x+v[i]);
  514. }
  515. for(i=2;i<=nd;i++){
  516. cnst *= i;
  517. pd[i] *= cnst;
  518. }
  519. return ftmp;
  520. }
  521. template<typename T>
  522. void CPolynomial<T>::Print() const
  523. {
  524. int n=v.size()-1;
  525. int bAllZero = 1;
  526. for(int i=n;i>=0;i--){
  527. if(fabs(v[i]) < 1e-37){
  528. if(i==0 && bAllZero) printf("0");
  529. continue;
  530. }
  531. bAllZero = 0;
  532. if(v[i] > 0 && i != n) printf(" + ");
  533. else if(v[i] < 0) printf(" - ");
  534. if(fabs(fabs(v[i])-1) > 1e-37){
  535. printf("%gx(%d)",fabs(v[i]),i);
  536. }
  537. else{
  538. printf("x(%d)",i);
  539. }
  540. }
  541. printf("n");
  542. }
  543. template<typename T>
  544. CPolynomial<T>& CPolynomial<T>::operator=(const CPolynomial<T>& a)
  545. {
  546. int an = a.v.size()-1;
  547. int n = an;
  548. v.resize(n+1);
  549. int m = 0;
  550. for(int i=0; i<=n; i++){
  551. v[i] = a.v[i];
  552. if(v[i] != 0.0) 
  553. m = i;
  554. }
  555. if(m != n) v.resize(m+1);
  556. return *this;
  557. }
  558. template<typename T>
  559. CPolynomial<T>& CPolynomial<T>::operator+=(const CPolynomial<T>& a)
  560. {
  561. int m = v.size()-1;
  562. int an = a.v.size()-1;
  563. int n = my_max(m,an);
  564. v.resize(n+1);
  565. for(int i=0; i<=n; i++)
  566. v[i] = ((i<=m)? v[i]: 0) + ((i<=an)? a.v[i]: 0);
  567. return *this;
  568. }
  569. template<typename T>
  570. CPolynomial<T>& CPolynomial<T>::operator-=(const CPolynomial<T>& a)
  571. {
  572. int m = v.size()-1;
  573. int an = a.v.size()-1;
  574. int n = my_max(m,an);
  575. v.resize(n+1);
  576. for(int i=0; i<=n; i++)
  577. v[i] = ((i<=m)? v[i]: 0) - ((i<=an)? a.v[i]: 0);
  578. return *this;
  579. }
  580. template<typename T>
  581. CPolynomial<T>& CPolynomial<T>::operator*=(const CPolynomial<T>& a)
  582. {
  583. int p,i;
  584. int m = v.size()-1;
  585. int an = a.v.size()-1;
  586. int n = m + an;
  587. v.resize(n+1);
  588. for(p=n;p>m;p--) v[p] = 0;
  589. for(p=n; p>=0; p--){
  590. T sum = 0;
  591. for(i=my_min(p,m); i>=0 && p-i<=an; i--){
  592. sum += v[i] * a.v[p-i];
  593. }
  594. v[p] = sum;
  595. }
  596. return *this;
  597. }
  598. template<typename T>
  599. CPolynomial<T>& CPolynomial<T>::operator/=(const CPolynomial<T>& a)
  600. {
  601. CPolynomial<T> q,r;
  602. PolynomialDivision(*this,a,q,r);
  603. return q;
  604. }
  605. #endif