Polynomial.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953
  1. /* Polynomial.cpp
  2. *
  3. * Copyright (C) 1993-2018 David Weenink
  4. *
  5. * This code is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This code is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this work. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. djmw 20020813 GPL header
  20. djmw 20030619 Added SVD_compute before SVD_solve
  21. djmw 20060510 Polynomial_to_Roots: changed behaviour. All roots found are now saved.
  22. In previous version a nullptr pointer was returned. New error messages.
  23. djmw 20071012 Added: o_CAN_WRITE_AS_ENCODING.h
  24. djmw 20071201 Melder_warning<n>
  25. djmw 20080122 float -> double
  26. djmw 20110304 Thing_new
  27. */
  28. #include "Polynomial.h"
  29. #include "SVD.h"
  30. #include "NUMclapack.h"
  31. #include "TableOfReal_extensions.h"
  32. #include "NUMmachar.h"
  33. #include "oo_DESTROY.h"
  34. #include "Polynomial_def.h"
  35. #include "oo_COPY.h"
  36. #include "Polynomial_def.h"
  37. #include "oo_EQUAL.h"
  38. #include "Polynomial_def.h"
  39. #include "oo_CAN_WRITE_AS_ENCODING.h"
  40. #include "Polynomial_def.h"
  41. #include "oo_WRITE_TEXT.h"
  42. #include "Polynomial_def.h"
  43. #include "oo_WRITE_BINARY.h"
  44. #include "Polynomial_def.h"
  45. #include "oo_READ_TEXT.h"
  46. #include "Polynomial_def.h"
  47. #include "oo_READ_BINARY.h"
  48. #include "Polynomial_def.h"
  49. #include "oo_DESCRIPTION.h"
  50. #include "Polynomial_def.h"
  51. /* Evaluate polynomial and derivative jointly
  52. c [1..n] -> degree n-1 !!
  53. */
  54. void Polynomial_evaluateWithDerivative (Polynomial me, double x, double *out_f, double *out_df) {
  55. longdouble p = my coefficients [my numberOfCoefficients], dp = 0.0, xc = x;
  56. for (integer i = my numberOfCoefficients - 1; i > 0; i --) {
  57. dp = dp * xc + p;
  58. p = p * xc + my coefficients [i];
  59. }
  60. if (out_f) *out_f = (double) p;
  61. if (out_df) *out_df = (double) dp;
  62. }
  63. /* Get value and derivative */
  64. static void Polynomial_evaluateWithDerivative_z (Polynomial me, dcomplex *in_z, dcomplex *out_p, dcomplex *out_dp) {
  65. longdouble pr = my coefficients [my numberOfCoefficients], pi = 0.0;
  66. longdouble dpr = 0.0, dpi = 0.0, x = in_z -> re, y = in_z -> im;
  67. for (integer i = my numberOfCoefficients - 1; i > 0; i --) {
  68. longdouble tr = dpr;
  69. dpr = dpr * x - dpi * y + pr;
  70. dpi = tr * y + dpi * x + pi;
  71. tr = pr;
  72. pr = pr * x - pi * y + my coefficients [i];
  73. pi = tr * y + pi * x;
  74. }
  75. if (out_p) *out_p = { (double) pr, (double) pi };
  76. if (out_dp) *out_dp = { (double) dpr, (double) dpi };
  77. }
  78. void Polynomial_evaluateDerivatives (Polynomial me, double x, double *derivatives, integer numberOfDerivatives) {
  79. /* Evaluate polynomial c [1]+c [2]*x+...degree*x^degree in derivative [0] and derivatives [1..numberOfDerivatives] */
  80. integer degree = my numberOfCoefficients - 1;
  81. numberOfDerivatives = numberOfDerivatives > degree ? degree : numberOfDerivatives;
  82. derivatives [0] = my coefficients [my numberOfCoefficients];
  83. for (integer j = 1; j <= numberOfDerivatives; j ++)
  84. derivatives [j] = 0.0;
  85. for (integer i = degree - 1; i >= 0; i--) {
  86. integer n =
  87. numberOfDerivatives < degree - i ? numberOfDerivatives : degree - i;
  88. for (integer j = n; j >= 1; j --)
  89. derivatives [j] = derivatives [j] * x + derivatives [j - 1];
  90. derivatives [0] = derivatives [0] * x + my coefficients [i + 1]; // evaluate polynomial (Horner)
  91. }
  92. double fact = 1.0;
  93. for (integer j = 2; j <= numberOfDerivatives; j ++) {
  94. fact *= j;
  95. derivatives [j] *= fact;
  96. }
  97. }
  98. /*
  99. void polynomial_divide (double *u, integer m, double *v, integer n, double *q, double *r);
  100. Purpose:
  101. Find the quotient q(x) and the remainder r(x) polynomials that result from the division of
  102. the polynomial u(x) = u [1] + u [2]*x^1 + u [3]*x^2 + ... + u [m]*x^(m-1) by the
  103. polynomial v(x) = v [1] + v [2]*x^1 + v [3]*x^2 + ... + v [n]*x^(n-1), such that
  104. u(x) = v(x)*q(x) + r(x).
  105. The arrays u, v, q and r have to be dimensioned as u [1...m], v [1..n], q [1...m] and r [1...m],
  106. respectively.
  107. On return, the q [1..m-n] and r [1..n-1] contain the quotient and the remainder
  108. polynomial coefficients, repectively.
  109. See Knuth, The Art of Computer Programming, Volume 2: Seminumerical algorithms,
  110. Third edition, Section 4.6.1 Algorithm D (the algorithm as described has been modified
  111. to prevent overwriting of the u-polynomial).
  112. */
  113. static void polynomial_divide (double *u, integer m, double *v, integer n, double *q, double *r) {
  114. // Copy u [1..m] into r [1..n] to prevent overwriting of u.
  115. // Put the q coefficients to zero for cases n > m.
  116. for (integer k = 1; k <= m; k ++) {
  117. r [k] = u [k];
  118. q [k] = 0.0;
  119. }
  120. for (integer k = m - n + 1; k > 0; k --) { /* D1 */
  121. q [k] = r [n + k - 1] / v [n]; /* D2 with u -> r*/
  122. for (integer j = n + k - 1; j >= k; j --) {
  123. r [j] -= q [k] * v [j - k + 1];
  124. }
  125. }
  126. }
  127. static void Polynomial_polish_realroot (Polynomial me, double *x, integer maxit) {
  128. double xbest = *x, pmin = 1e308;
  129. if (! NUMfpp)
  130. NUMmachar ();
  131. for (integer i = 1; i <= maxit; i ++) {
  132. double p, dp;
  133. Polynomial_evaluateWithDerivative (me, *x, & p, & dp);
  134. double fabsp = fabs (p);
  135. if (fabsp > pmin || fabs (fabsp - pmin) < NUMfpp -> eps) {
  136. /*
  137. We stop, because the approximation is getting worse or we cannot get any closer.
  138. Return the previous (hitherto best) value for x.
  139. */
  140. *x = xbest;
  141. return;
  142. }
  143. pmin = fabsp;
  144. xbest = *x;
  145. if (fabs (dp) == 0.0)
  146. return;
  147. double dx = p / dp; // Newton-Raphson
  148. *x -= dx;
  149. }
  150. // Melder_throw (U"Maximum number of iterations exceeded.");
  151. }
  152. static void Polynomial_polish_complexroot_nr (Polynomial me, dcomplex *z, integer maxit) {
  153. dcomplex zbest = *z;
  154. double pmin = 1e308;
  155. if (! NUMfpp)
  156. NUMmachar ();
  157. for (integer i = 1; i <= maxit; i ++) {
  158. dcomplex p, dp;
  159. Polynomial_evaluateWithDerivative_z (me, z, &p, &dp);
  160. double fabsp = dcomplex_abs (p);
  161. if (fabsp > pmin || fabs (fabsp - pmin) < NUMfpp -> eps) {
  162. /*
  163. We stop, because the approximation is getting worse.
  164. Return the previous (hitherto best) value for z.
  165. */
  166. *z = zbest;
  167. return;
  168. }
  169. pmin = fabsp;
  170. zbest = *z;
  171. if (dcomplex_abs (dp) == 0.0)
  172. return;
  173. dcomplex dz = dcomplex_div (p, dp); // Newton-Raphson
  174. *z = dcomplex_sub (*z, dz);
  175. }
  176. // Melder_throw (U"Maximum number of iterations exceeded.");
  177. }
  178. /*
  179. Symbolic evaluation of polynomial coefficients.
  180. Recurrence: P [n] = (a [n] * x + b [n]) P [n-1] + c [n] P [n-2],
  181. where P [n] is any orthogonal polynomial of degree n.
  182. P [n] is an array of coefficients p [k] representing: p [1] + p [2] x + ... p [n+1] x^n.
  183. Preconditions:
  184. degree > 1;
  185. pnm1 : polynomial of degree n - 1
  186. pnm2 : polynomial of degree n - 2
  187. */
  188. static void NUMpolynomial_recurrence (double *pn, integer degree, double a, double b, double c, double *pnm1, double *pnm2) {
  189. Melder_assert (degree > 1);
  190. pn [1] = b * pnm1 [1] + c * pnm2 [1];
  191. for (integer i = 2; i <= degree - 1; i ++) {
  192. pn [i] = a * pnm1 [i - 1] + b * pnm1 [i] + c * pnm2 [i];
  193. }
  194. pn [degree] = a * pnm1 [degree - 1] + b * pnm1 [degree];
  195. pn [degree + 1] = a * pnm1 [degree];
  196. }
  197. /* frozen [1..ma] */
  198. static void svdcvm (double **v, integer mfit, integer ma, int *frozen, double *w, double **cvm) {
  199. autoNUMvector<double> wti (1, mfit);
  200. for (integer i = 1; i <= mfit; i ++) {
  201. if (w [i] != 0.0) {
  202. wti [i] = 1.0 / (w [i] * w [i]);
  203. } else {
  204. ; // TODO: write up an explanation for why it is not necessary to do anything if w [i] is zero
  205. }
  206. }
  207. for (integer i = 1; i <= mfit; i ++) {
  208. for (integer j = 1; j <= i; j ++) {
  209. longdouble sum = 0.0;
  210. for (integer k = 1; k <= mfit; k ++) {
  211. sum += v [i] [k] * v [j] [k] * wti [k];
  212. }
  213. cvm [j] [i] = cvm [i] [j] = (double) sum;
  214. }
  215. }
  216. for (integer i = mfit + 1; i <= ma; i ++) {
  217. for (integer j = 1; j <= i; j ++) {
  218. cvm [j] [i] = cvm [i] [j] = 0.0;
  219. }
  220. }
  221. integer k = mfit;
  222. for (integer j = ma; j > 0; j --) {
  223. // if (! frozen || ! frozen [i]) why i?? TODO
  224. if (! frozen || ! frozen [j]) {
  225. for (integer i = 1; i <= ma; i ++) {
  226. double t = cvm [i] [k];
  227. cvm [i] [k] = cvm [i] [j];
  228. cvm [i] [j] = t;
  229. }
  230. for (integer i = 1; i <= ma; i ++) {
  231. double t = cvm [k] [i];
  232. cvm [k] [i] = cvm [j] [i];
  233. cvm [j] [i] = t;
  234. }
  235. k --;
  236. }
  237. }
  238. }
  239. /********* FunctionTerms *********************************************/
  240. Thing_implement (FunctionTerms, Function, 0);
  241. double structFunctionTerms :: v_evaluate (double /* x */) {
  242. return undefined;
  243. }
  244. dcomplex structFunctionTerms :: v_evaluate_z (dcomplex /* z */) {
  245. return { undefined, undefined };
  246. }
  247. void structFunctionTerms :: v_evaluateTerms (double /* x */, double terms []) {
  248. for (integer i = 1; i <= numberOfCoefficients; i ++) {
  249. terms [i] = undefined;
  250. }
  251. }
  252. integer structFunctionTerms :: v_getDegree () {
  253. return numberOfCoefficients - 1;
  254. }
  255. void structFunctionTerms :: v_getExtrema (double x1, double x2, double *p_xmin, double *p_ymin, double *p_xmax, double *p_ymax) { // David, geen aparte naam hier nodig: ???
  256. integer numberOfPoints = 1000;
  257. // Melder_warning (L"defaultGetExtrema: extrema calculated by sampling the interval");
  258. double x = x1, dx = (x2 - x1) / (numberOfPoints - 1);
  259. double xmn = x, xmx = xmn, ymn = v_evaluate (x), ymx = ymn; // xmin, xmax .. would shadow member
  260. for (integer i = 2; i <= numberOfPoints; i ++) {
  261. x += dx;
  262. double y = v_evaluate (x);
  263. if (y > ymx) {
  264. ymx = y; xmx = x;
  265. } else if (y < ymn) {
  266. ymn = y; xmn = x;
  267. }
  268. }
  269. if (p_xmin)
  270. *p_xmin = xmn;
  271. if (p_xmax)
  272. *p_xmax = xmx;
  273. if (p_ymin)
  274. *p_ymin = ymn;
  275. if (p_ymax)
  276. *p_ymax = ymx;
  277. }
  278. static inline void FunctionTerms_extendCapacityIf (FunctionTerms me, integer minimum) {
  279. if (my _capacity < minimum) {
  280. NUMvector_append <double> (& my coefficients, 1, & minimum);
  281. my _capacity = minimum;
  282. }
  283. }
  284. void FunctionTerms_init (FunctionTerms me, double xmin, double xmax, integer numberOfCoefficients) {
  285. my coefficients = NUMvector<double> (1, numberOfCoefficients);
  286. my numberOfCoefficients = numberOfCoefficients;
  287. my _capacity = numberOfCoefficients;
  288. my xmin = xmin; my xmax = xmax;
  289. }
  290. autoFunctionTerms FunctionTerms_create (double xmin, double xmax, integer numberOfCoefficients) {
  291. try {
  292. autoFunctionTerms me = Thing_new (FunctionTerms);
  293. FunctionTerms_init (me.get(), xmin, xmax, numberOfCoefficients);
  294. return me;
  295. } catch (MelderError) {
  296. Melder_throw (U"FunctionTerms not created.");
  297. }
  298. }
  299. void FunctionTerms_initFromString (FunctionTerms me, double xmin, double xmax, conststring32 s, bool allowTrailingZeros) {
  300. integer numberOfCoefficients;
  301. autoVEC numbers = VEC_createFromString (s);
  302. if (! allowTrailingZeros) {
  303. while (numbers [numbers.size] == 0 && numberOfCoefficients > 1)
  304. numberOfCoefficients --;
  305. }
  306. FunctionTerms_init (me, xmin, xmax, numberOfCoefficients);
  307. NUMvector_copyElements (numbers.at, my coefficients, 1, numberOfCoefficients);
  308. }
  309. integer FunctionTerms_getDegree (FunctionTerms me) {
  310. return my v_getDegree ();
  311. }
  312. void FunctionTerms_setDomain (FunctionTerms me, double xmin, double xmax) {
  313. my xmin = xmin; my xmax = xmax;
  314. }
  315. double FunctionTerms_evaluate (FunctionTerms me, double x) {
  316. return my v_evaluate (x);
  317. }
  318. dcomplex FunctionTerms_evaluate_z (FunctionTerms me, dcomplex z) {
  319. return my v_evaluate_z (z);
  320. }
  321. void FunctionTerms_evaluateTerms (FunctionTerms me, double x, double terms []) {
  322. my v_evaluateTerms (x, terms);
  323. }
  324. void FunctionTerms_getExtrema (FunctionTerms me, double x1, double x2, double *xmin, double *ymin, double *xmax, double *ymax) {
  325. if (x2 <= x1) {
  326. x1 = my xmin;
  327. x2 = my xmax;
  328. }
  329. my v_getExtrema (x1, x2, xmin, ymin, xmax, ymax);
  330. }
  331. double FunctionTerms_getMinimum (FunctionTerms me, double x1, double x2) {
  332. double xmin, xmax, ymin, ymax;
  333. FunctionTerms_getExtrema (me, x1, x2, &xmin, &ymin, &xmax, &ymax);
  334. return ymin;
  335. }
  336. double FunctionTerms_getXOfMinimum (FunctionTerms me, double x1, double x2) {
  337. double xmin, xmax, ymin, ymax;
  338. FunctionTerms_getExtrema (me, x1, x2, &xmin, &ymin, &xmax, &ymax);
  339. return xmin;
  340. }
  341. double FunctionTerms_getMaximum (FunctionTerms me, double x1, double x2) {
  342. double xmin, xmax, ymin, ymax;
  343. FunctionTerms_getExtrema (me, x1, x2, &xmin, &ymin, &xmax, &ymax);
  344. return ymax;
  345. }
  346. double FunctionTerms_getXOfMaximum (FunctionTerms me, double x1, double x2) {
  347. double xmin, xmax, ymin, ymax;
  348. FunctionTerms_getExtrema (me, x1, x2, &xmin, &ymin, &xmax, &ymax);
  349. return xmax;
  350. }
  351. static void Graphics_polyline_clipTopBottom (Graphics g, double *x, double *y, integer numberOfPoints, double ymin, double ymax) {
  352. integer index = 0;
  353. if (numberOfPoints < 2)
  354. return;
  355. double x1 = x [0], y1 = y [0];
  356. double xb = x1, yb = y1;
  357. for (integer i = 1; i < numberOfPoints; i ++) {
  358. double x2 = x [i], y2 = y [i];
  359. if (! ( (y1 > ymax && y2 > ymax) || (y1 < ymin && y2 < ymin))) {
  360. double dxy = (x2 - x1) / (y1 - y2);
  361. double xcros_max = x1 - (ymax - y1) * dxy;
  362. double xcros_min = x1 - (ymin - y1) * dxy;
  363. if (y1 > ymax && y2 < ymax) {
  364. // Line enters from above: start new segment. Save start values.
  365. xb = x [i - 1];
  366. yb = y [i - 1];
  367. index = i - 1;
  368. y [i - 1] = ymax;
  369. x [i - 1] = xcros_max;
  370. }
  371. if (y1 > ymin && y2 < ymin) {
  372. // Line leaves at bottom: draw segment. Save end values and restore them
  373. // Origin of arrays for Graphics_polyline are at element 0 !!!
  374. double xe = x [i], ye = y [i];
  375. y [i] = ymin;
  376. x [i] = xcros_min;
  377. Graphics_polyline (g, i - index + 1, x + index, y + index);
  378. x [index] = xb;
  379. y [index] = yb;
  380. x [i] = xe;
  381. y [i] = ye;
  382. }
  383. if (y1 < ymin && y2 > ymin) {
  384. // Line enters from below: start new segment. Save start values
  385. xb = x [i - 1];
  386. yb = y [i - 1];
  387. index = i - 1;
  388. y [i - 1] = ymin;
  389. x [i - 1] = xcros_min;
  390. }
  391. if (y1 < ymax && y2 > ymax) {
  392. // Line leaves at top: draw segment. Save and restore
  393. double xe = x [i], ye = y [i];
  394. y [i] = ymax;
  395. x [i] = xcros_max;
  396. Graphics_polyline (g, i - index + 1, x + index, y + index);
  397. x [index] = xb;
  398. y [index] = yb;
  399. x [i] = xe;
  400. y [i] = ye;
  401. }
  402. } else {
  403. index = i;
  404. }
  405. y1 = y2;
  406. x1 = x2;
  407. }
  408. if (index < numberOfPoints - 1) {
  409. Graphics_polyline (g, numberOfPoints - index, x + index, y + index);
  410. x [index] = xb; y [index] = yb;
  411. }
  412. }
  413. void FunctionTerms_draw (FunctionTerms me, Graphics g, double xmin, double xmax, double ymin, double ymax, int extrapolate, int garnish) {
  414. integer numberOfPoints = 1000;
  415. autoNUMvector<double> y (1, numberOfPoints + 1);
  416. autoNUMvector<double> x (1, numberOfPoints + 1);
  417. if (xmax <= xmin) {
  418. xmin = my xmin;
  419. xmax = my xmax;
  420. }
  421. double fxmin = xmin, fxmax = xmax;
  422. if (! extrapolate) {
  423. if (xmax < my xmin || xmin > my xmax)
  424. return;
  425. if (xmin < my xmin)
  426. fxmin = my xmin;
  427. if (xmax > my xmax)
  428. fxmax = my xmax;
  429. }
  430. if (ymax <= ymin) {
  431. double x1, x2;
  432. FunctionTerms_getExtrema (me, fxmin, fxmax, &x1, &ymin, &x2, &ymax);
  433. }
  434. Graphics_setInner (g);
  435. Graphics_setWindow (g, xmin, xmax, ymin, ymax);
  436. // Draw only the parts within [fxmin, fxmax] X [ymin, ymax].
  437. double dx = (fxmax - fxmin) / (numberOfPoints - 1);
  438. for (integer i = 1; i <= numberOfPoints; i ++) {
  439. x [i] = fxmin + (i - 1.0) * dx;
  440. y [i] = FunctionTerms_evaluate (me, x [i]);
  441. }
  442. //Graphics_polyline_clipTopBottom (g, x+1, y+1, numberOfPoints, ymin, ymax);
  443. Graphics_polyline_clipTopBottom (g, &x [1], &y [1], numberOfPoints, ymin, ymax);
  444. Graphics_unsetInner (g);
  445. if (garnish) {
  446. Graphics_drawInnerBox (g);
  447. Graphics_marksBottom (g, 2, true, true, false);
  448. Graphics_marksLeft (g, 2, true, true, false);
  449. }
  450. }
  451. void FunctionTerms_drawBasisFunction (FunctionTerms me, Graphics g, integer index, double xmin, double xmax, double ymin, double ymax, int extrapolate, int garnish) {
  452. if (index < 1 || index > my numberOfCoefficients)
  453. return;
  454. autoFunctionTerms thee = Data_copy (me);
  455. for (integer i = 1; i <= my numberOfCoefficients; i ++)
  456. thy coefficients [i] = 0.0;
  457. thy coefficients [index] = 1.0;
  458. thy numberOfCoefficients = index;
  459. FunctionTerms_draw (thee.get(), g, xmin, xmax, ymin, ymax, extrapolate, garnish);
  460. }
  461. void FunctionTerms_setCoefficient (FunctionTerms me, integer index, double value) {
  462. Melder_require (index > 0 && index <= my numberOfCoefficients, U"Index out of range [1, ", my numberOfCoefficients, U"].");
  463. Melder_require (value == 0.0 && index < my numberOfCoefficients, U"You should not remove the highest degree term.");
  464. my coefficients [index] = value;
  465. }
  466. /********** Polynomial ***********************************************/
  467. Thing_implement (Polynomial, FunctionTerms, 1);
  468. double structPolynomial :: v_evaluate (double x) {
  469. longdouble p = coefficients [numberOfCoefficients];
  470. for (integer i = numberOfCoefficients - 1; i > 0; i --)
  471. p = p * x + coefficients [i];
  472. return (double) p;
  473. }
  474. dcomplex structPolynomial :: v_evaluate_z (dcomplex z) {
  475. longdouble x = z.re, y = z.im;
  476. longdouble pr = coefficients [numberOfCoefficients];
  477. longdouble pi = 0.0;
  478. for (integer i = numberOfCoefficients - 1; i > 0; i --) {
  479. longdouble prtmp = pr;
  480. pr = pr * x - pi * y + coefficients [i];
  481. pi = prtmp * y + pi * x;
  482. }
  483. return { (double) pr, (double) pi };
  484. }
  485. void structPolynomial :: v_evaluateTerms (double x, double terms []) {
  486. terms [1] = 1;
  487. for (integer i = 2; i <= numberOfCoefficients; i ++)
  488. terms [i] = terms [i - 1] * x;
  489. }
  490. void structPolynomial :: v_getExtrema (double x1, double x2, double *p_xmin, double *p_ymin, double *p_xmax, double *p_ymax) {
  491. try {
  492. integer degree = numberOfCoefficients - 1;
  493. double xmn = x1, ymn = v_evaluate (x1);
  494. double xmx = x2, ymx = v_evaluate (x2);
  495. if (ymn > ymx) {
  496. std::swap (ymn, ymx);
  497. std::swap (xmn, xmx);
  498. }
  499. if (degree < 2)
  500. return;
  501. autoPolynomial d = Polynomial_getDerivative (this);
  502. autoRoots r = Polynomial_to_Roots (d.get());
  503. for (integer i = 1; i <= degree - 1; i ++) {
  504. double x = (r -> v [i]).re;
  505. if (x > x1 && x < x2) {
  506. double y = v_evaluate (x);
  507. if (y > ymx) {
  508. ymx = y;
  509. xmx = x;
  510. } else if (y < ymn) {
  511. ymn = y;
  512. xmn = x;
  513. }
  514. }
  515. }
  516. if (p_xmin)
  517. *p_xmin = xmn;
  518. if (p_xmax)
  519. *p_xmax = xmx;
  520. if (p_ymin)
  521. *p_ymin = ymn;
  522. if (p_ymax)
  523. *p_ymax = ymx;
  524. } catch (MelderError) {
  525. structFunctionTerms :: v_getExtrema (x1, x2, p_xmin, p_ymin, p_xmax, p_ymax);
  526. Melder_clearError ();
  527. }
  528. }
  529. autoPolynomial Polynomial_create (double xmin, double xmax, integer degree) {
  530. try {
  531. autoPolynomial me = Thing_new (Polynomial);
  532. FunctionTerms_init (me.get(), xmin, xmax, degree + 1);
  533. return me;
  534. } catch (MelderError) {
  535. Melder_throw (U"Polynomial not created.");
  536. }
  537. }
  538. autoPolynomial Polynomial_createFromString (double lxmin, double lxmax, conststring32 s) {
  539. try {
  540. autoPolynomial me = Thing_new (Polynomial);
  541. FunctionTerms_initFromString (me.get(), lxmin, lxmax, s, 0);
  542. return me;
  543. } catch (MelderError) {
  544. Melder_throw (U"Polynomial not created from string.");
  545. }
  546. }
  547. void Polynomial_scaleCoefficients_monic (Polynomial me) {
  548. double cn = my coefficients [my numberOfCoefficients];
  549. if (cn == 1 || my numberOfCoefficients <= 1)
  550. return;
  551. for (integer i = 1; i < my numberOfCoefficients; i ++)
  552. my coefficients [i] /= cn;
  553. my coefficients [my numberOfCoefficients] = 1.0;
  554. }
  555. /*
  556. Transform the polynomial as if the domain were [xmin, xmax].
  557. Some polynomials (Legendre) are defined on the domain [-1,1]. The domain
  558. for x may be extended to [xmin, xmax] by a transformation such as
  559. x' = (2 * x - (xmin + xmax)) / (xmax - xmin) -1 < x' < x.
  560. This procedure transforms x' back to x.
  561. */
  562. autoPolynomial Polynomial_scaleX (Polynomial me, double xmin, double xmax) {
  563. try {
  564. Melder_assert (xmin < xmax);
  565. autoPolynomial thee = Polynomial_create (xmin, xmax, my numberOfCoefficients - 1);
  566. thy coefficients [1] = my coefficients [1];
  567. if (my numberOfCoefficients == 1)
  568. return thee;
  569. // x = a x + b
  570. // Constraints:
  571. // my xmin = a xmin + b; a = (my xmin - my xmax) / (xmin - xmax);
  572. // my xmax = a xmax + b; b = my xmin - a * xmin
  573. double a = (my xmin - my xmax) / (xmin - xmax);
  574. double b = my xmin - a * xmin;
  575. thy coefficients [2] = my coefficients [2] * a;
  576. thy coefficients [1] += my coefficients [2] * b;
  577. if (my numberOfCoefficients == 2)
  578. return thee;
  579. autoNUMvector<double> buf (1, 3 * my numberOfCoefficients);
  580. double *pn = buf.peek();
  581. double *pnm1 = pn + my numberOfCoefficients;
  582. double *pnm2 = pnm1 + my numberOfCoefficients;
  583. // Start the recursion: P [1] = a x + b; P [0] = 1;
  584. pnm1 [2] = a;
  585. pnm1 [1] = b;
  586. pnm2 [1] = 1;
  587. for (integer n = 2; n <= my numberOfCoefficients - 1; n ++) {
  588. double *t1 = pnm1, *t2 = pnm2;
  589. NUMpolynomial_recurrence (pn, n, a, b, 0, pnm1, pnm2);
  590. if (my coefficients [n + 1] != 0) {
  591. for (integer j = 1; j <= n + 1; j ++)
  592. thy coefficients [j] += my coefficients [n + 1] * pn [j];
  593. }
  594. pnm1 = pn;
  595. pnm2 = t1;
  596. pn = t2;
  597. }
  598. return thee;
  599. } catch (MelderError) {
  600. Melder_throw (me, U": cannot scale.");
  601. }
  602. }
  603. double Polynomial_evaluate (Polynomial me, double x) {
  604. return my v_evaluate (x);
  605. }
  606. dcomplex Polynomial_evaluate_z (Polynomial me, dcomplex z) {
  607. return my v_evaluate_z (z);
  608. }
  609. static void Polynomial_evaluate_z_cart (Polynomial me, double r, double phi, double *re, double *im) {
  610. double rn = 1;
  611. *re = my coefficients [1];
  612. *im = 0.0;
  613. if (r == 0.0)
  614. return;
  615. for (integer i = 2; i <= my numberOfCoefficients; i ++) {
  616. rn *= r;
  617. double arg = (i - 1) * phi;
  618. *re += my coefficients [i] * rn * cos (arg);
  619. *im += my coefficients [i] * rn * sin (arg);
  620. }
  621. }
  622. autoPolynomial Polynomial_getDerivative (Polynomial me) {
  623. try {
  624. if (my numberOfCoefficients == 1)
  625. return Polynomial_create (my xmin, my xmax, 0);
  626. autoPolynomial thee = Polynomial_create (my xmin, my xmax, my numberOfCoefficients - 2);
  627. for (integer i = 1; i <= thy numberOfCoefficients; i ++)
  628. thy coefficients [i] = i * my coefficients [i + 1];
  629. return thee;
  630. } catch (MelderError) {
  631. Melder_throw (me, U": no derivative created.");
  632. }
  633. }
  634. autoPolynomial Polynomial_getPrimitive (Polynomial me, double constant) {
  635. try {
  636. autoPolynomial thee = Polynomial_create (my xmin, my xmax, my numberOfCoefficients);
  637. for (integer i = 1; i <= my numberOfCoefficients; i ++)
  638. thy coefficients [i + 1] = my coefficients [i] / i;
  639. thy coefficients [1] = constant;
  640. return thee;
  641. } catch (MelderError) {
  642. Melder_throw (me, U": no primitive created.");
  643. }
  644. }
  645. /* P(x)= (x-roots [1])*(x-roots [2])*..*(x-roots [numberOfRoots]) */
  646. void Polynomial_initFromRealRoots (Polynomial me, constVEC roots) {
  647. try {
  648. FunctionTerms_extendCapacityIf (me, roots.size + 1);
  649. double *c = & my coefficients [1];
  650. integer n = 1;
  651. c [0] = - roots [1];
  652. c [1] = 1.0;
  653. for (integer i = 2; i <= roots.size; i ++) {
  654. c [n + 1] = c [n];
  655. for (integer j = n; j >= 1; j --)
  656. c [j] = c [j - 1] - c [j] * roots [i];
  657. c [0] *= -roots [i];
  658. n ++;
  659. }
  660. my numberOfCoefficients = n + 1;
  661. } catch (MelderError) {
  662. Melder_throw (me, U": not initalized from real roots.");
  663. }
  664. }
  665. autoPolynomial Polynomial_createFromRealRootsString (double xmin, double xmax, conststring32 s) {
  666. try {
  667. autoPolynomial me = Thing_new (Polynomial);
  668. autoVEC roots = VEC_createFromString (s);
  669. FunctionTerms_init (me.get(), xmin, xmax, roots.size + 1);
  670. Polynomial_initFromRealRoots (me.get(), roots.get());
  671. return me;
  672. } catch (MelderError) {
  673. Melder_throw (U"Polynomial not created from roots.");
  674. }
  675. }
  676. /* Product (i=1; a.size; (1 + a[i]*x + x^2)
  677. * Postcondition : my numberOfCoeffcients = 2*a.size+1
  678. */
  679. void Polynomial_initFromProductOfSecondOrderTerms (Polynomial me, constVEC a) {
  680. FunctionTerms_extendCapacityIf (me, 2 * a.size + 1);
  681. my coefficients [1] = my coefficients [3] = 1.0;
  682. my coefficients [2] = a [1];
  683. integer ncoef = 3;
  684. for (integer i = 2; i <= a.size; i ++) {
  685. my coefficients [ncoef + 1] = a [i] * my coefficients [ncoef] + my coefficients [ncoef - 1];
  686. my coefficients [ncoef + 2] = my coefficients [ncoef];
  687. for (integer j = ncoef; j > 2; j --)
  688. my coefficients [j] += a [i] * my coefficients [j - 1] + my coefficients [j - 2];
  689. my coefficients [2] += a [i]; // a [i] * my coefficients [1]
  690. ncoef += 2;
  691. }
  692. my numberOfCoefficients = ncoef;
  693. }
  694. autoPolynomial Polynomial_createFromProductOfSecondOrderTermsString (double xmin, double xmax, conststring32 s) {
  695. try {
  696. autoPolynomial me = Thing_new (Polynomial);
  697. autoVEC a = VEC_createFromString (s);
  698. FunctionTerms_init (me.get(), xmin, xmax, 2 * a.size + 1);
  699. Polynomial_initFromProductOfSecondOrderTerms (me.get(), a.get());
  700. return me;
  701. } catch (MelderError) {
  702. Melder_throw (U"Polynomial not created from second order terms string.");
  703. }
  704. }
  705. double Polynomial_getArea (Polynomial me, double xmin, double xmax) {
  706. if (xmax >= xmin) {
  707. xmin = my xmin;
  708. xmax = my xmax;
  709. }
  710. autoPolynomial p = Polynomial_getPrimitive (me, 0);
  711. double area = FunctionTerms_evaluate (p.get(), xmax) - FunctionTerms_evaluate (p.get(), xmin);
  712. return area;
  713. }
  714. /* P(x) * (x-a)
  715. * Postcondition: my numberOfCoefficients = old_numberOfCoefficients + 1
  716. */
  717. void Polynomial_multiply_firstOrderFactor (Polynomial me, double factor) {
  718. integer n = my numberOfCoefficients;
  719. FunctionTerms_extendCapacityIf (me, n + 1);
  720. my coefficients [n + 1] = my coefficients [n];
  721. for (integer j = n; j >= 2; j --)
  722. my coefficients [j] = my coefficients [j - 1] - my coefficients [j] * factor;
  723. my coefficients [1] *= -factor;
  724. my numberOfCoefficients += 1;
  725. }
  726. /* P(x) * (x^2 - a)
  727. * Postcondition: my numberOfCoefficients = old_numberOfCoefficients + 2
  728. */
  729. void Polynomial_multiply_secondOrderFactor (Polynomial me, double factor) {
  730. integer n = my numberOfCoefficients;
  731. FunctionTerms_extendCapacityIf (me, n + 2);
  732. my coefficients [n + 2] = my coefficients [n];
  733. my coefficients [n + 1] = my coefficients [n - 1];
  734. for (integer j = n; j >= 3; j --)
  735. my coefficients [j] = my coefficients [j - 2] - factor * my coefficients [j];
  736. my coefficients [2] *= - factor;
  737. my coefficients [1] *= - factor;
  738. my numberOfCoefficients += 2;
  739. }
  740. autoPolynomial Polynomials_multiply (Polynomial me, Polynomial thee) {
  741. try {
  742. integer n1 = my numberOfCoefficients, n2 = thy numberOfCoefficients;
  743. Melder_require (my xmax > thy xmin && my xmin < thy xmax, U"Domains should overlap.");
  744. double xmin = my xmin > thy xmin ? my xmin : thy xmin;
  745. double xmax = my xmax < thy xmax ? my xmax : thy xmax;
  746. autoPolynomial him = Polynomial_create (xmin, xmax, n1 + n2 - 2);
  747. for (integer i = 1; i <= n1; i ++) {
  748. for (integer j = 1; j <= n2; j ++) {
  749. integer k = i + j - 1;
  750. his coefficients [k] += my coefficients [i] * thy coefficients [j];
  751. }
  752. }
  753. return him;
  754. } catch (MelderError) {
  755. Melder_throw (U"Polynomials not multiplied.");
  756. }
  757. }
  758. void Polynomials_divide (Polynomial me, Polynomial thee, autoPolynomial *q, autoPolynomial *r) {
  759. integer degree, m = my numberOfCoefficients, n = thy numberOfCoefficients;
  760. if (! q && ! r)
  761. return;
  762. autoNUMvector<double> qc (1, m);
  763. autoNUMvector<double> rc (1, m);
  764. autoPolynomial aq, ar;
  765. polynomial_divide (my coefficients, m, thy coefficients, n, qc.peek(), rc.peek());
  766. if (q) {
  767. degree = std::max (m - n, (integer) 0);
  768. aq = Polynomial_create (my xmin, my xmax, degree);
  769. if (degree >= 0)
  770. NUMvector_copyElements (qc.peek(), aq -> coefficients, 1, degree + 1);
  771. *q = aq.move();
  772. }
  773. if (r) {
  774. degree = n - 2;
  775. if (m >= n)
  776. degree --;
  777. if (degree < 0)
  778. degree = 0;
  779. while (degree > 1 && rc [degree] == 0.0)
  780. degree --;
  781. ar = Polynomial_create (my xmin, my xmax, degree);
  782. NUMvector_copyElements (rc.peek(), ar -> coefficients, 1, degree + 1);
  783. *r = ar.move();
  784. }
  785. }
  786. /******** LegendreSeries ********************************************/
  787. Thing_implement (LegendreSeries, FunctionTerms, 0);
  788. double structLegendreSeries :: v_evaluate (double x) {
  789. double p = our coefficients [1];
  790. // Transform x from domain [xmin, xmax] to domain [-1, 1]
  791. if (x < our xmin || x > our xmax)
  792. return undefined;
  793. double pim1 = x = (2 * x - our xmin - our xmax) / (our xmax - our xmin);
  794. if (numberOfCoefficients > 1) {
  795. double pim2 = 1, twox = 2.0 * x, f2 = x, d = 1.0;
  796. p += our coefficients [2] * pim1;
  797. for (integer i = 3; i <= our numberOfCoefficients; i ++) {
  798. double f1 = d ++;
  799. f2 += twox;
  800. double pi = (f2 * pim1 - f1 * pim2) / d;
  801. p += our coefficients [i] * pi;
  802. pim2 = pim1; pim1 = pi;
  803. }
  804. }
  805. return p;
  806. }
  807. void structLegendreSeries :: v_evaluateTerms (double x, double terms []) {
  808. if (x < our xmin || x > our xmax) {
  809. for (integer i = 1; i <= numberOfCoefficients; i ++)
  810. terms [i] = undefined;
  811. return;
  812. }
  813. // Transform x from domain [xmin, xmax] to domain [-1, 1]
  814. x = (2.0 * x - our xmin - our xmax) / (our xmax - our xmin);
  815. terms [1] = 1;
  816. if (our numberOfCoefficients > 1) {
  817. double twox = 2.0 * x, f2 = x, d = 1.0;
  818. terms [2] = x;
  819. for (integer i = 3; i <= numberOfCoefficients; i ++) {
  820. double f1 = d ++;
  821. f2 += twox;
  822. terms [i] = (f2 * terms [i - 1] - f1 * terms [i - 2]) / d;
  823. }
  824. }
  825. }
  826. void structLegendreSeries :: v_getExtrema (double x1, double x2, double *p_xmin, double *p_ymin, double *p_xmax, double *p_ymax) {
  827. try {
  828. autoPolynomial p = LegendreSeries_to_Polynomial (this);
  829. FunctionTerms_getExtrema (p.get(), x1, x2, p_xmin, p_ymin, p_xmax, p_ymax);
  830. } catch (MelderError) {
  831. structFunctionTerms :: v_getExtrema (x1, x2, p_xmin, p_ymin, p_xmax, p_ymax);
  832. Melder_clearError ();
  833. }
  834. }
  835. autoLegendreSeries LegendreSeries_create (double xmin, double xmax, integer numberOfPolynomials) {
  836. try {
  837. autoLegendreSeries me = Thing_new (LegendreSeries);
  838. FunctionTerms_init (me.get(), xmin, xmax, numberOfPolynomials);
  839. return me;
  840. } catch (MelderError) {
  841. Melder_throw (U"LegendreSeries not created.");
  842. }
  843. }
  844. autoLegendreSeries LegendreSeries_createFromString (double xmin, double xmax, conststring32 s) {
  845. try {
  846. autoLegendreSeries me = Thing_new (LegendreSeries);
  847. FunctionTerms_initFromString (me.get(), xmin, xmax, s, 0);
  848. return me;
  849. } catch (MelderError) {
  850. Melder_throw (U"LegendreSeries not created from string.");
  851. }
  852. }
  853. autoLegendreSeries LegendreSeries_getDerivative (LegendreSeries me) {
  854. try {
  855. autoLegendreSeries thee = LegendreSeries_create (my xmin, my xmax, my numberOfCoefficients - 1);
  856. for (integer n = 1; n <= my numberOfCoefficients - 1; n ++) {
  857. // P [n]'(x) = Sum (k=0..nonNegative, (2n - 4k - 1) P [n-2k-1](x))
  858. integer n2 = n - 1;
  859. for (integer k = 0; n2 >= 0; k ++, n2 -= 2)
  860. thy coefficients [n2 + 1] += (2 * n - 4 * k - 1) * my coefficients [n + 1];
  861. }
  862. return thee;
  863. } catch (MelderError) {
  864. Melder_throw (me, U": no derivative created.");
  865. }
  866. }
  867. autoPolynomial LegendreSeries_to_Polynomial (LegendreSeries me) {
  868. try {
  869. double xmin = -1, xmax = 1;
  870. autoPolynomial thee = Polynomial_create (xmin, xmax, my numberOfCoefficients - 1);
  871. thy coefficients [1] = my coefficients [1]; /* * p [1] */
  872. if (my numberOfCoefficients == 1)
  873. return thee;
  874. thy coefficients [2] = my coefficients [2]; /* * p [2] */
  875. if (my numberOfCoefficients > 2) {
  876. autoNUMvector<double> buf (1, 3 * my numberOfCoefficients);
  877. double *pn = buf.peek();
  878. double *pnm1 = pn + my numberOfCoefficients;
  879. double *pnm2 = pnm1 + my numberOfCoefficients;
  880. // Start the recursion: P [1] = x; P [0] = 1;
  881. pnm1 [2] = 1;
  882. pnm2 [1] = 1;
  883. for (integer n = 2; n <= my numberOfCoefficients - 1; n ++) {
  884. double a = (2.0 * n - 1.0) / (double) n;
  885. double c = - (n - 1.0) / (double) n;
  886. double *t1 = pnm1, *t2 = pnm2;
  887. NUMpolynomial_recurrence (pn, n, a, 0, c, pnm1, pnm2);
  888. if (my coefficients [n + 1] != 0.0) {
  889. for (integer j = 1; j <= n + 1; j ++)
  890. thy coefficients [j] += my coefficients [n + 1] * pn [j];
  891. }
  892. pnm1 = pn; pnm2 = t1; pn = t2;
  893. }
  894. }
  895. if (my xmin != xmin || my xmax != xmax)
  896. thee = Polynomial_scaleX (thee.get(), my xmin, my xmax);
  897. return thee;
  898. } catch (MelderError) {
  899. Melder_throw (me, U": not converted to Polynomial.");
  900. }
  901. }
  902. /********* Roots ****************************************************/
  903. Thing_implement (Roots, ComplexVector, 0);
  904. autoRoots Roots_create (integer numberOfRoots) {
  905. try {
  906. autoRoots me = Thing_new (Roots);
  907. ComplexVector_init (me.get(), 1, numberOfRoots);
  908. return me;
  909. } catch (MelderError) {
  910. Melder_throw (U"Roots not created.");
  911. }
  912. }
  913. void Roots_fixIntoUnitCircle (Roots me) {
  914. dcomplex z10 { 1.0, 0.0 };
  915. for (integer i = my min; i <= my max; i ++) {
  916. if (dcomplex_abs (my v [i]) > 1.0)
  917. my v [i] = dcomplex_div (z10, dcomplex_conjugate (my v [i]));
  918. }
  919. }
  920. static void NUMdcvector_extrema_re (dcomplex v [], integer lo, integer hi, double *min, double *max) {
  921. *min = *max = v [lo].re;
  922. for (integer i = lo + 1; i <= hi; i ++) {
  923. if (v [i].re < *min) {
  924. *min = v [i].re;
  925. } else if (v [i].re > *max) {
  926. *max = v [i].re;
  927. }
  928. }
  929. }
  930. static void NUMdcvector_extrema_im (dcomplex v [], integer lo, integer hi, double *min, double *max) {
  931. *min = *max = v [lo].im;
  932. for (integer i = lo + 1; i <= hi; i ++) {
  933. if (v [i]. im < *min) {
  934. *min = v [i]. im;
  935. } else if (v [i]. im > *max) {
  936. *max = v [i]. im;
  937. }
  938. }
  939. }
  940. void Roots_draw (Roots me, Graphics g, double rmin, double rmax, double imin, double imax,
  941. conststring32 symbol, int fontSize, bool garnish)
  942. {
  943. int oldFontSize = Graphics_inqFontSize (g);
  944. double eps = 1e-6;
  945. if (rmax <= rmin) {
  946. NUMdcvector_extrema_re (my v, 1, my max, & rmin, & rmax);
  947. }
  948. double denominator = fabs (rmax) > fabs (rmin) ? fabs (rmax) : fabs (rmin);
  949. if (denominator == 0.0)
  950. denominator = 1.0;
  951. if (fabs ((rmax - rmin) / denominator) < eps) {
  952. rmin -= 1.0;
  953. rmax += 1.0;
  954. }
  955. if (imax <= imin) {
  956. NUMdcvector_extrema_im (my v, 1, my max, & imin, & imax);
  957. }
  958. denominator = fabs (imax) > fabs (imin) ? fabs (imax) : fabs (imin);
  959. if (denominator == 0.0)
  960. denominator = 1.0;
  961. if (fabs ((imax - imin) / denominator) < eps) {
  962. imin -= 1;
  963. imax += 1;
  964. }
  965. Graphics_setInner (g);
  966. Graphics_setWindow (g, rmin, rmax, imin, imax);
  967. Graphics_setFontSize (g, fontSize);
  968. Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
  969. for (integer i = 1; i <= my max; i ++) {
  970. double re = my v [i].re, im = my v [i].im;
  971. if (re >= rmin && re <= rmax && im >= imin && im <= imax)
  972. Graphics_text (g, re, im, symbol);
  973. }
  974. Graphics_setFontSize (g, oldFontSize);
  975. Graphics_unsetInner (g);
  976. if (garnish) {
  977. Graphics_drawInnerBox (g);
  978. if (rmin * rmax < 0.0)
  979. Graphics_markLeft (g, 0.0, true, true, true, U"0");
  980. if (imin * imax < 0.0)
  981. Graphics_markBottom (g, 0.0, true, true, true, U"0");
  982. Graphics_marksLeft (g, 2, true, true, false);
  983. Graphics_textLeft (g, true, U"Imaginary part");
  984. Graphics_marksBottom (g, 2, true, true, false);
  985. Graphics_textBottom (g, true, U"Real part");
  986. }
  987. }
  988. autoRoots Polynomial_to_Roots (Polynomial me) {
  989. try {
  990. integer np1 = my numberOfCoefficients, n = np1 - 1, n2 = n * n;
  991. Melder_require (n > 0, U"Cannot find roots of a constant function.");
  992. // Allocate storage for Hessenberg matrix (n * n) plus real and imaginary
  993. // parts of eigenvalues wr [1..n] and wi [1..n].
  994. autoNUMvector <double> hes (1, n2 + n + n);
  995. double *wr = & hes [n2];
  996. double *wi = & hes [n2 + n];
  997. // Fill the upper Hessenberg matrix (storage is Fortran)
  998. // C: [i] [j] -> Fortran: (j-1)*n + i
  999. for (integer i = 1; i <= n; i ++) {
  1000. hes [(i - 1) * n + 1] = - (my coefficients [np1 - i] / my coefficients [np1]);
  1001. if (i < n) {
  1002. hes [(i - 1) * n + 1 + i] = 1;
  1003. }
  1004. }
  1005. // Find out the working storage needed
  1006. char job = 'E', compz = 'N';
  1007. integer ilo = 1, ihi = n, ldh = n, ldz = n, lwork = -1, info;
  1008. double *z = 0, wt [1];
  1009. NUMlapack_dhseqr (&job, &compz, &n, &ilo, &ihi, &hes [1], &ldh, &wr [1], &wi [1], z, &ldz, wt, &lwork, &info);
  1010. if (info != 0) {
  1011. if (info < 0)
  1012. Melder_throw (U"Programming error. Argument ", info, U" in NUMlapack_dhseqr has illegal value.");
  1013. }
  1014. lwork = Melder_ifloor (wt [0]);
  1015. autoNUMvector <double> work (1, lwork);
  1016. // Find eigenvalues.
  1017. NUMlapack_dhseqr (&job, &compz, &n, &ilo, &ihi, &hes [1], &ldh, &wr [1], &wi [1], z, &ldz, &work [1], &lwork, &info);
  1018. integer nrootsfound = n;
  1019. integer ioffset = 0;
  1020. if (info > 0) {
  1021. // if INFO = i, NUMlapack_dhseqr failed to compute all of the eigenvalues. Elements i+1:n of
  1022. // WR and WI contain those eigenvalues which have been successfully computed
  1023. nrootsfound -= info;
  1024. Melder_require (nrootsfound > 0, U"No roots found.");
  1025. Melder_warning (U"Calculated only ", nrootsfound, U" roots.");
  1026. ioffset = info;
  1027. } else if (info < 0) {
  1028. Melder_throw (U"Programming error. Argument ", info, U" in NUMlapack_dhseqr has illegal value.");
  1029. }
  1030. autoRoots thee = Roots_create (nrootsfound);
  1031. for (integer i = 1; i <= nrootsfound; i ++) {
  1032. (thy v [i]).re = wr [ioffset + i];
  1033. (thy v [i]).im = wi [ioffset + i];
  1034. }
  1035. Roots_Polynomial_polish (thee.get(), me);
  1036. return thee;
  1037. } catch (MelderError) {
  1038. Melder_throw (me, U": no roots can be calculated.");
  1039. }
  1040. }
  1041. void Roots_sort (Roots me) {
  1042. (void) me;
  1043. }
  1044. // Precondition: complex roots occur in pairs (a,bi), (a,-bi) with b>0
  1045. void Roots_Polynomial_polish (Roots me, Polynomial thee) {
  1046. integer i = my min, maxit = 80;
  1047. while (i <= my max) {
  1048. double im = my v [i].im, re = my v [i].re;
  1049. if (im != 0.0) {
  1050. Polynomial_polish_complexroot_nr (thee, & my v [i], maxit);
  1051. if (i < my max && im == -my v [i + 1].im && re == my v [i + 1].re) {
  1052. my v [i + 1].re = my v [i].re; my v [i + 1].im = -my v [i].im;
  1053. i ++;
  1054. }
  1055. } else {
  1056. Polynomial_polish_realroot (thee, & (my v [i].re), maxit);
  1057. }
  1058. i ++;
  1059. }
  1060. }
  1061. autoPolynomial Roots_to_Polynomial (Roots me, bool rootsAreReal) {
  1062. try {
  1063. (void) me;
  1064. autoPolynomial thee;
  1065. if (! rootsAreReal)
  1066. throw MelderError();
  1067. return thee;
  1068. } catch (MelderError) {
  1069. Melder_throw (U"Not implemented yet");
  1070. }
  1071. }
  1072. static void dpoly_nr (double x, double *f, double *df, void *closure) {
  1073. Polynomial_evaluateWithDerivative ((Polynomial) closure, x, f, df);
  1074. }
  1075. double Polynomial_findOneSimpleRealRoot_nr (Polynomial me, double xmin, double xmax) {
  1076. double root;
  1077. NUMnrbis (dpoly_nr, xmin, xmax, me, &root);
  1078. return root;
  1079. }
  1080. static double dpoly_r (double x, void *closure) {
  1081. return Polynomial_evaluate ((Polynomial) closure, x);
  1082. }
  1083. double Polynomial_findOneSimpleRealRoot_ridders (Polynomial me, double xmin, double xmax) {
  1084. return NUMridders (dpoly_r, xmin, xmax, me);
  1085. }
  1086. void Polynomial_divide_firstOrderFactor (Polynomial me, double factor, double *p_remainder) { // P(x)/(x-a)
  1087. double remainder = undefined;
  1088. if (my numberOfCoefficients > 1) {
  1089. remainder = my coefficients [my numberOfCoefficients];
  1090. for (integer j = my numberOfCoefficients - 1; j > 0; j --) {
  1091. double tmp = my coefficients [j];
  1092. my coefficients [j] = remainder;
  1093. remainder = tmp + remainder * factor;
  1094. }
  1095. my numberOfCoefficients --;
  1096. } else {
  1097. my coefficients [1] = 0.0;
  1098. }
  1099. if (p_remainder)
  1100. *p_remainder = remainder;
  1101. }
  1102. void Polynomial_divide_secondOrderFactor (Polynomial me, double factor) {
  1103. if (my numberOfCoefficients > 2) {
  1104. integer n = my numberOfCoefficients;
  1105. /* c [1]+c [2]*x...c [n+1]*x^n / (x^2 - a) = r [1]+r [2]*x+...r [n-1]x^(n-2) + possible remainder a [1]+a [2]*x)
  1106. * r [j] = c [j+2]+factor*r [j+2] */
  1107. double cjp2 = my coefficients [n];
  1108. double cjp1 = my coefficients [n - 1];
  1109. my coefficients [n] = my coefficients [n - 1] = 0.0;
  1110. for (integer j = n - 2; j > 0; j --) {
  1111. double cj = my coefficients [j];
  1112. my coefficients [j] = cjp2 + factor * my coefficients [j + 2];
  1113. cjp2 = cjp1;
  1114. cjp1 = cj;
  1115. }
  1116. my numberOfCoefficients -= 2;
  1117. } else {
  1118. my numberOfCoefficients = 1;
  1119. my coefficients [1] = 0.0;
  1120. }
  1121. }
  1122. void Roots_setRoot (Roots me, integer index, double re, double im) {
  1123. Melder_require (index >= my min && index <= my max, U"Index should be in interval [1, ", my max, U"].");
  1124. my v [index].re = re;
  1125. my v [index].im = im;
  1126. }
  1127. dcomplex Roots_evaluate_z (Roots me, dcomplex z) {
  1128. dcomplex result = {1, 0};
  1129. for (integer i = my min; i <= my max; i ++) {
  1130. dcomplex t = dcomplex_sub (z, my v [i]);
  1131. result = dcomplex_mul (result, t);
  1132. }
  1133. return result;
  1134. }
  1135. autoSpectrum Roots_to_Spectrum (Roots me, double nyquistFrequency, integer numberOfFrequencies, double radius) {
  1136. try {
  1137. Melder_require (numberOfFrequencies > 1,
  1138. U"Number of frequencies should be greater than 1.");
  1139. autoSpectrum thee = Spectrum_create (nyquistFrequency, numberOfFrequencies);
  1140. double phi = NUMpi / (numberOfFrequencies - 1);
  1141. dcomplex z;
  1142. for (integer i = 1; i <= numberOfFrequencies; i ++) {
  1143. z.re = radius * cos ( (i - 1) * phi);
  1144. z.im = radius * sin ( (i - 1) * phi);
  1145. dcomplex s = Roots_evaluate_z (me, z);
  1146. thy z [1] [i] = s.re; thy z [2] [i] = s.im;
  1147. }
  1148. return thee;
  1149. } catch (MelderError) {
  1150. Melder_throw (me, U": no Spectrum calculated.");
  1151. }
  1152. }
  1153. integer Roots_getNumberOfRoots (Roots me) {
  1154. return my max;
  1155. }
  1156. dcomplex Roots_getRoot (Roots me, integer index) {
  1157. Melder_require (index > 0 && index <= my max,
  1158. U"Root index out of range.");
  1159. return my v [index];
  1160. }
  1161. /* Can be speeded up by doing a FFT */
  1162. autoSpectrum Polynomial_to_Spectrum (Polynomial me, double nyquistFrequency, integer numberOfFrequencies, double radius) {
  1163. try {
  1164. Melder_require (numberOfFrequencies > 1,
  1165. U"Number of frequencies should be greater than 1.");
  1166. autoSpectrum thee = Spectrum_create (nyquistFrequency, numberOfFrequencies);
  1167. double phi = NUMpi / (numberOfFrequencies - 1);
  1168. for (integer i = 1; i <= numberOfFrequencies; i ++) {
  1169. double re, im;
  1170. Polynomial_evaluate_z_cart (me, radius, (i - 1) * phi, &re, &im);
  1171. thy z [1] [i] = re;
  1172. thy z [2] [i] = im;
  1173. }
  1174. return thee;
  1175. } catch (MelderError) {
  1176. Melder_throw (me, U": no Spectrum calculated.");
  1177. }
  1178. }
  1179. /****** ChebyshevSeries ******************************************/
  1180. Thing_implement (ChebyshevSeries, FunctionTerms, 0);
  1181. /*
  1182. p(x) = sum (k=1..numberOfCoefficients, c [k]*T [k](x')) - c [1] / 2;
  1183. Numerical evaluation via Clenshaw's recurrence equation (NRC: 5.8.11)
  1184. d [m+1] = d [m] = 0;
  1185. d [j] = 2 x' d [j+1] - d [j+2] + c [j];
  1186. p(x) = d [0] = x' d [1] - d [2] + c [0] / 2;
  1187. x' = (2 * x - xmin - xmax) / (xmax - xmin)
  1188. */
  1189. double structChebyshevSeries :: v_evaluate (double x) {
  1190. if (x < our xmin || x > our xmax)
  1191. return undefined;
  1192. double d1 = 0.0, d2 = 0.0;
  1193. if (numberOfCoefficients > 1) {
  1194. // Transform x from domain [xmin, xmax] to domain [-1, 1]
  1195. x = (2.0 * x - our xmin - our xmax) / (our xmax - our xmin);
  1196. double x2 = 2.0 * x;
  1197. for (integer i = our numberOfCoefficients; i > 1; i --) {
  1198. double tmp = d1;
  1199. d1 = x2 * d1 - d2 + our coefficients [i];
  1200. d2 = tmp;
  1201. }
  1202. }
  1203. return x * d1 - d2 + our coefficients [1];
  1204. }
  1205. /*
  1206. T [n](x) = 2*x*T [n-1] - T [n-2](x) n >= 2
  1207. */
  1208. void structChebyshevSeries :: v_evaluateTerms (double x, double *terms) {
  1209. if (x < our xmin || x > our xmax) {
  1210. for (integer i = 1; i <= our numberOfCoefficients; i ++)
  1211. terms [i] = undefined;
  1212. return;
  1213. }
  1214. terms [1] = 1.0;
  1215. if (numberOfCoefficients > 1) {
  1216. // Transform x from domain [xmin, xmax] to domain [-1, 1]
  1217. terms [2] = x = (2.0 * x - xmin - xmax) / (xmax - xmin);
  1218. for (integer i = 3; i <= numberOfCoefficients; i ++)
  1219. terms [i] = 2.0 * x * terms [i - 1] - terms [i - 2];
  1220. }
  1221. }
  1222. void structChebyshevSeries :: v_getExtrema (double x1, double x2, double *p_xmin, double *p_ymin, double *p_xmax, double *p_ymax) {
  1223. try {
  1224. autoPolynomial p = ChebyshevSeries_to_Polynomial (this);
  1225. FunctionTerms_getExtrema (p.get(), x1, x2, p_xmin, p_ymin, p_xmax, p_ymax);
  1226. } catch (MelderError) {
  1227. Melder_throw (this, U"Extrema cannot be calculated");
  1228. }
  1229. }
  1230. autoChebyshevSeries ChebyshevSeries_create (double lxmin, double lxmax, integer numberOfPolynomials) {
  1231. try {
  1232. autoChebyshevSeries me = Thing_new (ChebyshevSeries);
  1233. FunctionTerms_init (me.get(), lxmin, lxmax, numberOfPolynomials);
  1234. return me;
  1235. } catch (MelderError) {
  1236. Melder_throw (U"ChebyshevSeries not created.");
  1237. }
  1238. }
  1239. autoChebyshevSeries ChebyshevSeries_createFromString (double lxmin, double lxmax, conststring32 s) {
  1240. try {
  1241. autoChebyshevSeries me = Thing_new (ChebyshevSeries);
  1242. FunctionTerms_initFromString (me.get(), lxmin, lxmax, s, 0);
  1243. return me;
  1244. } catch (MelderError) {
  1245. Melder_throw (U"ChebyshevSeries not created from string.");
  1246. };
  1247. }
  1248. autoPolynomial ChebyshevSeries_to_Polynomial (ChebyshevSeries me) {
  1249. try {
  1250. double xmin = -1, xmax = 1;
  1251. autoPolynomial thee = Polynomial_create (xmin, xmax, my numberOfCoefficients - 1);
  1252. thy coefficients [1] = my coefficients [1] /* * p [1] */;
  1253. if (my numberOfCoefficients == 1)
  1254. return thee;
  1255. thy coefficients [2] = my coefficients [2];
  1256. if (my numberOfCoefficients > 2) {
  1257. autoNUMvector<double> buf (1, 3 * my numberOfCoefficients);
  1258. double *pn = buf.peek();
  1259. double *pnm1 = pn + my numberOfCoefficients;
  1260. double *pnm2 = pnm1 + my numberOfCoefficients;
  1261. // Start the recursion: T [1] = x; T [0] = 1;
  1262. pnm1 [2] = 1.0;
  1263. pnm2 [1] = 1.0;
  1264. double a = 2.0, b = 0.0, c = -1.0;
  1265. for (integer n = 2; n <= my numberOfCoefficients - 1; n ++) {
  1266. double *t1 = pnm1, *t2 = pnm2;
  1267. NUMpolynomial_recurrence (pn, n, a, b, c, pnm1, pnm2);
  1268. if (my coefficients [n + 1] != 0) {
  1269. for (integer j = 1; j <= n + 1; j ++)
  1270. thy coefficients [j] += my coefficients [n + 1] * pn [j];
  1271. }
  1272. pnm1 = pn;
  1273. pnm2 = t1;
  1274. pn = t2;
  1275. }
  1276. }
  1277. if (my xmin != xmin || my xmax != xmax)
  1278. thee = Polynomial_scaleX (thee.get(), my xmin, my xmax);
  1279. return thee;
  1280. } catch (MelderError) {
  1281. Melder_throw (me, U"; not converted to Polynomial.");
  1282. };
  1283. }
  1284. void FunctionTerms_RealTier_fit (FunctionTerms me, RealTier thee, int freeze [], double tol, int ic, autoCovariance *c) {
  1285. try {
  1286. integer numberOfData = thy points.size;
  1287. integer numberOfParameters = my numberOfCoefficients;
  1288. integer numberOfFreeParameters = numberOfParameters;
  1289. Melder_require (numberOfData > 1, U"The number of data point should be larger than 1.");
  1290. autoFunctionTerms frozen = Data_copy (me);
  1291. autoVEC terms = VECzero (my numberOfCoefficients);
  1292. autoVEC p = VECzero (numberOfParameters);
  1293. autoVEC y_residual = VECzero (numberOfData);
  1294. autoCovariance ac;
  1295. if (ic)
  1296. ac = (Covariance_create (numberOfParameters));
  1297. integer k = 1;
  1298. for (integer j = 1; j <= my numberOfCoefficients; j ++) {
  1299. if (freeze && freeze [j]) {
  1300. numberOfFreeParameters--;
  1301. } else {
  1302. p [k] = my coefficients [j]; k ++;
  1303. frozen -> coefficients [j] = 0;
  1304. }
  1305. }
  1306. Melder_require (numberOfFreeParameters > 0, U"No free parameters left.");
  1307. autoSVD svd = SVD_create (numberOfData, numberOfFreeParameters);
  1308. double sigma = RealTier_getStandardDeviation_points (thee, my xmin, my xmax);
  1309. Melder_require (isdefined (sigma), U"Not enough data points in fit interval.");
  1310. for (integer i = 1; i <= numberOfData; i ++) {
  1311. // Only 'residual variance' must be explained by the model
  1312. // Evaluate only with the frozen parameters
  1313. RealPoint point = thy points.at [i];
  1314. double x = point -> number;
  1315. double y = point -> value;
  1316. double y_frozen = ( numberOfFreeParameters == numberOfParameters ? 0.0 :
  1317. FunctionTerms_evaluate (frozen.get(), x));
  1318. y_residual [i] = (y - y_frozen) / sigma;
  1319. // Data matrix
  1320. FunctionTerms_evaluateTerms (me, x, terms.at);
  1321. k = 0;
  1322. for (integer j = 1; j <= my numberOfCoefficients; j ++) {
  1323. if (! freeze || ! freeze [j]) {
  1324. k ++;
  1325. svd -> u [i] [k] = terms [j] / sigma;
  1326. }
  1327. }
  1328. }
  1329. // SVD and evaluation of the singular values
  1330. if (tol > 0.0)
  1331. SVD_setTolerance (svd.get(), tol);
  1332. SVD_compute (svd.get());
  1333. autoVEC result = SVD_solve (svd.get(), y_residual.get());
  1334. // Put fitted values at correct position
  1335. k = 1;
  1336. for (integer j = 1; j <= my numberOfCoefficients; j ++) {
  1337. if (! freeze || ! freeze [j])
  1338. my coefficients [j] = result [k ++];
  1339. }
  1340. if (ic)
  1341. svdcvm (svd -> v.at, numberOfFreeParameters, numberOfParameters, freeze, svd -> d.at, ac -> data.at);
  1342. if (c) *c = ac.move();
  1343. } catch (MelderError) {
  1344. Melder_throw (me, U" & ", thee, U": no fit.");
  1345. }
  1346. }
  1347. autoPolynomial RealTier_to_Polynomial (RealTier me, integer degree, double tol, int ic, autoCovariance *cvm) {
  1348. try {
  1349. autoPolynomial thee = Polynomial_create (my xmin, my xmax, degree);
  1350. FunctionTerms_RealTier_fit (thee.get(), me, 0, tol, ic, cvm);
  1351. return thee;
  1352. } catch (MelderError) {
  1353. Melder_throw (me, U": no Polynomial fitted.");
  1354. }
  1355. }
  1356. autoLegendreSeries RealTier_to_LegendreSeries (RealTier me, integer degree, double tol, int ic, autoCovariance *cvm) {
  1357. try {
  1358. autoLegendreSeries thee = LegendreSeries_create (my xmin, my xmax, degree);
  1359. FunctionTerms_RealTier_fit (thee.get(), me, 0, tol, ic, cvm);
  1360. return thee;
  1361. } catch (MelderError) {
  1362. Melder_throw (me, U": no LegendreSeries fitted.");
  1363. }
  1364. }
  1365. autoChebyshevSeries RealTier_to_ChebyshevSeries (RealTier me, integer degree, double tol, int ic, autoCovariance *cvm) {
  1366. try {
  1367. autoChebyshevSeries thee = ChebyshevSeries_create (my xmin, my xmax, degree);
  1368. FunctionTerms_RealTier_fit (thee.get(), me, 0, tol, ic, cvm);
  1369. return thee;
  1370. } catch (MelderError) {
  1371. Melder_throw (me, U":no ChebyshevSeries fitted.");
  1372. };
  1373. }
  1374. /******* Splines *************************************************/
  1375. /*
  1376. Functions for calculating an mspline and an ispline. These functions should replace
  1377. the functions in NUM2.c. Before we can do that we first have to adapt the spline-
  1378. dependencies in MDS.c.
  1379. Formally nKnots == order + numberOfInteriorKnots + order.
  1380. We forget about the multiple knots at start and end.
  1381. Our point-sequece xmin < interiorKont [1] < ... < interiorKnot [n] < xmax.
  1382. nKnots is now numberOfinteriorKnots + 2.
  1383. */
  1384. static double NUMmspline2 (constVEC points, integer order, integer index, double x) {
  1385. integer numberOfSplines = points.size + order - 2;
  1386. double m [Spline_MAXIMUM_DEGREE + 2];
  1387. Melder_assert (points.size > 2 && order > 0 && index > 0);
  1388. if (index > numberOfSplines)
  1389. return undefined;
  1390. /*
  1391. Find the range/interval where x is located.
  1392. M-splines of order k have degree k-1.
  1393. M-splines are zero outside interval [knot [i], knot [i+order]).
  1394. First and last 'order' knots are equal, i.e.,
  1395. knot [1] = ... = knot [order] && knot [nKnots-order+1] = ... knot [nKnots].
  1396. */
  1397. integer index_b = index - order + 1;
  1398. index_b = std::max (index_b, (integer) 1);
  1399. if (x < points [index_b])
  1400. return 0;
  1401. integer index_e = index_b + std::min (index, order);
  1402. index_e = std::min (points.size, index_e);
  1403. if (x > points [index_e])
  1404. return 0;
  1405. // Calculate M [i](x|1,t) according to eq.2.
  1406. for (integer k = 1; k <= order; k ++) {
  1407. integer k1 = index - order + k, k2 = k1 + 1;
  1408. m [k] = 0;
  1409. if (k1 > 0 && k2 <= points.size && x >= points [k1] && x < points [k2])
  1410. m [k] = 1 / (points [k2] - points [k1]);
  1411. }
  1412. // Iterate to get M [i](x|k,t)
  1413. for (integer k = 2; k <= order; k ++) {
  1414. for (integer j = 1; j <= order - k + 1; j ++) {
  1415. integer k1 = index - order + j, k2 = k1 + k;
  1416. if (k2 > 1 && k1 < 1) {
  1417. k1 = 1;
  1418. } else if (k2 > points.size && k1 < points.size) {
  1419. k2 = points.size;
  1420. }
  1421. if (k1 > 0 && k2 <= points.size) {
  1422. double p1 = points [k1], p2 = points [k2];
  1423. m [j] = k * ((x - p1) * m [j] + (p2 - x) * m [j + 1]) /
  1424. ((k - 1) * (p2 - p1));
  1425. }
  1426. }
  1427. }
  1428. return m [1];
  1429. }
  1430. static double NUMispline2 (constVEC points, integer order, integer index, double x) {
  1431. Melder_assert (points.size > 2 && order > 0 && index > 0);
  1432. integer index_b = index - order + 1;
  1433. index_b = std::max (index_b, (integer) 1);
  1434. if (x < points [index_b])
  1435. return 0.0;
  1436. integer index_e = index_b + std::min (index, order);
  1437. index_e = std::min (points.size, index_e);
  1438. if (x > points [index_e])
  1439. return 1.0;
  1440. integer j;
  1441. for (j = index_e - 1; j >= index_b; j--) {
  1442. if (x > points [j]) {
  1443. break;
  1444. }
  1445. }
  1446. // Equation 5 in Ramsay's article contains some errors!!!
  1447. // 1. the interval selection must be 'j-k <= i <= j' instead of
  1448. // 'j-k+1 <= i <= j'
  1449. // 2. the summation index m starts at 'i+1' instead of 'i'
  1450. double y = 0.0;
  1451. for (integer m = index + 1; m <= j + order; m ++) {
  1452. integer km = m - order, kmp = km + order + 1;
  1453. km = std::max (km, (integer) 1);
  1454. kmp = std::min (kmp, points.size);
  1455. y += (points [kmp] - points [km]) * NUMmspline2 (points, order + 1, m, x);
  1456. }
  1457. return y /= (order + 1);
  1458. }
  1459. Thing_implement (Spline, FunctionTerms, 0);
  1460. double structSpline :: v_evaluate (double /* x */) {
  1461. return 0.0;
  1462. }
  1463. integer structSpline :: v_getDegree () {
  1464. return degree;
  1465. }
  1466. integer structSpline :: v_getOrder () {
  1467. return degree + 1;
  1468. }
  1469. /* Precondition: FunctionTerms part inited + degree */
  1470. static void Spline_initKnotsFromString (Spline me, integer degree, conststring32 interiorKnots_string) {
  1471. Melder_require (degree <= Spline_MAXIMUM_DEGREE, U"Degree should be <= ", Spline_MAXIMUM_DEGREE, U".");
  1472. autoVEC interiorKnots = VEC_createFromString (interiorKnots_string);
  1473. VECsort_inplace (interiorKnots.get());
  1474. if (interiorKnots [1] <= my xmin || interiorKnots [interiorKnots.size] > my xmax)
  1475. Melder_throw (U"Knots should be inside domain.");
  1476. my degree = degree;
  1477. integer order = Spline_getOrder (me); /* depends on spline type !! */
  1478. integer n = interiorKnots.size + order;
  1479. Melder_require (my numberOfCoefficients == n, U"Number of coefficients should equal ", n, U".");
  1480. my numberOfKnots = interiorKnots.size + 2;
  1481. my knots = VECzero (my numberOfKnots);
  1482. for (integer i = 1; i <= interiorKnots.size; i ++) {
  1483. my knots [i + 1] = interiorKnots [i];
  1484. }
  1485. my knots [1] = my xmin;
  1486. my knots [my numberOfKnots] = my xmax;
  1487. }
  1488. void Spline_init (Spline me, double xmin, double xmax, integer degree, integer numberOfCoefficients, integer numberOfKnots) {
  1489. Melder_require (degree <= Spline_MAXIMUM_DEGREE, U"Degree should be <= ", Spline_MAXIMUM_DEGREE, U".");
  1490. FunctionTerms_init (me, xmin, xmax, numberOfCoefficients);
  1491. my knots = VECzero (numberOfKnots);
  1492. my degree = degree;
  1493. my numberOfKnots = numberOfKnots;
  1494. my knots [1] = xmin;
  1495. my knots [numberOfKnots] = xmax;
  1496. }
  1497. void Spline_drawKnots (Spline me, Graphics g, double xmin, double xmax, double ymin, double ymax, int garnish) {
  1498. integer order = Spline_getOrder (me);
  1499. if (xmax <= xmin) {
  1500. xmin = my xmin;
  1501. xmax = my xmax;
  1502. }
  1503. if (xmax < my xmin || xmin > my xmax)
  1504. return;
  1505. if (ymax <= ymin) {
  1506. double x1, x2;
  1507. FunctionTerms_getExtrema (me, xmin, xmax, &x1, &ymin, &x2, &ymax);
  1508. }
  1509. Graphics_setWindow (g, xmin, xmax, ymin, ymax);
  1510. if (my knots [1] >= xmin && my knots [1] <= xmax) {
  1511. Graphics_markTop (g, my knots [1], false, true, true,
  1512. ! garnish ? U"" :
  1513. order == 1 ? U"t__1_" :
  1514. order == 2 ? U"{t__1_, t__2_}" :
  1515. Melder_cat (U"{t__1_..t__", order, U"_}")
  1516. );
  1517. }
  1518. for (integer i = 2; i <= my numberOfKnots - 1; i ++) {
  1519. if (my knots [i] >= xmin && my knots [i] <= xmax) {
  1520. Graphics_markTop (g, my knots [i], false, true, true,
  1521. ! garnish ? U"" :
  1522. Melder_cat (U"t__", i + order - 1, U"_")
  1523. );
  1524. }
  1525. }
  1526. if (my knots [my numberOfKnots] >= xmin && my knots [my numberOfKnots] <= xmax) {
  1527. integer numberOfKnots = ! garnish ? 0 : my numberOfKnots + 2 * (order - 1);
  1528. Graphics_markTop (g, my knots [my numberOfKnots], false, true, true,
  1529. ! garnish ? U"" :
  1530. order == 1 ? Melder_cat (U"t__", numberOfKnots, U"_") :
  1531. order == 2 ? Melder_cat (U"{t__", numberOfKnots - 1, U"_, t__", numberOfKnots, U"_}") :
  1532. Melder_cat (U"{t__", numberOfKnots - order + 1, U"_..t__", numberOfKnots, U"_}")
  1533. );
  1534. }
  1535. }
  1536. integer Spline_getOrder (Spline me) {
  1537. return my v_getOrder ();
  1538. }
  1539. autoSpline Spline_scaleX (Spline me, double xmin, double xmax) {
  1540. try {
  1541. Melder_assert (xmin < xmax);
  1542. autoSpline thee = Data_copy (me);
  1543. thy xmin = xmin;
  1544. thy xmax = xmax;
  1545. // x = a x + b
  1546. // Constraints:
  1547. // my xmin = a xmin + b; a = (my xmin - my xmax) / (xmin - xmax);
  1548. // my xmax = a xmax + b; b = my xmin - a * xmin
  1549. double a = (xmin - xmax) / (my xmin - my xmax);
  1550. double b = xmin - a * my xmin;
  1551. for (integer i = 1; i <= my numberOfKnots; i ++) {
  1552. thy knots [i] = a * my knots [i] + b;
  1553. }
  1554. return thee;
  1555. } catch (MelderError) {
  1556. Melder_throw (U"Scaled Spline not created.");
  1557. }
  1558. }
  1559. /********* MSplines ************************************************/
  1560. double structMSpline :: v_evaluate (double x) {
  1561. if (x < our xmin || x > our xmax)
  1562. return 0.0;
  1563. double result = 0.0;
  1564. for (integer i = 1; i <= numberOfCoefficients; i ++) {
  1565. if (coefficients [i] != 0.0)
  1566. result += coefficients [i] * NUMmspline2 (knots.get(), degree + 1, i, x);
  1567. }
  1568. return result;
  1569. }
  1570. void structMSpline :: v_evaluateTerms (double x, double *terms) {
  1571. if (x < our xmin || x > our xmax)
  1572. return;
  1573. for (integer i = 1; i <= numberOfCoefficients; i ++)
  1574. terms [i] = NUMmspline2 (knots.get(), degree + 1, i, x);
  1575. }
  1576. Thing_implement (MSpline, Spline, 0);
  1577. autoMSpline MSpline_create (double xmin, double xmax, integer degree, integer numberOfInteriorKnots) {
  1578. try {
  1579. autoMSpline me = Thing_new (MSpline);
  1580. integer numberOfCoefficients = numberOfInteriorKnots + degree + 1;
  1581. integer numberOfKnots = numberOfCoefficients + degree + 1;
  1582. Spline_init (me.get(), xmin, xmax, degree, numberOfCoefficients, numberOfKnots);
  1583. return me;
  1584. } catch (MelderError) {
  1585. Melder_throw (U"MSpline not created.");
  1586. }
  1587. }
  1588. autoMSpline MSpline_createFromStrings (double xmin, double xmax, integer degree, conststring32 coef, conststring32 interiorKnots) {
  1589. try {
  1590. Melder_require (degree <= Spline_MAXIMUM_DEGREE,
  1591. U"Degree should be <= ", Spline_MAXIMUM_DEGREE, U".");
  1592. autoMSpline me = Thing_new (MSpline);
  1593. FunctionTerms_initFromString (me.get(), xmin, xmax, coef, 1);
  1594. Spline_initKnotsFromString (me.get(), degree, interiorKnots);
  1595. return me;
  1596. } catch (MelderError) {
  1597. Melder_throw (U"MSpline not created from strings.");
  1598. }
  1599. }
  1600. /******** ISplines ************************************************/
  1601. double structISpline :: v_evaluate (double x) {
  1602. if (x < our xmin || x > our xmax)
  1603. return 0.0;
  1604. double result = 0.0;
  1605. for (integer i = 1; i <= numberOfCoefficients; i ++) {
  1606. if (coefficients [i] != 0.0)
  1607. result += coefficients [i] * NUMispline2 (knots.get(), degree, i, x);
  1608. }
  1609. return result;
  1610. }
  1611. void structISpline :: v_evaluateTerms (double x, double *terms) {
  1612. for (integer i = 1; i <= numberOfCoefficients; i ++)
  1613. terms [i] = NUMispline2 (knots.get(), degree, i, x);
  1614. }
  1615. integer structISpline :: v_getOrder () {
  1616. return degree;
  1617. }
  1618. Thing_implement (ISpline, Spline, 0);
  1619. autoISpline ISpline_create (double xmin, double xmax, integer degree, integer numberOfInteriorKnots) {
  1620. try {
  1621. autoISpline me = Thing_new (ISpline);
  1622. integer numberOfCoefficients = numberOfInteriorKnots + degree;
  1623. integer numberOfKnots = numberOfCoefficients + degree;
  1624. Spline_init (me.get(), xmin, xmax, degree, numberOfCoefficients, numberOfKnots);
  1625. return me;
  1626. } catch (MelderError) {
  1627. Melder_throw (U"ISpline not created.");
  1628. }
  1629. }
  1630. autoISpline ISpline_createFromStrings (double xmin, double xmax, integer degree, conststring32 coef, conststring32 interiorKnots) {
  1631. try {
  1632. if (degree > Spline_MAXIMUM_DEGREE)
  1633. Melder_throw (U"Degree should be <= 20.");
  1634. autoISpline me = Thing_new (ISpline);
  1635. FunctionTerms_initFromString (me.get(), xmin, xmax, coef, 1);
  1636. Spline_initKnotsFromString (me.get(), degree, interiorKnots);
  1637. return me;
  1638. } catch (MelderError) {
  1639. Melder_throw (U"ISpline not created from strings.");
  1640. };
  1641. }
  1642. /*
  1643. #define RationalFunction_members Function_members \
  1644. Polynomial num, denum;
  1645. #define RationalFunction_methods Function_methods
  1646. class_create (RationalFunction, Function)
  1647. RationalFunction RationalFunction_create (double xmin, double xmax,
  1648. integer degree_num, integer degree_denum)
  1649. {
  1650. RationalFunction me = new (RationalFunction);
  1651. if (! me || ! (my num = Polynomial_create (xmin, xmax, degree_num)) ||
  1652. ! (my denum = Polynomial_create (xmin, xmax, degree_denum))) forget (me);
  1653. return me;
  1654. }
  1655. RationalFunction RationalFunction_createFromString (I, double xmin, double xmax,
  1656. char *num, char *denum)
  1657. {
  1658. RationalFunction me = new (RationalFunction); integer i;
  1659. if (! (my num = Polynomial_createFromString (xmin, xmax, num)) ||
  1660. ! (my denum = Polynomial_createFromString (xmin, xmax, denum))) forget (me);
  1661. if (my denum -> v [1] != 1 && my denum -> v [1] != 0)
  1662. {
  1663. double q0 = my denum -> v [1];
  1664. for (i=1; 1 <= my num ->numberOfCoefficients; i ++) my num -> v [i] /= q0;
  1665. for (i=1; 1 <= my denum ->numberOfCoefficients; i ++) my denum -> v [i] /= q0;
  1666. }
  1667. return me;
  1668. }
  1669. // divide out common roots
  1670. RationalFunction RationalFunction_simplify (RationalFunction me)
  1671. {
  1672. Roots num = nullptr, denum = nullptr; RationalFunction thee = nullptr;
  1673. if (! (num = Polynomial_to_Roots (my num)) ||
  1674. ! (denum = Polynomial_to_Roots (my denum))) goto end;
  1675. }
  1676. */
  1677. /* end of file Polynomial.cpp */