Changeset 2430 for trunk/sources/ALGLIB/spline3.cs
- Timestamp:
- 10/15/09 13:22:07 (15 years ago)
- Location:
- trunk/sources/ALGLIB
- Files:
-
- 1 added
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/ALGLIB/spline3.cs
r2426 r2430 2 2 Copyright (c) 2007, Sergey Bochkanov (ALGLIB project). 3 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are 6 met: 7 8 - Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 11 - Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer listed 13 in this license in the documentation and/or other materials 14 provided with the distribution. 15 16 - Neither the name of the copyright holders nor the names of its 17 contributors may be used to endorse or promote products derived from 18 this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 4 >>> SOURCE LICENSE >>> 5 This program 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 (www.fsf.org); either version 2 of the 8 License, or (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 A copy of the GNU General Public License is available at 16 http://www.fsf.org/licensing/licenses 17 18 >>> END OF LICENSE >>> 31 19 *************************************************************************/ 32 20 33 21 using System; 34 22 35 class spline3 23 namespace alglib 36 24 { 37 /************************************************************************* 38 This subroutine builds linear spline coefficients table. 39 40 Input parameters: 41 X - spline nodes, array[0..N-1] 42 Y - function values, array[0..N-1] 43 N - points count, N>=2 44 45 Output parameters: 46 C - coefficients table. Used by SplineInterpolation and other 47 subroutines from this file. 48 49 -- ALGLIB PROJECT -- 50 Copyright 24.06.2007 by Bochkanov Sergey 51 *************************************************************************/ 52 public static void buildlinearspline(double[] x, 53 double[] y, 54 int n, 55 ref double[] c) 25 public class spline3 56 26 { 57 int i = 0; 58 int tblsize = 0; 59 60 x = (double[])x.Clone(); 61 y = (double[])y.Clone(); 62 63 System.Diagnostics.Debug.Assert(n>=2, "BuildLinearSpline: N<2!"); 64 65 // 66 // Sort points 67 // 68 heapsortpoints(ref x, ref y, n); 69 70 // 71 // Fill C: 72 // C[0] - length(C) 73 // C[1] - type(C): 74 // 3 - general cubic spline 75 // C[2] - N 76 // C[3]...C[3+N-1] - x[i], i = 0...N-1 77 // C[3+N]...C[3+N+(N-1)*4-1] - coefficients table 78 // 79 tblsize = 3+n+(n-1)*4; 80 c = new double[tblsize-1+1]; 81 c[0] = tblsize; 82 c[1] = 3; 83 c[2] = n; 84 for(i=0; i<=n-1; i++) 85 { 86 c[3+i] = x[i]; 87 } 88 for(i=0; i<=n-2; i++) 89 { 90 c[3+n+4*i+0] = y[i]; 91 c[3+n+4*i+1] = (y[i+1]-y[i])/(x[i+1]-x[i]); 92 c[3+n+4*i+2] = 0; 93 c[3+n+4*i+3] = 0; 94 } 95 } 96 97 98 /************************************************************************* 99 This subroutine builds cubic spline coefficients table. 100 101 Input parameters: 102 X - spline nodes, array[0..N-1] 103 Y - function values, array[0..N-1] 104 N - points count, N>=2 105 BoundLType - boundary condition type for the left boundary 106 BoundL - left boundary condition (first or second derivative, 107 depending on the BoundLType) 108 BoundRType - boundary condition type for the right boundary 109 BoundR - right boundary condition (first or second derivative, 110 depending on the BoundRType) 111 112 Output parameters: 113 C - coefficients table. Used by SplineInterpolation and 114 other subroutines from this file. 115 116 The BoundLType/BoundRType parameters can have the following values: 117 * 0, which corresponds to the parabolically terminated spline 118 (BoundL/BoundR are ignored). 119 * 1, which corresponds to the first derivative boundary condition 120 * 2, which corresponds to the second derivative boundary condition 121 122 -- ALGLIB PROJECT -- 123 Copyright 23.06.2007 by Bochkanov Sergey 124 *************************************************************************/ 125 public static void buildcubicspline(double[] x, 126 double[] y, 127 int n, 128 int boundltype, 129 double boundl, 130 int boundrtype, 131 double boundr, 132 ref double[] c) 133 { 134 double[] a1 = new double[0]; 135 double[] a2 = new double[0]; 136 double[] a3 = new double[0]; 137 double[] b = new double[0]; 138 double[] d = new double[0]; 139 int i = 0; 140 int tblsize = 0; 141 double delta = 0; 142 double delta2 = 0; 143 double delta3 = 0; 144 145 x = (double[])x.Clone(); 146 y = (double[])y.Clone(); 147 148 System.Diagnostics.Debug.Assert(n>=2, "BuildCubicSpline: N<2!"); 149 System.Diagnostics.Debug.Assert(boundltype==0 | boundltype==1 | boundltype==2, "BuildCubicSpline: incorrect BoundLType!"); 150 System.Diagnostics.Debug.Assert(boundrtype==0 | boundrtype==1 | boundrtype==2, "BuildCubicSpline: incorrect BoundRType!"); 151 a1 = new double[n-1+1]; 152 a2 = new double[n-1+1]; 153 a3 = new double[n-1+1]; 154 b = new double[n-1+1]; 155 156 // 157 // Special case: 158 // * N=2 159 // * parabolic terminated boundary condition on both ends 160 // 161 if( n==2 & boundltype==0 & boundrtype==0 ) 162 { 163 164 // 165 // Change task type 166 // 167 boundltype = 2; 168 boundl = 0; 169 boundrtype = 2; 170 boundr = 0; 171 } 172 173 // 174 // 175 // Sort points 176 // 177 heapsortpoints(ref x, ref y, n); 178 179 // 180 // Left boundary conditions 181 // 182 if( boundltype==0 ) 183 { 184 a1[0] = 0; 185 a2[0] = 1; 186 a3[0] = 1; 187 b[0] = 2*(y[1]-y[0])/(x[1]-x[0]); 188 } 189 if( boundltype==1 ) 190 { 191 a1[0] = 0; 192 a2[0] = 1; 193 a3[0] = 0; 194 b[0] = boundl; 195 } 196 if( boundltype==2 ) 197 { 198 a1[0] = 0; 199 a2[0] = 2; 200 a3[0] = 1; 201 b[0] = 3*(y[1]-y[0])/(x[1]-x[0])-0.5*boundl*(x[1]-x[0]); 202 } 203 204 // 205 // Central conditions 206 // 207 for(i=1; i<=n-2; i++) 208 { 209 a1[i] = x[i+1]-x[i]; 210 a2[i] = 2*(x[i+1]-x[i-1]); 211 a3[i] = x[i]-x[i-1]; 212 b[i] = 3*(y[i]-y[i-1])/(x[i]-x[i-1])*(x[i+1]-x[i])+3*(y[i+1]-y[i])/(x[i+1]-x[i])*(x[i]-x[i-1]); 213 } 214 215 // 216 // Right boundary conditions 217 // 218 if( boundrtype==0 ) 219 { 220 a1[n-1] = 1; 221 a2[n-1] = 1; 222 a3[n-1] = 0; 223 b[n-1] = 2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2]); 224 } 225 if( boundrtype==1 ) 226 { 227 a1[n-1] = 0; 228 a2[n-1] = 1; 229 a3[n-1] = 0; 230 b[n-1] = boundr; 231 } 232 if( boundrtype==2 ) 233 { 234 a1[n-1] = 1; 235 a2[n-1] = 2; 236 a3[n-1] = 0; 237 b[n-1] = 3*(y[n-1]-y[n-2])/(x[n-1]-x[n-2])+0.5*boundr*(x[n-1]-x[n-2]); 238 } 239 240 // 241 // Solve 242 // 243 solvetridiagonal(a1, a2, a3, b, n, ref d); 244 245 // 246 // Now problem is reduced to the cubic Hermite spline 247 // 248 buildhermitespline(x, y, d, n, ref c); 249 } 250 251 252 /************************************************************************* 253 This subroutine builds cubic Hermite spline coefficients table. 254 255 Input parameters: 256 X - spline nodes, array[0..N-1] 257 Y - function values, array[0..N-1] 258 D - derivatives, array[0..N-1] 259 N - points count, N>=2 260 261 Output parameters: 262 C - coefficients table. Used by SplineInterpolation and 263 other subroutines from this file. 264 265 -- ALGLIB PROJECT -- 266 Copyright 23.06.2007 by Bochkanov Sergey 267 *************************************************************************/ 268 public static void buildhermitespline(double[] x, 269 double[] y, 270 double[] d, 271 int n, 272 ref double[] c) 273 { 274 int i = 0; 275 int tblsize = 0; 276 double delta = 0; 277 double delta2 = 0; 278 double delta3 = 0; 279 280 x = (double[])x.Clone(); 281 y = (double[])y.Clone(); 282 d = (double[])d.Clone(); 283 284 System.Diagnostics.Debug.Assert(n>=2, "BuildHermiteSpline: N<2!"); 285 286 // 287 // Sort points 288 // 289 heapsortdpoints(ref x, ref y, ref d, n); 290 291 // 292 // Fill C: 293 // C[0] - length(C) 294 // C[1] - type(C): 295 // 3 - general cubic spline 296 // C[2] - N 297 // C[3]...C[3+N-1] - x[i], i = 0...N-1 298 // C[3+N]...C[3+N+(N-1)*4-1] - coefficients table 299 // 300 tblsize = 3+n+(n-1)*4; 301 c = new double[tblsize-1+1]; 302 c[0] = tblsize; 303 c[1] = 3; 304 c[2] = n; 305 for(i=0; i<=n-1; i++) 306 { 307 c[3+i] = x[i]; 308 } 309 for(i=0; i<=n-2; i++) 310 { 311 delta = x[i+1]-x[i]; 312 delta2 = AP.Math.Sqr(delta); 313 delta3 = delta*delta2; 314 c[3+n+4*i+0] = y[i]; 315 c[3+n+4*i+1] = d[i]; 316 c[3+n+4*i+2] = (3*(y[i+1]-y[i])-2*d[i]*delta-d[i+1]*delta)/delta2; 317 c[3+n+4*i+3] = (2*(y[i]-y[i+1])+d[i]*delta+d[i+1]*delta)/delta3; 318 } 319 } 320 321 322 /************************************************************************* 323 This subroutine builds Akima spline coefficients table. 324 325 Input parameters: 326 X - spline nodes, array[0..N-1] 327 Y - function values, array[0..N-1] 328 N - points count, N>=5 329 330 Output parameters: 331 C - coefficients table. Used by SplineInterpolation and 332 other subroutines from this file. 333 334 -- ALGLIB PROJECT -- 335 Copyright 24.06.2007 by Bochkanov Sergey 336 *************************************************************************/ 337 public static void buildakimaspline(double[] x, 338 double[] y, 339 int n, 340 ref double[] c) 341 { 342 int i = 0; 343 double[] d = new double[0]; 344 double[] w = new double[0]; 345 double[] diff = new double[0]; 346 347 x = (double[])x.Clone(); 348 y = (double[])y.Clone(); 349 350 System.Diagnostics.Debug.Assert(n>=5, "BuildAkimaSpline: N<5!"); 351 352 // 353 // Sort points 354 // 355 heapsortpoints(ref x, ref y, n); 356 357 // 358 // Prepare W (weights), Diff (divided differences) 359 // 360 w = new double[n-2+1]; 361 diff = new double[n-2+1]; 362 for(i=0; i<=n-2; i++) 363 { 364 diff[i] = (y[i+1]-y[i])/(x[i+1]-x[i]); 365 } 366 for(i=1; i<=n-2; i++) 367 { 368 w[i] = Math.Abs(diff[i]-diff[i-1]); 369 } 370 371 // 372 // Prepare Hermite interpolation scheme 373 // 374 d = new double[n-1+1]; 375 for(i=2; i<=n-3; i++) 376 { 377 if( Math.Abs(w[i-1])+Math.Abs(w[i+1])!=0 ) 378 { 379 d[i] = (w[i+1]*diff[i-1]+w[i-1]*diff[i])/(w[i+1]+w[i-1]); 380 } 381 else 382 { 383 d[i] = ((x[i+1]-x[i])*diff[i-1]+(x[i]-x[i-1])*diff[i])/(x[i+1]-x[i-1]); 384 } 385 } 386 d[0] = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]); 387 d[1] = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]); 388 d[n-2] = diffthreepoint(x[n-2], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]); 389 d[n-1] = diffthreepoint(x[n-1], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]); 390 391 // 392 // Build Akima spline using Hermite interpolation scheme 393 // 394 buildhermitespline(x, y, d, n, ref c); 395 } 396 397 398 /************************************************************************* 399 This subroutine calculates the value of the spline at the given point X. 400 401 Input parameters: 402 C - coefficients table. Built by BuildLinearSpline, 403 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 404 X - point 405 406 Result: 407 S(x) 408 409 -- ALGLIB PROJECT -- 410 Copyright 23.06.2007 by Bochkanov Sergey 411 *************************************************************************/ 412 public static double splineinterpolation(ref double[] c, 413 double x) 414 { 415 double result = 0; 416 int n = 0; 417 int l = 0; 418 int r = 0; 419 int m = 0; 420 421 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!"); 422 n = (int)Math.Round(c[2]); 423 424 // 425 // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) 426 // 427 l = 3; 428 r = 3+n-2+1; 429 while( l!=r-1 ) 430 { 431 m = (l+r)/2; 432 if( c[m]>=x ) 433 { 434 r = m; 435 } 436 else 437 { 438 l = m; 439 } 440 } 441 442 // 443 // Interpolation 444 // 445 x = x-c[l]; 446 m = 3+n+4*(l-3); 447 result = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3])); 448 return result; 449 } 450 451 452 /************************************************************************* 453 This subroutine differentiates the spline. 454 455 Input parameters: 456 C - coefficients table. Built by BuildLinearSpline, 457 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 458 X - point 459 460 Result: 461 S - S(x) 462 DS - S'(x) 463 D2S - S''(x) 464 465 -- ALGLIB PROJECT -- 466 Copyright 24.06.2007 by Bochkanov Sergey 467 *************************************************************************/ 468 public static void splinedifferentiation(ref double[] c, 469 double x, 470 ref double s, 471 ref double ds, 472 ref double d2s) 473 { 474 int n = 0; 475 int l = 0; 476 int r = 0; 477 int m = 0; 478 479 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!"); 480 n = (int)Math.Round(c[2]); 481 482 // 483 // Binary search 484 // 485 l = 3; 486 r = 3+n-2+1; 487 while( l!=r-1 ) 488 { 489 m = (l+r)/2; 490 if( c[m]>=x ) 491 { 492 r = m; 493 } 494 else 495 { 496 l = m; 497 } 498 } 499 500 // 501 // Differentiation 502 // 503 x = x-c[l]; 504 m = 3+n+4*(l-3); 505 s = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3])); 506 ds = c[m+1]+2*x*c[m+2]+3*AP.Math.Sqr(x)*c[m+3]; 507 d2s = 2*c[m+2]+6*x*c[m+3]; 508 } 509 510 511 /************************************************************************* 512 This subroutine makes the copy of the spline. 513 514 Input parameters: 515 C - coefficients table. Built by BuildLinearSpline, 516 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 517 518 Result: 519 CC - spline copy 520 521 -- ALGLIB PROJECT -- 522 Copyright 29.06.2007 by Bochkanov Sergey 523 *************************************************************************/ 524 public static void splinecopy(ref double[] c, 525 ref double[] cc) 526 { 527 int s = 0; 528 int i_ = 0; 529 530 s = (int)Math.Round(c[0]); 531 cc = new double[s-1+1]; 532 for(i_=0; i_<=s-1;i_++) 533 { 534 cc[i_] = c[i_]; 535 } 536 } 537 538 539 /************************************************************************* 540 This subroutine unpacks the spline into the coefficients table. 541 542 Input parameters: 543 C - coefficients table. Built by BuildLinearSpline, 544 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 545 X - point 546 547 Result: 548 Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. 549 For I = 0...N-2: 550 Tbl[I,0] = X[i] 551 Tbl[I,1] = X[i+1] 552 Tbl[I,2] = C0 553 Tbl[I,3] = C1 554 Tbl[I,4] = C2 555 Tbl[I,5] = C3 556 On [x[i], x[i+1]] spline is equals to: 557 S(x) = C0 + C1*t + C2*t^2 + C3*t^3 558 t = x-x[i] 559 560 -- ALGLIB PROJECT -- 561 Copyright 29.06.2007 by Bochkanov Sergey 562 *************************************************************************/ 563 public static void splineunpack(ref double[] c, 564 ref int n, 565 ref double[,] tbl) 566 { 567 int i = 0; 568 569 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineUnpack: incorrect C!"); 570 n = (int)Math.Round(c[2]); 571 tbl = new double[n-2+1, 5+1]; 572 573 // 574 // Fill 575 // 576 for(i=0; i<=n-2; i++) 577 { 578 tbl[i,0] = c[3+i]; 579 tbl[i,1] = c[3+i+1]; 580 tbl[i,2] = c[3+n+4*i]; 581 tbl[i,3] = c[3+n+4*i+1]; 582 tbl[i,4] = c[3+n+4*i+2]; 583 tbl[i,5] = c[3+n+4*i+3]; 584 } 585 } 586 587 588 /************************************************************************* 589 This subroutine performs linear transformation of the spline argument. 590 591 Input parameters: 592 C - coefficients table. Built by BuildLinearSpline, 593 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 594 A, B- transformation coefficients: x = A*t + B 595 Result: 596 C - transformed spline 597 598 -- ALGLIB PROJECT -- 599 Copyright 30.06.2007 by Bochkanov Sergey 600 *************************************************************************/ 601 public static void splinelintransx(ref double[] c, 602 double a, 603 double b) 604 { 605 int i = 0; 606 int n = 0; 607 double v = 0; 608 double dv = 0; 609 double d2v = 0; 610 double[] x = new double[0]; 611 double[] y = new double[0]; 612 double[] d = new double[0]; 613 614 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!"); 615 n = (int)Math.Round(c[2]); 616 617 // 618 // Special case: A=0 619 // 620 if( a==0 ) 621 { 622 v = splineinterpolation(ref c, b); 27 /************************************************************************* 28 This subroutine builds linear spline coefficients table. 29 30 Input parameters: 31 X - spline nodes, array[0..N-1] 32 Y - function values, array[0..N-1] 33 N - points count, N>=2 34 35 Output parameters: 36 C - coefficients table. Used by SplineInterpolation and other 37 subroutines from this file. 38 39 -- ALGLIB PROJECT -- 40 Copyright 24.06.2007 by Bochkanov Sergey 41 *************************************************************************/ 42 public static void buildlinearspline(double[] x, 43 double[] y, 44 int n, 45 ref double[] c) 46 { 47 int i = 0; 48 int tblsize = 0; 49 50 x = (double[])x.Clone(); 51 y = (double[])y.Clone(); 52 53 System.Diagnostics.Debug.Assert(n>=2, "BuildLinearSpline: N<2!"); 54 55 // 56 // Sort points 57 // 58 heapsortpoints(ref x, ref y, n); 59 60 // 61 // Fill C: 62 // C[0] - length(C) 63 // C[1] - type(C): 64 // 3 - general cubic spline 65 // C[2] - N 66 // C[3]...C[3+N-1] - x[i], i = 0...N-1 67 // C[3+N]...C[3+N+(N-1)*4-1] - coefficients table 68 // 69 tblsize = 3+n+(n-1)*4; 70 c = new double[tblsize-1+1]; 71 c[0] = tblsize; 72 c[1] = 3; 73 c[2] = n; 74 for(i=0; i<=n-1; i++) 75 { 76 c[3+i] = x[i]; 77 } 623 78 for(i=0; i<=n-2; i++) 624 79 { 625 c[3+n+4*i ] = v;626 c[3+n+4*i+1] = 0;80 c[3+n+4*i+0] = y[i]; 81 c[3+n+4*i+1] = (y[i+1]-y[i])/(x[i+1]-x[i]); 627 82 c[3+n+4*i+2] = 0; 628 83 c[3+n+4*i+3] = 0; 629 84 } 630 return; 631 } 632 633 // 634 // General case: A<>0. 635 // Unpack, X, Y, dY/dX. 636 // Scale and pack again. 637 // 638 x = new double[n-1+1]; 639 y = new double[n-1+1]; 640 d = new double[n-1+1]; 641 for(i=0; i<=n-1; i++) 642 { 643 x[i] = c[3+i]; 644 splinedifferentiation(ref c, x[i], ref v, ref dv, ref d2v); 645 x[i] = (x[i]-b)/a; 646 y[i] = v; 647 d[i] = a*dv; 648 } 649 buildhermitespline(x, y, d, n, ref c); 650 } 651 652 653 /************************************************************************* 654 This subroutine performs linear transformation of the spline. 655 656 Input parameters: 657 C - coefficients table. Built by BuildLinearSpline, 658 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 659 A, B- transformation coefficients: S2(x) = A*S(x) + B 660 Result: 661 C - transformed spline 662 663 -- ALGLIB PROJECT -- 664 Copyright 30.06.2007 by Bochkanov Sergey 665 *************************************************************************/ 666 public static void splinelintransy(ref double[] c, 667 double a, 668 double b) 669 { 670 int i = 0; 671 int n = 0; 672 double v = 0; 673 double dv = 0; 674 double d2v = 0; 675 double[] x = new double[0]; 676 double[] y = new double[0]; 677 double[] d = new double[0]; 678 679 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!"); 680 n = (int)Math.Round(c[2]); 681 682 // 683 // Special case: A=0 684 // 685 for(i=0; i<=n-2; i++) 686 { 687 c[3+n+4*i] = a*c[3+n+4*i]+b; 688 c[3+n+4*i+1] = a*c[3+n+4*i+1]; 689 c[3+n+4*i+2] = a*c[3+n+4*i+2]; 690 c[3+n+4*i+3] = a*c[3+n+4*i+3]; 691 } 692 } 693 694 695 /************************************************************************* 696 This subroutine integrates the spline. 697 698 Input parameters: 699 C - coefficients table. Built by BuildLinearSpline, 700 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 701 X - right bound of the integration interval [a, x] 702 Result: 703 integral(S(t)dt,a,x) 704 705 -- ALGLIB PROJECT -- 706 Copyright 23.06.2007 by Bochkanov Sergey 707 *************************************************************************/ 708 public static double splineintegration(ref double[] c, 709 double x) 710 { 711 double result = 0; 712 int n = 0; 713 int i = 0; 714 int l = 0; 715 int r = 0; 716 int m = 0; 717 double w = 0; 718 719 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineIntegration: incorrect C!"); 720 n = (int)Math.Round(c[2]); 721 722 // 723 // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) 724 // 725 l = 3; 726 r = 3+n-2+1; 727 while( l!=r-1 ) 728 { 729 m = (l+r)/2; 730 if( c[m]>=x ) 731 { 732 r = m; 733 } 734 else 735 { 736 l = m; 737 } 738 } 739 740 // 741 // Integration 742 // 743 result = 0; 744 for(i=3; i<=l-1; i++) 745 { 746 w = c[i+1]-c[i]; 747 m = 3+n+4*(i-3); 85 } 86 87 88 /************************************************************************* 89 This subroutine builds cubic spline coefficients table. 90 91 Input parameters: 92 X - spline nodes, array[0..N-1] 93 Y - function values, array[0..N-1] 94 N - points count, N>=2 95 BoundLType - boundary condition type for the left boundary 96 BoundL - left boundary condition (first or second derivative, 97 depending on the BoundLType) 98 BoundRType - boundary condition type for the right boundary 99 BoundR - right boundary condition (first or second derivative, 100 depending on the BoundRType) 101 102 Output parameters: 103 C - coefficients table. Used by SplineInterpolation and 104 other subroutines from this file. 105 106 The BoundLType/BoundRType parameters can have the following values: 107 * 0, which corresponds to the parabolically terminated spline 108 (BoundL/BoundR are ignored). 109 * 1, which corresponds to the first derivative boundary condition 110 * 2, which corresponds to the second derivative boundary condition 111 112 -- ALGLIB PROJECT -- 113 Copyright 23.06.2007 by Bochkanov Sergey 114 *************************************************************************/ 115 public static void buildcubicspline(double[] x, 116 double[] y, 117 int n, 118 int boundltype, 119 double boundl, 120 int boundrtype, 121 double boundr, 122 ref double[] c) 123 { 124 double[] a1 = new double[0]; 125 double[] a2 = new double[0]; 126 double[] a3 = new double[0]; 127 double[] b = new double[0]; 128 double[] d = new double[0]; 129 int i = 0; 130 int tblsize = 0; 131 double delta = 0; 132 double delta2 = 0; 133 double delta3 = 0; 134 135 x = (double[])x.Clone(); 136 y = (double[])y.Clone(); 137 138 System.Diagnostics.Debug.Assert(n>=2, "BuildCubicSpline: N<2!"); 139 System.Diagnostics.Debug.Assert(boundltype==0 | boundltype==1 | boundltype==2, "BuildCubicSpline: incorrect BoundLType!"); 140 System.Diagnostics.Debug.Assert(boundrtype==0 | boundrtype==1 | boundrtype==2, "BuildCubicSpline: incorrect BoundRType!"); 141 a1 = new double[n-1+1]; 142 a2 = new double[n-1+1]; 143 a3 = new double[n-1+1]; 144 b = new double[n-1+1]; 145 146 // 147 // Special case: 148 // * N=2 149 // * parabolic terminated boundary condition on both ends 150 // 151 if( n==2 & boundltype==0 & boundrtype==0 ) 152 { 153 154 // 155 // Change task type 156 // 157 boundltype = 2; 158 boundl = 0; 159 boundrtype = 2; 160 boundr = 0; 161 } 162 163 // 164 // 165 // Sort points 166 // 167 heapsortpoints(ref x, ref y, n); 168 169 // 170 // Left boundary conditions 171 // 172 if( boundltype==0 ) 173 { 174 a1[0] = 0; 175 a2[0] = 1; 176 a3[0] = 1; 177 b[0] = 2*(y[1]-y[0])/(x[1]-x[0]); 178 } 179 if( boundltype==1 ) 180 { 181 a1[0] = 0; 182 a2[0] = 1; 183 a3[0] = 0; 184 b[0] = boundl; 185 } 186 if( boundltype==2 ) 187 { 188 a1[0] = 0; 189 a2[0] = 2; 190 a3[0] = 1; 191 b[0] = 3*(y[1]-y[0])/(x[1]-x[0])-0.5*boundl*(x[1]-x[0]); 192 } 193 194 // 195 // Central conditions 196 // 197 for(i=1; i<=n-2; i++) 198 { 199 a1[i] = x[i+1]-x[i]; 200 a2[i] = 2*(x[i+1]-x[i-1]); 201 a3[i] = x[i]-x[i-1]; 202 b[i] = 3*(y[i]-y[i-1])/(x[i]-x[i-1])*(x[i+1]-x[i])+3*(y[i+1]-y[i])/(x[i+1]-x[i])*(x[i]-x[i-1]); 203 } 204 205 // 206 // Right boundary conditions 207 // 208 if( boundrtype==0 ) 209 { 210 a1[n-1] = 1; 211 a2[n-1] = 1; 212 a3[n-1] = 0; 213 b[n-1] = 2*(y[n-1]-y[n-2])/(x[n-1]-x[n-2]); 214 } 215 if( boundrtype==1 ) 216 { 217 a1[n-1] = 0; 218 a2[n-1] = 1; 219 a3[n-1] = 0; 220 b[n-1] = boundr; 221 } 222 if( boundrtype==2 ) 223 { 224 a1[n-1] = 1; 225 a2[n-1] = 2; 226 a3[n-1] = 0; 227 b[n-1] = 3*(y[n-1]-y[n-2])/(x[n-1]-x[n-2])+0.5*boundr*(x[n-1]-x[n-2]); 228 } 229 230 // 231 // Solve 232 // 233 solvetridiagonal(a1, a2, a3, b, n, ref d); 234 235 // 236 // Now problem is reduced to the cubic Hermite spline 237 // 238 buildhermitespline(x, y, d, n, ref c); 239 } 240 241 242 /************************************************************************* 243 This subroutine builds cubic Hermite spline coefficients table. 244 245 Input parameters: 246 X - spline nodes, array[0..N-1] 247 Y - function values, array[0..N-1] 248 D - derivatives, array[0..N-1] 249 N - points count, N>=2 250 251 Output parameters: 252 C - coefficients table. Used by SplineInterpolation and 253 other subroutines from this file. 254 255 -- ALGLIB PROJECT -- 256 Copyright 23.06.2007 by Bochkanov Sergey 257 *************************************************************************/ 258 public static void buildhermitespline(double[] x, 259 double[] y, 260 double[] d, 261 int n, 262 ref double[] c) 263 { 264 int i = 0; 265 int tblsize = 0; 266 double delta = 0; 267 double delta2 = 0; 268 double delta3 = 0; 269 270 x = (double[])x.Clone(); 271 y = (double[])y.Clone(); 272 d = (double[])d.Clone(); 273 274 System.Diagnostics.Debug.Assert(n>=2, "BuildHermiteSpline: N<2!"); 275 276 // 277 // Sort points 278 // 279 heapsortdpoints(ref x, ref y, ref d, n); 280 281 // 282 // Fill C: 283 // C[0] - length(C) 284 // C[1] - type(C): 285 // 3 - general cubic spline 286 // C[2] - N 287 // C[3]...C[3+N-1] - x[i], i = 0...N-1 288 // C[3+N]...C[3+N+(N-1)*4-1] - coefficients table 289 // 290 tblsize = 3+n+(n-1)*4; 291 c = new double[tblsize-1+1]; 292 c[0] = tblsize; 293 c[1] = 3; 294 c[2] = n; 295 for(i=0; i<=n-1; i++) 296 { 297 c[3+i] = x[i]; 298 } 299 for(i=0; i<=n-2; i++) 300 { 301 delta = x[i+1]-x[i]; 302 delta2 = AP.Math.Sqr(delta); 303 delta3 = delta*delta2; 304 c[3+n+4*i+0] = y[i]; 305 c[3+n+4*i+1] = d[i]; 306 c[3+n+4*i+2] = (3*(y[i+1]-y[i])-2*d[i]*delta-d[i+1]*delta)/delta2; 307 c[3+n+4*i+3] = (2*(y[i]-y[i+1])+d[i]*delta+d[i+1]*delta)/delta3; 308 } 309 } 310 311 312 /************************************************************************* 313 This subroutine builds Akima spline coefficients table. 314 315 Input parameters: 316 X - spline nodes, array[0..N-1] 317 Y - function values, array[0..N-1] 318 N - points count, N>=5 319 320 Output parameters: 321 C - coefficients table. Used by SplineInterpolation and 322 other subroutines from this file. 323 324 -- ALGLIB PROJECT -- 325 Copyright 24.06.2007 by Bochkanov Sergey 326 *************************************************************************/ 327 public static void buildakimaspline(double[] x, 328 double[] y, 329 int n, 330 ref double[] c) 331 { 332 int i = 0; 333 double[] d = new double[0]; 334 double[] w = new double[0]; 335 double[] diff = new double[0]; 336 337 x = (double[])x.Clone(); 338 y = (double[])y.Clone(); 339 340 System.Diagnostics.Debug.Assert(n>=5, "BuildAkimaSpline: N<5!"); 341 342 // 343 // Sort points 344 // 345 heapsortpoints(ref x, ref y, n); 346 347 // 348 // Prepare W (weights), Diff (divided differences) 349 // 350 w = new double[n-2+1]; 351 diff = new double[n-2+1]; 352 for(i=0; i<=n-2; i++) 353 { 354 diff[i] = (y[i+1]-y[i])/(x[i+1]-x[i]); 355 } 356 for(i=1; i<=n-2; i++) 357 { 358 w[i] = Math.Abs(diff[i]-diff[i-1]); 359 } 360 361 // 362 // Prepare Hermite interpolation scheme 363 // 364 d = new double[n-1+1]; 365 for(i=2; i<=n-3; i++) 366 { 367 if( Math.Abs(w[i-1])+Math.Abs(w[i+1])!=0 ) 368 { 369 d[i] = (w[i+1]*diff[i-1]+w[i-1]*diff[i])/(w[i+1]+w[i-1]); 370 } 371 else 372 { 373 d[i] = ((x[i+1]-x[i])*diff[i-1]+(x[i]-x[i-1])*diff[i])/(x[i+1]-x[i-1]); 374 } 375 } 376 d[0] = diffthreepoint(x[0], x[0], y[0], x[1], y[1], x[2], y[2]); 377 d[1] = diffthreepoint(x[1], x[0], y[0], x[1], y[1], x[2], y[2]); 378 d[n-2] = diffthreepoint(x[n-2], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]); 379 d[n-1] = diffthreepoint(x[n-1], x[n-3], y[n-3], x[n-2], y[n-2], x[n-1], y[n-1]); 380 381 // 382 // Build Akima spline using Hermite interpolation scheme 383 // 384 buildhermitespline(x, y, d, n, ref c); 385 } 386 387 388 /************************************************************************* 389 This subroutine calculates the value of the spline at the given point X. 390 391 Input parameters: 392 C - coefficients table. Built by BuildLinearSpline, 393 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 394 X - point 395 396 Result: 397 S(x) 398 399 -- ALGLIB PROJECT -- 400 Copyright 23.06.2007 by Bochkanov Sergey 401 *************************************************************************/ 402 public static double splineinterpolation(ref double[] c, 403 double x) 404 { 405 double result = 0; 406 int n = 0; 407 int l = 0; 408 int r = 0; 409 int m = 0; 410 411 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!"); 412 n = (int)Math.Round(c[2]); 413 414 // 415 // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) 416 // 417 l = 3; 418 r = 3+n-2+1; 419 while( l!=r-1 ) 420 { 421 m = (l+r)/2; 422 if( c[m]>=x ) 423 { 424 r = m; 425 } 426 else 427 { 428 l = m; 429 } 430 } 431 432 // 433 // Interpolation 434 // 435 x = x-c[l]; 436 m = 3+n+4*(l-3); 437 result = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3])); 438 return result; 439 } 440 441 442 /************************************************************************* 443 This subroutine differentiates the spline. 444 445 Input parameters: 446 C - coefficients table. Built by BuildLinearSpline, 447 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 448 X - point 449 450 Result: 451 S - S(x) 452 DS - S'(x) 453 D2S - S''(x) 454 455 -- ALGLIB PROJECT -- 456 Copyright 24.06.2007 by Bochkanov Sergey 457 *************************************************************************/ 458 public static void splinedifferentiation(ref double[] c, 459 double x, 460 ref double s, 461 ref double ds, 462 ref double d2s) 463 { 464 int n = 0; 465 int l = 0; 466 int r = 0; 467 int m = 0; 468 469 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineInterpolation: incorrect C!"); 470 n = (int)Math.Round(c[2]); 471 472 // 473 // Binary search 474 // 475 l = 3; 476 r = 3+n-2+1; 477 while( l!=r-1 ) 478 { 479 m = (l+r)/2; 480 if( c[m]>=x ) 481 { 482 r = m; 483 } 484 else 485 { 486 l = m; 487 } 488 } 489 490 // 491 // Differentiation 492 // 493 x = x-c[l]; 494 m = 3+n+4*(l-3); 495 s = c[m]+x*(c[m+1]+x*(c[m+2]+x*c[m+3])); 496 ds = c[m+1]+2*x*c[m+2]+3*AP.Math.Sqr(x)*c[m+3]; 497 d2s = 2*c[m+2]+6*x*c[m+3]; 498 } 499 500 501 /************************************************************************* 502 This subroutine makes the copy of the spline. 503 504 Input parameters: 505 C - coefficients table. Built by BuildLinearSpline, 506 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 507 508 Result: 509 CC - spline copy 510 511 -- ALGLIB PROJECT -- 512 Copyright 29.06.2007 by Bochkanov Sergey 513 *************************************************************************/ 514 public static void splinecopy(ref double[] c, 515 ref double[] cc) 516 { 517 int s = 0; 518 int i_ = 0; 519 520 s = (int)Math.Round(c[0]); 521 cc = new double[s-1+1]; 522 for(i_=0; i_<=s-1;i_++) 523 { 524 cc[i_] = c[i_]; 525 } 526 } 527 528 529 /************************************************************************* 530 This subroutine unpacks the spline into the coefficients table. 531 532 Input parameters: 533 C - coefficients table. Built by BuildLinearSpline, 534 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 535 X - point 536 537 Result: 538 Tbl - coefficients table, unpacked format, array[0..N-2, 0..5]. 539 For I = 0...N-2: 540 Tbl[I,0] = X[i] 541 Tbl[I,1] = X[i+1] 542 Tbl[I,2] = C0 543 Tbl[I,3] = C1 544 Tbl[I,4] = C2 545 Tbl[I,5] = C3 546 On [x[i], x[i+1]] spline is equals to: 547 S(x) = C0 + C1*t + C2*t^2 + C3*t^3 548 t = x-x[i] 549 550 -- ALGLIB PROJECT -- 551 Copyright 29.06.2007 by Bochkanov Sergey 552 *************************************************************************/ 553 public static void splineunpack(ref double[] c, 554 ref int n, 555 ref double[,] tbl) 556 { 557 int i = 0; 558 559 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineUnpack: incorrect C!"); 560 n = (int)Math.Round(c[2]); 561 tbl = new double[n-2+1, 5+1]; 562 563 // 564 // Fill 565 // 566 for(i=0; i<=n-2; i++) 567 { 568 tbl[i,0] = c[3+i]; 569 tbl[i,1] = c[3+i+1]; 570 tbl[i,2] = c[3+n+4*i]; 571 tbl[i,3] = c[3+n+4*i+1]; 572 tbl[i,4] = c[3+n+4*i+2]; 573 tbl[i,5] = c[3+n+4*i+3]; 574 } 575 } 576 577 578 /************************************************************************* 579 This subroutine performs linear transformation of the spline argument. 580 581 Input parameters: 582 C - coefficients table. Built by BuildLinearSpline, 583 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 584 A, B- transformation coefficients: x = A*t + B 585 Result: 586 C - transformed spline 587 588 -- ALGLIB PROJECT -- 589 Copyright 30.06.2007 by Bochkanov Sergey 590 *************************************************************************/ 591 public static void splinelintransx(ref double[] c, 592 double a, 593 double b) 594 { 595 int i = 0; 596 int n = 0; 597 double v = 0; 598 double dv = 0; 599 double d2v = 0; 600 double[] x = new double[0]; 601 double[] y = new double[0]; 602 double[] d = new double[0]; 603 604 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!"); 605 n = (int)Math.Round(c[2]); 606 607 // 608 // Special case: A=0 609 // 610 if( a==0 ) 611 { 612 v = splineinterpolation(ref c, b); 613 for(i=0; i<=n-2; i++) 614 { 615 c[3+n+4*i] = v; 616 c[3+n+4*i+1] = 0; 617 c[3+n+4*i+2] = 0; 618 c[3+n+4*i+3] = 0; 619 } 620 return; 621 } 622 623 // 624 // General case: A<>0. 625 // Unpack, X, Y, dY/dX. 626 // Scale and pack again. 627 // 628 x = new double[n-1+1]; 629 y = new double[n-1+1]; 630 d = new double[n-1+1]; 631 for(i=0; i<=n-1; i++) 632 { 633 x[i] = c[3+i]; 634 splinedifferentiation(ref c, x[i], ref v, ref dv, ref d2v); 635 x[i] = (x[i]-b)/a; 636 y[i] = v; 637 d[i] = a*dv; 638 } 639 buildhermitespline(x, y, d, n, ref c); 640 } 641 642 643 /************************************************************************* 644 This subroutine performs linear transformation of the spline. 645 646 Input parameters: 647 C - coefficients table. Built by BuildLinearSpline, 648 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 649 A, B- transformation coefficients: S2(x) = A*S(x) + B 650 Result: 651 C - transformed spline 652 653 -- ALGLIB PROJECT -- 654 Copyright 30.06.2007 by Bochkanov Sergey 655 *************************************************************************/ 656 public static void splinelintransy(ref double[] c, 657 double a, 658 double b) 659 { 660 int i = 0; 661 int n = 0; 662 double v = 0; 663 double dv = 0; 664 double d2v = 0; 665 double[] x = new double[0]; 666 double[] y = new double[0]; 667 double[] d = new double[0]; 668 669 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineLinTransX: incorrect C!"); 670 n = (int)Math.Round(c[2]); 671 672 // 673 // Special case: A=0 674 // 675 for(i=0; i<=n-2; i++) 676 { 677 c[3+n+4*i] = a*c[3+n+4*i]+b; 678 c[3+n+4*i+1] = a*c[3+n+4*i+1]; 679 c[3+n+4*i+2] = a*c[3+n+4*i+2]; 680 c[3+n+4*i+3] = a*c[3+n+4*i+3]; 681 } 682 } 683 684 685 /************************************************************************* 686 This subroutine integrates the spline. 687 688 Input parameters: 689 C - coefficients table. Built by BuildLinearSpline, 690 BuildHermiteSpline, BuildCubicSpline, BuildAkimaSpline. 691 X - right bound of the integration interval [a, x] 692 Result: 693 integral(S(t)dt,a,x) 694 695 -- ALGLIB PROJECT -- 696 Copyright 23.06.2007 by Bochkanov Sergey 697 *************************************************************************/ 698 public static double splineintegration(ref double[] c, 699 double x) 700 { 701 double result = 0; 702 int n = 0; 703 int i = 0; 704 int l = 0; 705 int r = 0; 706 int m = 0; 707 double w = 0; 708 709 System.Diagnostics.Debug.Assert((int)Math.Round(c[1])==3, "SplineIntegration: incorrect C!"); 710 n = (int)Math.Round(c[2]); 711 712 // 713 // Binary search in the [ x[0], ..., x[n-2] ] (x[n-1] is not included) 714 // 715 l = 3; 716 r = 3+n-2+1; 717 while( l!=r-1 ) 718 { 719 m = (l+r)/2; 720 if( c[m]>=x ) 721 { 722 r = m; 723 } 724 else 725 { 726 l = m; 727 } 728 } 729 730 // 731 // Integration 732 // 733 result = 0; 734 for(i=3; i<=l-1; i++) 735 { 736 w = c[i+1]-c[i]; 737 m = 3+n+4*(i-3); 738 result = result+c[m]*w; 739 result = result+c[m+1]*AP.Math.Sqr(w)/2; 740 result = result+c[m+2]*AP.Math.Sqr(w)*w/3; 741 result = result+c[m+3]*AP.Math.Sqr(AP.Math.Sqr(w))/4; 742 } 743 w = x-c[l]; 744 m = 3+n+4*(l-3); 748 745 result = result+c[m]*w; 749 746 result = result+c[m+1]*AP.Math.Sqr(w)/2; 750 747 result = result+c[m+2]*AP.Math.Sqr(w)*w/3; 751 748 result = result+c[m+3]*AP.Math.Sqr(AP.Math.Sqr(w))/4; 752 } 753 w = x-c[l]; 754 m = 3+n+4*(l-3); 755 result = result+c[m]*w; 756 result = result+c[m+1]*AP.Math.Sqr(w)/2; 757 result = result+c[m+2]*AP.Math.Sqr(w)*w/3; 758 result = result+c[m+3]*AP.Math.Sqr(AP.Math.Sqr(w))/4; 759 return result; 760 } 761 762 763 /************************************************************************* 764 Obsolete subroutine, left for backward compatibility. 765 *************************************************************************/ 766 public static void spline3buildtable(int n, 767 int diffn, 768 double[] x, 769 double[] y, 770 double boundl, 771 double boundr, 772 ref double[,] ctbl) 773 { 774 bool c = new bool(); 775 int e = 0; 776 int g = 0; 777 double tmp = 0; 778 int nxm1 = 0; 779 int i = 0; 780 int j = 0; 781 double dx = 0; 782 double dxj = 0; 783 double dyj = 0; 784 double dxjp1 = 0; 785 double dyjp1 = 0; 786 double dxp = 0; 787 double dyp = 0; 788 double yppa = 0; 789 double yppb = 0; 790 double pj = 0; 791 double b1 = 0; 792 double b2 = 0; 793 double b3 = 0; 794 double b4 = 0; 795 796 x = (double[])x.Clone(); 797 y = (double[])y.Clone(); 798 799 n = n-1; 800 g = (n+1)/2; 801 do 802 { 803 i = g; 749 return result; 750 } 751 752 753 /************************************************************************* 754 Obsolete subroutine, left for backward compatibility. 755 *************************************************************************/ 756 public static void spline3buildtable(int n, 757 int diffn, 758 double[] x, 759 double[] y, 760 double boundl, 761 double boundr, 762 ref double[,] ctbl) 763 { 764 bool c = new bool(); 765 int e = 0; 766 int g = 0; 767 double tmp = 0; 768 int nxm1 = 0; 769 int i = 0; 770 int j = 0; 771 double dx = 0; 772 double dxj = 0; 773 double dyj = 0; 774 double dxjp1 = 0; 775 double dyjp1 = 0; 776 double dxp = 0; 777 double dyp = 0; 778 double yppa = 0; 779 double yppb = 0; 780 double pj = 0; 781 double b1 = 0; 782 double b2 = 0; 783 double b3 = 0; 784 double b4 = 0; 785 786 x = (double[])x.Clone(); 787 y = (double[])y.Clone(); 788 789 n = n-1; 790 g = (n+1)/2; 804 791 do 805 792 { 806 j = i-g; 807 c = true; 793 i = g; 808 794 do 809 795 { 810 if( x[j]<=x[j+g] ) 796 j = i-g; 797 c = true; 798 do 811 799 { 812 c = false; 800 if( x[j]<=x[j+g] ) 801 { 802 c = false; 803 } 804 else 805 { 806 tmp = x[j]; 807 x[j] = x[j+g]; 808 x[j+g] = tmp; 809 tmp = y[j]; 810 y[j] = y[j+g]; 811 y[j+g] = tmp; 812 } 813 j = j-1; 813 814 } 814 else 815 while( j>=0 & c ); 816 i = i+1; 817 } 818 while( i<=n ); 819 g = g/2; 820 } 821 while( g>0 ); 822 ctbl = new double[4+1, n+1]; 823 n = n+1; 824 if( diffn==1 ) 825 { 826 b1 = 1; 827 b2 = 6/(x[1]-x[0])*((y[1]-y[0])/(x[1]-x[0])-boundl); 828 b3 = 1; 829 b4 = 6/(x[n-1]-x[n-2])*(boundr-(y[n-1]-y[n-2])/(x[n-1]-x[n-2])); 830 } 831 else 832 { 833 b1 = 0; 834 b2 = 2*boundl; 835 b3 = 0; 836 b4 = 2*boundr; 837 } 838 nxm1 = n-1; 839 if( n>=2 ) 840 { 841 if( n>2 ) 842 { 843 dxj = x[1]-x[0]; 844 dyj = y[1]-y[0]; 845 j = 2; 846 while( j<=nxm1 ) 815 847 { 816 tmp = x[j]; 817 x[j] = x[j+g]; 818 x[j+g] = tmp; 819 tmp = y[j]; 820 y[j] = y[j+g]; 821 y[j+g] = tmp; 848 dxjp1 = x[j]-x[j-1]; 849 dyjp1 = y[j]-y[j-1]; 850 dxp = dxj+dxjp1; 851 ctbl[1,j-1] = dxjp1/dxp; 852 ctbl[2,j-1] = 1-ctbl[1,j-1]; 853 ctbl[3,j-1] = 6*(dyjp1/dxjp1-dyj/dxj)/dxp; 854 dxj = dxjp1; 855 dyj = dyjp1; 856 j = j+1; 822 857 } 823 j = j-1; 824 } 825 while( j>=0 & c ); 826 i = i+1; 827 } 828 while( i<=n ); 829 g = g/2; 830 } 831 while( g>0 ); 832 ctbl = new double[4+1, n+1]; 833 n = n+1; 834 if( diffn==1 ) 835 { 836 b1 = 1; 837 b2 = 6/(x[1]-x[0])*((y[1]-y[0])/(x[1]-x[0])-boundl); 838 b3 = 1; 839 b4 = 6/(x[n-1]-x[n-2])*(boundr-(y[n-1]-y[n-2])/(x[n-1]-x[n-2])); 840 } 841 else 842 { 843 b1 = 0; 844 b2 = 2*boundl; 845 b3 = 0; 846 b4 = 2*boundr; 847 } 848 nxm1 = n-1; 849 if( n>=2 ) 850 { 851 if( n>2 ) 852 { 853 dxj = x[1]-x[0]; 854 dyj = y[1]-y[0]; 855 j = 2; 856 while( j<=nxm1 ) 857 { 858 dxjp1 = x[j]-x[j-1]; 859 dyjp1 = y[j]-y[j-1]; 860 dxp = dxj+dxjp1; 861 ctbl[1,j-1] = dxjp1/dxp; 862 ctbl[2,j-1] = 1-ctbl[1,j-1]; 863 ctbl[3,j-1] = 6*(dyjp1/dxjp1-dyj/dxj)/dxp; 864 dxj = dxjp1; 865 dyj = dyjp1; 866 j = j+1; 867 } 868 } 869 ctbl[1,0] = -(b1/2); 870 ctbl[2,0] = b2/2; 871 if( n!=2 ) 872 { 873 j = 2; 874 while( j<=nxm1 ) 875 { 876 pj = ctbl[2,j-1]*ctbl[1,j-2]+2; 877 ctbl[1,j-1] = -(ctbl[1,j-1]/pj); 878 ctbl[2,j-1] = (ctbl[3,j-1]-ctbl[2,j-1]*ctbl[2,j-2])/pj; 879 j = j+1; 880 } 881 } 882 yppb = (b4-b3*ctbl[2,nxm1-1])/(b3*ctbl[1,nxm1-1]+2); 883 i = 1; 884 while( i<=nxm1 ) 885 { 886 j = n-i; 887 yppa = ctbl[1,j-1]*yppb+ctbl[2,j-1]; 888 dx = x[j]-x[j-1]; 889 ctbl[3,j-1] = (yppb-yppa)/dx/6; 890 ctbl[2,j-1] = yppa/2; 891 ctbl[1,j-1] = (y[j]-y[j-1])/dx-(ctbl[2,j-1]+ctbl[3,j-1]*dx)*dx; 892 yppb = yppa; 893 i = i+1; 894 } 895 for(i=1; i<=n; i++) 896 { 897 ctbl[0,i-1] = y[i-1]; 898 ctbl[4,i-1] = x[i-1]; 899 } 900 } 901 } 902 903 904 /************************************************************************* 905 Obsolete subroutine, left for backward compatibility. 906 *************************************************************************/ 907 public static double spline3interpolate(int n, 908 ref double[,] c, 909 double x) 910 { 911 double result = 0; 912 int i = 0; 913 int l = 0; 914 int half = 0; 915 int first = 0; 916 int middle = 0; 917 918 n = n-1; 919 l = n; 920 first = 0; 921 while( l>0 ) 922 { 923 half = l/2; 924 middle = first+half; 925 if( c[4,middle]<x ) 926 { 927 first = middle+1; 928 l = l-half-1; 929 } 930 else 931 { 932 l = half; 933 } 934 } 935 i = first-1; 936 if( i<0 ) 937 { 938 i = 0; 939 } 940 result = c[0,i]+(x-c[4,i])*(c[1,i]+(x-c[4,i])*(c[2,i]+c[3,i]*(x-c[4,i]))); 941 return result; 942 } 943 944 945 /************************************************************************* 946 Internal subroutine. Heap sort. 947 *************************************************************************/ 948 private static void heapsortpoints(ref double[] x, 949 ref double[] y, 950 int n) 951 { 952 int i = 0; 953 int j = 0; 954 int k = 0; 955 int t = 0; 956 double tmp = 0; 957 bool isascending = new bool(); 958 bool isdescending = new bool(); 959 960 961 // 962 // Test for already sorted set 963 // 964 isascending = true; 965 isdescending = true; 966 for(i=1; i<=n-1; i++) 967 { 968 isascending = isascending & x[i]>x[i-1]; 969 isdescending = isdescending & x[i]<x[i-1]; 970 } 971 if( isascending ) 972 { 973 return; 974 } 975 if( isdescending ) 976 { 977 for(i=0; i<=n-1; i++) 978 { 979 j = n-1-i; 980 if( j<=i ) 981 { 982 break; 983 } 984 tmp = x[i]; 985 x[i] = x[j]; 986 x[j] = tmp; 987 tmp = y[i]; 988 y[i] = y[j]; 989 y[j] = tmp; 990 } 991 return; 992 } 993 994 // 995 // Special case: N=1 996 // 997 if( n==1 ) 998 { 999 return; 1000 } 1001 1002 // 1003 // General case 1004 // 1005 i = 2; 1006 do 1007 { 1008 t = i; 1009 while( t!=1 ) 1010 { 1011 k = t/2; 1012 if( x[k-1]>=x[t-1] ) 1013 { 1014 t = 1; 858 } 859 ctbl[1,0] = -(b1/2); 860 ctbl[2,0] = b2/2; 861 if( n!=2 ) 862 { 863 j = 2; 864 while( j<=nxm1 ) 865 { 866 pj = ctbl[2,j-1]*ctbl[1,j-2]+2; 867 ctbl[1,j-1] = -(ctbl[1,j-1]/pj); 868 ctbl[2,j-1] = (ctbl[3,j-1]-ctbl[2,j-1]*ctbl[2,j-2])/pj; 869 j = j+1; 870 } 871 } 872 yppb = (b4-b3*ctbl[2,nxm1-1])/(b3*ctbl[1,nxm1-1]+2); 873 i = 1; 874 while( i<=nxm1 ) 875 { 876 j = n-i; 877 yppa = ctbl[1,j-1]*yppb+ctbl[2,j-1]; 878 dx = x[j]-x[j-1]; 879 ctbl[3,j-1] = (yppb-yppa)/dx/6; 880 ctbl[2,j-1] = yppa/2; 881 ctbl[1,j-1] = (y[j]-y[j-1])/dx-(ctbl[2,j-1]+ctbl[3,j-1]*dx)*dx; 882 yppb = yppa; 883 i = i+1; 884 } 885 for(i=1; i<=n; i++) 886 { 887 ctbl[0,i-1] = y[i-1]; 888 ctbl[4,i-1] = x[i-1]; 889 } 890 } 891 } 892 893 894 /************************************************************************* 895 Obsolete subroutine, left for backward compatibility. 896 *************************************************************************/ 897 public static double spline3interpolate(int n, 898 ref double[,] c, 899 double x) 900 { 901 double result = 0; 902 int i = 0; 903 int l = 0; 904 int half = 0; 905 int first = 0; 906 int middle = 0; 907 908 n = n-1; 909 l = n; 910 first = 0; 911 while( l>0 ) 912 { 913 half = l/2; 914 middle = first+half; 915 if( c[4,middle]<x ) 916 { 917 first = middle+1; 918 l = l-half-1; 1015 919 } 1016 920 else 1017 921 { 1018 tmp = x[k-1]; 1019 x[k-1] = x[t-1]; 1020 x[t-1] = tmp; 1021 tmp = y[k-1]; 1022 y[k-1] = y[t-1]; 1023 y[t-1] = tmp; 1024 t = k; 1025 } 1026 } 1027 i = i+1; 1028 } 1029 while( i<=n ); 1030 i = n-1; 1031 do 1032 { 1033 tmp = x[i]; 1034 x[i] = x[0]; 1035 x[0] = tmp; 1036 tmp = y[i]; 1037 y[i] = y[0]; 1038 y[0] = tmp; 1039 t = 1; 1040 while( t!=0 ) 1041 { 1042 k = 2*t; 1043 if( k>i ) 1044 { 1045 t = 0; 1046 } 1047 else 1048 { 1049 if( k<i ) 922 l = half; 923 } 924 } 925 i = first-1; 926 if( i<0 ) 927 { 928 i = 0; 929 } 930 result = c[0,i]+(x-c[4,i])*(c[1,i]+(x-c[4,i])*(c[2,i]+c[3,i]*(x-c[4,i]))); 931 return result; 932 } 933 934 935 /************************************************************************* 936 Internal subroutine. Heap sort. 937 *************************************************************************/ 938 private static void heapsortpoints(ref double[] x, 939 ref double[] y, 940 int n) 941 { 942 int i = 0; 943 int j = 0; 944 int k = 0; 945 int t = 0; 946 double tmp = 0; 947 bool isascending = new bool(); 948 bool isdescending = new bool(); 949 950 951 // 952 // Test for already sorted set 953 // 954 isascending = true; 955 isdescending = true; 956 for(i=1; i<=n-1; i++) 957 { 958 isascending = isascending & x[i]>x[i-1]; 959 isdescending = isdescending & x[i]<x[i-1]; 960 } 961 if( isascending ) 962 { 963 return; 964 } 965 if( isdescending ) 966 { 967 for(i=0; i<=n-1; i++) 968 { 969 j = n-1-i; 970 if( j<=i ) 1050 971 { 1051 if( x[k]>x[k-1] ) 1052 { 1053 k = k+1; 1054 } 972 break; 1055 973 } 1056 if( x[t-1]>=x[k-1] ) 974 tmp = x[i]; 975 x[i] = x[j]; 976 x[j] = tmp; 977 tmp = y[i]; 978 y[i] = y[j]; 979 y[j] = tmp; 980 } 981 return; 982 } 983 984 // 985 // Special case: N=1 986 // 987 if( n==1 ) 988 { 989 return; 990 } 991 992 // 993 // General case 994 // 995 i = 2; 996 do 997 { 998 t = i; 999 while( t!=1 ) 1000 { 1001 k = t/2; 1002 if( x[k-1]>=x[t-1] ) 1057 1003 { 1058 t = 0;1004 t = 1; 1059 1005 } 1060 1006 else … … 1069 1015 } 1070 1016 } 1071 } 1072 i = i-1; 1073 } 1074 while( i>=1 ); 1075 } 1076 1077 1078 /************************************************************************* 1079 Internal subroutine. Heap sort. 1080 *************************************************************************/ 1081 private static void heapsortdpoints(ref double[] x, 1082 ref double[] y, 1083 ref double[] d, 1084 int n) 1085 { 1086 int i = 0; 1087 int j = 0; 1088 int k = 0; 1089 int t = 0; 1090 double tmp = 0; 1091 bool isascending = new bool(); 1092 bool isdescending = new bool(); 1093 1094 1095 // 1096 // Test for already sorted set 1097 // 1098 isascending = true; 1099 isdescending = true; 1100 for(i=1; i<=n-1; i++) 1101 { 1102 isascending = isascending & x[i]>x[i-1]; 1103 isdescending = isdescending & x[i]<x[i-1]; 1104 } 1105 if( isascending ) 1106 { 1107 return; 1108 } 1109 if( isdescending ) 1110 { 1111 for(i=0; i<=n-1; i++) 1112 { 1113 j = n-1-i; 1114 if( j<=i ) 1115 { 1116 break; 1117 } 1017 i = i+1; 1018 } 1019 while( i<=n ); 1020 i = n-1; 1021 do 1022 { 1118 1023 tmp = x[i]; 1119 x[i] = x[ j];1120 x[ j] = tmp;1024 x[i] = x[0]; 1025 x[0] = tmp; 1121 1026 tmp = y[i]; 1122 y[i] = y[j]; 1123 y[j] = tmp; 1124 tmp = d[i]; 1125 d[i] = d[j]; 1126 d[j] = tmp; 1127 } 1128 return; 1129 } 1130 1131 // 1132 // Special case: N=1 1133 // 1134 if( n==1 ) 1135 { 1136 return; 1137 } 1138 1139 // 1140 // General case 1141 // 1142 i = 2; 1143 do 1144 { 1145 t = i; 1146 while( t!=1 ) 1147 { 1148 k = t/2; 1149 if( x[k-1]>=x[t-1] ) 1150 { 1151 t = 1; 1152 } 1153 else 1154 { 1155 tmp = x[k-1]; 1156 x[k-1] = x[t-1]; 1157 x[t-1] = tmp; 1158 tmp = y[k-1]; 1159 y[k-1] = y[t-1]; 1160 y[t-1] = tmp; 1161 tmp = d[k-1]; 1162 d[k-1] = d[t-1]; 1163 d[t-1] = tmp; 1164 t = k; 1165 } 1166 } 1167 i = i+1; 1168 } 1169 while( i<=n ); 1170 i = n-1; 1171 do 1172 { 1173 tmp = x[i]; 1174 x[i] = x[0]; 1175 x[0] = tmp; 1176 tmp = y[i]; 1177 y[i] = y[0]; 1178 y[0] = tmp; 1179 tmp = d[i]; 1180 d[i] = d[0]; 1181 d[0] = tmp; 1182 t = 1; 1183 while( t!=0 ) 1184 { 1185 k = 2*t; 1186 if( k>i ) 1187 { 1188 t = 0; 1189 } 1190 else 1191 { 1192 if( k<i ) 1027 y[i] = y[0]; 1028 y[0] = tmp; 1029 t = 1; 1030 while( t!=0 ) 1031 { 1032 k = 2*t; 1033 if( k>i ) 1193 1034 { 1194 if( x[k]>x[k-1] ) 1035 t = 0; 1036 } 1037 else 1038 { 1039 if( k<i ) 1195 1040 { 1196 k = k+1; 1041 if( x[k]>x[k-1] ) 1042 { 1043 k = k+1; 1044 } 1045 } 1046 if( x[t-1]>=x[k-1] ) 1047 { 1048 t = 0; 1049 } 1050 else 1051 { 1052 tmp = x[k-1]; 1053 x[k-1] = x[t-1]; 1054 x[t-1] = tmp; 1055 tmp = y[k-1]; 1056 y[k-1] = y[t-1]; 1057 y[t-1] = tmp; 1058 t = k; 1197 1059 } 1198 1060 } 1199 if( x[t-1]>=x[k-1] ) 1061 } 1062 i = i-1; 1063 } 1064 while( i>=1 ); 1065 } 1066 1067 1068 /************************************************************************* 1069 Internal subroutine. Heap sort. 1070 *************************************************************************/ 1071 private static void heapsortdpoints(ref double[] x, 1072 ref double[] y, 1073 ref double[] d, 1074 int n) 1075 { 1076 int i = 0; 1077 int j = 0; 1078 int k = 0; 1079 int t = 0; 1080 double tmp = 0; 1081 bool isascending = new bool(); 1082 bool isdescending = new bool(); 1083 1084 1085 // 1086 // Test for already sorted set 1087 // 1088 isascending = true; 1089 isdescending = true; 1090 for(i=1; i<=n-1; i++) 1091 { 1092 isascending = isascending & x[i]>x[i-1]; 1093 isdescending = isdescending & x[i]<x[i-1]; 1094 } 1095 if( isascending ) 1096 { 1097 return; 1098 } 1099 if( isdescending ) 1100 { 1101 for(i=0; i<=n-1; i++) 1102 { 1103 j = n-1-i; 1104 if( j<=i ) 1200 1105 { 1201 t = 0; 1106 break; 1107 } 1108 tmp = x[i]; 1109 x[i] = x[j]; 1110 x[j] = tmp; 1111 tmp = y[i]; 1112 y[i] = y[j]; 1113 y[j] = tmp; 1114 tmp = d[i]; 1115 d[i] = d[j]; 1116 d[j] = tmp; 1117 } 1118 return; 1119 } 1120 1121 // 1122 // Special case: N=1 1123 // 1124 if( n==1 ) 1125 { 1126 return; 1127 } 1128 1129 // 1130 // General case 1131 // 1132 i = 2; 1133 do 1134 { 1135 t = i; 1136 while( t!=1 ) 1137 { 1138 k = t/2; 1139 if( x[k-1]>=x[t-1] ) 1140 { 1141 t = 1; 1202 1142 } 1203 1143 else … … 1215 1155 } 1216 1156 } 1217 } 1218 i = i-1; 1219 } 1220 while( i>=1 ); 1221 } 1222 1223 1224 /************************************************************************* 1225 Internal subroutine. Tridiagonal solver. 1226 *************************************************************************/ 1227 private static void solvetridiagonal(double[] a, 1228 double[] b, 1229 double[] c, 1230 double[] d, 1231 int n, 1232 ref double[] x) 1233 { 1234 int k = 0; 1235 double t = 0; 1236 1237 a = (double[])a.Clone(); 1238 b = (double[])b.Clone(); 1239 c = (double[])c.Clone(); 1240 d = (double[])d.Clone(); 1241 1242 x = new double[n-1+1]; 1243 a[0] = 0; 1244 c[n-1] = 0; 1245 for(k=1; k<=n-1; k++) 1246 { 1247 t = a[k]/b[k-1]; 1248 b[k] = b[k]-t*c[k-1]; 1249 d[k] = d[k]-t*d[k-1]; 1250 } 1251 x[n-1] = d[n-1]/b[n-1]; 1252 for(k=n-2; k>=0; k--) 1253 { 1254 x[k] = (d[k]-c[k]*x[k+1])/b[k]; 1255 } 1256 } 1257 1258 1259 /************************************************************************* 1260 Internal subroutine. Three-point differentiation 1261 *************************************************************************/ 1262 private static double diffthreepoint(double t, 1263 double x0, 1264 double f0, 1265 double x1, 1266 double f1, 1267 double x2, 1268 double f2) 1269 { 1270 double result = 0; 1271 double a = 0; 1272 double b = 0; 1273 1274 t = t-x0; 1275 x1 = x1-x0; 1276 x2 = x2-x0; 1277 a = (f2-f0-x2/x1*(f1-f0))/(AP.Math.Sqr(x2)-x1*x2); 1278 b = (f1-f0-a*AP.Math.Sqr(x1))/x1; 1279 result = 2*a*t+b; 1280 return result; 1157 i = i+1; 1158 } 1159 while( i<=n ); 1160 i = n-1; 1161 do 1162 { 1163 tmp = x[i]; 1164 x[i] = x[0]; 1165 x[0] = tmp; 1166 tmp = y[i]; 1167 y[i] = y[0]; 1168 y[0] = tmp; 1169 tmp = d[i]; 1170 d[i] = d[0]; 1171 d[0] = tmp; 1172 t = 1; 1173 while( t!=0 ) 1174 { 1175 k = 2*t; 1176 if( k>i ) 1177 { 1178 t = 0; 1179 } 1180 else 1181 { 1182 if( k<i ) 1183 { 1184 if( x[k]>x[k-1] ) 1185 { 1186 k = k+1; 1187 } 1188 } 1189 if( x[t-1]>=x[k-1] ) 1190 { 1191 t = 0; 1192 } 1193 else 1194 { 1195 tmp = x[k-1]; 1196 x[k-1] = x[t-1]; 1197 x[t-1] = tmp; 1198 tmp = y[k-1]; 1199 y[k-1] = y[t-1]; 1200 y[t-1] = tmp; 1201 tmp = d[k-1]; 1202 d[k-1] = d[t-1]; 1203 d[t-1] = tmp; 1204 t = k; 1205 } 1206 } 1207 } 1208 i = i-1; 1209 } 1210 while( i>=1 ); 1211 } 1212 1213 1214 /************************************************************************* 1215 Internal subroutine. Tridiagonal solver. 1216 *************************************************************************/ 1217 private static void solvetridiagonal(double[] a, 1218 double[] b, 1219 double[] c, 1220 double[] d, 1221 int n, 1222 ref double[] x) 1223 { 1224 int k = 0; 1225 double t = 0; 1226 1227 a = (double[])a.Clone(); 1228 b = (double[])b.Clone(); 1229 c = (double[])c.Clone(); 1230 d = (double[])d.Clone(); 1231 1232 x = new double[n-1+1]; 1233 a[0] = 0; 1234 c[n-1] = 0; 1235 for(k=1; k<=n-1; k++) 1236 { 1237 t = a[k]/b[k-1]; 1238 b[k] = b[k]-t*c[k-1]; 1239 d[k] = d[k]-t*d[k-1]; 1240 } 1241 x[n-1] = d[n-1]/b[n-1]; 1242 for(k=n-2; k>=0; k--) 1243 { 1244 x[k] = (d[k]-c[k]*x[k+1])/b[k]; 1245 } 1246 } 1247 1248 1249 /************************************************************************* 1250 Internal subroutine. Three-point differentiation 1251 *************************************************************************/ 1252 private static double diffthreepoint(double t, 1253 double x0, 1254 double f0, 1255 double x1, 1256 double f1, 1257 double x2, 1258 double f2) 1259 { 1260 double result = 0; 1261 double a = 0; 1262 double b = 0; 1263 1264 t = t-x0; 1265 x1 = x1-x0; 1266 x2 = x2-x0; 1267 a = (f2-f0-x2/x1*(f1-f0))/(AP.Math.Sqr(x2)-x1*x2); 1268 b = (f1-f0-a*AP.Math.Sqr(x1))/x1; 1269 result = 2*a*t+b; 1270 return result; 1271 } 1281 1272 } 1282 1273 }
Note: See TracChangeset
for help on using the changeset viewer.