setLastRow() public method

public setLastRow ( double valA, double valB ) : void
valA double
valB double
return void
コード例 #1
0
      public override void update()
      {
         TridiagonalOperator L = new TridiagonalOperator(cH_.n_);

         Array<double> tmp = new Array<double>(cH_.n_);
         var dx = new Array<double>(cH_.n_ - 1);
         var S = new Array<double>(cH_.n_ - 1);

         int i=0;
         dx[i] = this.xBegin_[i+1] - this.xBegin_[i];
         S[i] = (this.yBegin_[i+1] - this.yBegin_[i])/dx[i];
         for (i=1; i<cH_.n_-1; ++i) {
           dx[i] = this.xBegin_[i+1] - this.xBegin_[i];
           S[i] = (this.yBegin_[i+1] - this.yBegin_[i])/dx[i];

           L.setMidRow(i, dx[i], 2.0*(dx[i]+dx[i-1]), dx[i-1]);
           tmp[i] = 3.0*(dx[i]*S[i-1] + dx[i-1]*S[i]);
         }

         /**** BOUNDARY CONDITIONS ****/

         // left condition
         switch (leftType_) 
         {
            case CubicSplineInterpolation.BoundaryCondition.NotAKnot:
              // ignoring end condition value
              L.setFirstRow(dx[1]*(dx[1]+dx[0]),
                            (dx[0]+dx[1])*(dx[0]+dx[1]));
              tmp[0] = S[0]*dx[1]*(2.0*dx[1]+3.0*dx[0]) +
                       S[1]*dx[0]*dx[0];
              break;
            case CubicSplineInterpolation.BoundaryCondition.FirstDerivative:
              L.setFirstRow(1.0, 0.0);
              tmp[0] = leftValue_;
              break;
            case CubicSplineInterpolation.BoundaryCondition.SecondDerivative:
              L.setFirstRow(2.0, 1.0);
              tmp[0] = 3.0*S[0] - leftValue_*dx[0]/2.0;
              break;
            case CubicSplineInterpolation.BoundaryCondition.Periodic:
            case CubicSplineInterpolation.BoundaryCondition.Lagrange:
              // ignoring end condition value
              throw new ApplicationException("this end condition is not implemented yet");
            default:
              throw new ApplicationException("unknown end condition");
         }

         // right condition
         switch (rightType_) 
         {
            case CubicSplineInterpolation.BoundaryCondition.NotAKnot:
              // ignoring end condition value
              L.setLastRow(-(dx[cH_.n_-2]+dx[cH_.n_-3])*(dx[cH_.n_-2]+dx[cH_.n_-3]),
                           -dx[cH_.n_-3]*(dx[cH_.n_-3]+dx[cH_.n_-2]));
              tmp[cH_.n_-1] = -S[cH_.n_-3]*dx[cH_.n_-2]*dx[cH_.n_-2] -
                           S[cH_.n_-2]*dx[cH_.n_-3]*(3.0*dx[cH_.n_-2]+2.0*dx[cH_.n_-3]);
              break;
            case CubicSplineInterpolation.BoundaryCondition.FirstDerivative:
              L.setLastRow(0.0, 1.0);
              tmp[cH_.n_-1] = rightValue_;
              break;
            case CubicSplineInterpolation.BoundaryCondition.SecondDerivative:
              L.setLastRow(1.0, 2.0);
              tmp[cH_.n_-1] = 3.0*S[cH_.n_-2] + rightValue_*dx[cH_.n_-2]/2.0;
              break;
            case CubicSplineInterpolation.BoundaryCondition.Periodic:
            case CubicSplineInterpolation.BoundaryCondition.Lagrange:
              // ignoring end condition value
              throw new ApplicationException("this end condition is not implemented yet");
            default:
              throw new ApplicationException("unknown end condition");
         }

         // solve the system
         tmp = L.solveFor(tmp);

         for (int j = 0; i < cH_.monotonicityAdjustments_.Count; j++ )
            cH_.monotonicityAdjustments_[j] = false;

         if (constrained_) 
         {
           double correction;
           double pm, pu, pd, M;
           for (i=0; i<cH_.n_; ++i) {
               if (i==0) {
                   if (tmp[i]*S[0]>0.0) 
                   {
                       correction = tmp[i]/Math.Abs(tmp[i]) *
                           Math.Min(Math.Abs(tmp[i]),
                                    Math.Abs(3.0*S[0]));
                   } 
                   else 
                   {
                       correction = 0.0;
                   }
                   if (correction!=tmp[i]) 
                   {
                       tmp[i] = correction;
                       cH_.monotonicityAdjustments_[i] = true;
                   }
               } 
               else if (i==cH_.n_-1) 
               {
                  if (tmp[i]*S[cH_.n_-2]>0.0) 
                   {
                       correction = tmp[i]/Math.Abs(tmp[i]) *
                           Math.Min(Math.Abs(tmp[i]),
                                    Math.Abs(3.0*S[cH_.n_-2]));
                   } 
                   else 
                   {
                       correction = 0.0;
                   }
                   if (correction!=tmp[i]) 
                   {
                       tmp[i] = correction;
                       cH_.monotonicityAdjustments_[i] = true;
                   }
               } 
               else 
               {
                   pm=(S[i-1]*dx[i]+S[i]*dx[i-1])/
                       (dx[i-1]+dx[i]);
                   M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i-1]),
                                               Math.Abs(S[i])),
                                      Math.Abs(pm));
                   if (i>1) 
                   {
                       if ((S[i-1]-S[i-2])*(S[i]-S[i-1])>0.0) 
                       {
                           pd=(S[i-1]*(2.0*dx[i-1]+dx[i-2])
                               -S[i-2]*dx[i-1])/
                               (dx[i-2]+dx[i-1]);
                           if (pm*pd>0.0 && pm*(S[i-1]-S[i-2])>0.0) 
                           {
                               M = Math.Max(M, 1.5*Math.Min(
                                       Math.Abs(pm),Math.Abs(pd)));
                           }
                       }
                   }
                   if (i<cH_.n_-2) 
                   {
                       if ((S[i]-S[i-1])*(S[i+1]-S[i])>0.0) 
                       {
                           pu=(S[i]*(2.0*dx[i]+dx[i+1])-S[i+1]*dx[i])/
                               (dx[i]+dx[i+1]);
                           if (pm*pu>0.0 && -pm*(S[i]-S[i-1])>0.0) 
                           {
                               M = Math.Max(M, 1.5*Math.Min(
                                       Math.Abs(pm),Math.Abs(pu)));
                           }
                       }
                   }
                   if (tmp[i]*pm>0.0) 
                   {
                       correction = tmp[i]/Math.Abs(tmp[i]) *
                           Math.Min(Math.Abs(tmp[i]), M);
                   } 
                   else 
                   {
                       correction = 0.0;
                   }
                   if (correction!=tmp[i]) 
                   {
                       tmp[i] = correction;
                       cH_.monotonicityAdjustments_[i] = true;
                   }
               }
           }
         }

         for (i=0; i<cH_.n_-1; ++i) 
         {
           cH_.a_[i] = tmp[i];
           cH_.b_[i] = (3.0*S[i] - tmp[i+1] - 2.0*tmp[i])/dx[i];
           cH_.c_[i] = (tmp[i+1] + tmp[i] - 2.0*S[i])/(dx[i]*dx[i]);
         }

         cH_.primitiveConst_[0] = 0.0;
         for (i=1; i<cH_.n_-1; ++i) 
         {
           cH_.primitiveConst_[i] = cH_.primitiveConst_[i-1]
               + dx[i-1] *
               (this.yBegin_[i-1] + dx[i-1] *
                (cH_.a_[i-1]/2.0 + dx[i-1] *
                 (cH_.b_[i-1]/3.0 + dx[i-1] * cH_.c_[i-1]/4.0)));
         }
      }
コード例 #2
0
        public override void update()
        {
            Vector tmp = new Vector(size_);
            List<double> dx = new InitializedList<double>(size_ - 1),
                         S = new InitializedList<double>(size_ - 1);

            for (int i = 0; i < size_ - 1; ++i) {
                dx[i] = xBegin_[i+1] - xBegin_[i];
                S[i] = (yBegin_[i+1] - yBegin_[i])/dx[i];
            }

            // first derivative approximation
            if (da_==CubicInterpolation.DerivativeApprox.Spline) {
                TridiagonalOperator L = new TridiagonalOperator(size_);
                for (int i = 1; i < size_ - 1; ++i) {
                    L.setMidRow(i, dx[i], 2.0*(dx[i]+dx[i-1]), dx[i-1]);
                    tmp[i] = 3.0*(dx[i]*S[i-1] + dx[i-1]*S[i]);
                }

                // left boundary condition
                switch (leftType_) {
                    case CubicInterpolation.BoundaryCondition.NotAKnot:
                        // ignoring end condition value
                        L.setFirstRow(dx[1]*(dx[1]+dx[0]), (dx[0]+dx[1])*(dx[0]+dx[1]));
                        tmp[0] = S[0]*dx[1]*(2.0*dx[1]+3.0*dx[0]) + S[1]*dx[0]*dx[0];
                        break;
                    case CubicInterpolation.BoundaryCondition.FirstDerivative:
                        L.setFirstRow(1.0, 0.0);
                        tmp[0] = leftValue_;
                        break;
                    case CubicInterpolation.BoundaryCondition.SecondDerivative:
                        L.setFirstRow(2.0, 1.0);
                        tmp[0] = 3.0*S[0] - leftValue_*dx[0]/2.0;
                        break;
                    case CubicInterpolation.BoundaryCondition.Periodic:
                    case CubicInterpolation.BoundaryCondition.Lagrange:
                        // ignoring end condition value
                        throw new NotImplementedException("this end condition is not implemented yet");
                    default:
                        throw new ArgumentException("unknown end condition");
                }

                // right boundary condition
                switch (rightType_) {
                    case CubicInterpolation.BoundaryCondition.NotAKnot:
                        // ignoring end condition value
                        L.setLastRow(-(dx[size_ - 2] + dx[size_ - 3]) * (dx[size_ - 2] + dx[size_ - 3]),
                                     -dx[size_ - 3] * (dx[size_ - 3] + dx[size_ - 2]));
                        tmp[size_ - 1] = -S[size_ - 3] * dx[size_ - 2] * dx[size_ - 2] -
                                     S[size_ - 2] * dx[size_ - 3] * (3.0 * dx[size_ - 2] + 2.0 * dx[size_ - 3]);
                        break;
                    case CubicInterpolation.BoundaryCondition.FirstDerivative:
                        L.setLastRow(0.0, 1.0);
                        tmp[size_ - 1] = rightValue_;
                        break;
                    case CubicInterpolation.BoundaryCondition.SecondDerivative:
                        L.setLastRow(1.0, 2.0);
                        tmp[size_ - 1] = 3.0 * S[size_ - 2] + rightValue_ * dx[size_ - 2] / 2.0;
                        break;
                    case CubicInterpolation.BoundaryCondition.Periodic:
                    case CubicInterpolation.BoundaryCondition.Lagrange:
                        // ignoring end condition value
                        throw new NotImplementedException("this end condition is not implemented yet");
                    default:
                        throw new ArgumentException("unknown end condition");
                }

                // solve the system
                tmp = L.solveFor(tmp);
            } else { // local schemes
                if (size_ == 2)
                    tmp[0] = tmp[1] = S[0];
                else {
                    switch (da_) {
                        case CubicInterpolation.DerivativeApprox.FourthOrder:
                            throw new NotImplementedException("FourthOrder not implemented yet");
                            break;
                        case CubicInterpolation.DerivativeApprox.Parabolic:
                            // intermediate points
                            for (int i = 1; i < size_ - 1; ++i) {
                                tmp[i] = (dx[i - 1] * S[i] + dx[i] * S[i - 1]) / (dx[i] + dx[i - 1]);
                            }
                            // end points
                            tmp[0] = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                            tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                            break;
                            break;
                        case CubicInterpolation.DerivativeApprox.FritschButland:
                            // intermediate points
                            for (int i=1; i<size_-1; ++i) {
                                double Smin = Math.Min(S[i-1], S[i]);
                                double Smax = Math.Max(S[i-1], S[i]);
                                tmp[i] = 3.0*Smin*Smax/(Smax+2.0*Smin);
                            }
                            // end points
                            tmp[0]    = ((2.0*dx[   0]+dx[   1])*S[   0] - dx[   0]*S[   1]) / (dx[   0]+dx[   1]);
                            tmp[size_-1] = ((2.0*dx[size_-2]+dx[size_-3])*S[size_-2] - dx[size_-2]*S[size_-3]) / (dx[size_-2]+dx[size_-3]);
                            break;
                        case CubicInterpolation.DerivativeApprox.Akima:
                            throw new NotImplementedException("Akima not implemented yet");
                            // end points
                            tmp[0] = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                            tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                            break;
                        case CubicInterpolation.DerivativeApprox.Kruger:
                            // intermediate points
                            for (int i = 1; i < size_ - 1; ++i) {
                                if (S[i-1]*S[i]<0.0)
                                    // slope changes sign at point
                                    tmp[i] = 0.0;
                                else
                                    // slope will be between the slopes of the adjacent
                                    // straight lines and should approach zero if the
                                    // slope of either line approaches zero
                                    tmp[i] = 2.0/(1.0/S[i-1]+1.0/S[i]);
                            }
                            // end points
                            tmp[0] = (3.0*S[0]-tmp[1])/2.0;
                            tmp[size_ - 1] = (3.0 * S[size_ - 2] - tmp[size_ - 2]) / 2.0;
                            break;
                        default:
                            throw new ArgumentException("unknown scheme");
                    }
                }
            }

            monotonicityAdjustments_.Erase();

            // Hyman monotonicity constrained filter
            if (monotonic_) {
                double correction;
                double pm, pu, pd, M;
                for (int i = 0; i < size_; ++i) {
                    if (i==0) {
                        if (tmp[i]*S[0]>0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]),
                                               Math.Abs(3.0*S[0]));
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    } else if (i == size_ - 1) {
                        if (tmp[i] * S[size_ - 2] > 0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]), Math.Abs(3.0 * S[size_ - 2]));
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    } else {
                        pm=(S[i-1]*dx[i]+S[i]*dx[i-1])/
                            (dx[i-1]+dx[i]);
                        M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i-1]), Math.Abs(S[i])),
                                           Math.Abs(pm));
                        if (i>1) {
                            if ((S[i-1]-S[i-2])*(S[i]-S[i-1])>0.0) {
                                pd=(S[i-1]*(2.0*dx[i-1]+dx[i-2])
                                    -S[i-2]*dx[i-1])/
                                    (dx[i-2]+dx[i-1]);
                                if (pm*pd>0.0 && pm*(S[i-1]-S[i-2])>0.0) {
                                    M = Math.Max(M, 1.5*Math.Min(
                                            Math.Abs(pm),Math.Abs(pd)));
                                }
                            }
                        }
                        if (i < size_ - 2) {
                            if ((S[i]-S[i-1])*(S[i+1]-S[i])>0.0) {
                                pu=(S[i]*(2.0*dx[i]+dx[i+1])-S[i+1]*dx[i])/
                                    (dx[i]+dx[i+1]);
                                if (pm*pu>0.0 && -pm*(S[i]-S[i-1])>0.0) {
                                    M = Math.Max(M, 1.5*Math.Min(
                                            Math.Abs(pm),Math.Abs(pu)));
                                }
                            }
                        }
                        if (tmp[i]*pm>0.0) {
                            correction = tmp[i]/Math.Abs(tmp[i]) *
                                Math.Min(Math.Abs(tmp[i]), M);
                        } else {
                            correction = 0.0;
                        }
                        if (correction!=tmp[i]) {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                }
            }

            // cubic coefficients
            for (int i = 0; i < size_ - 1; ++i) {
                a_[i] = tmp[i];
                b_[i] = (3.0*S[i] - tmp[i+1] - 2.0*tmp[i])/dx[i];
                c_[i] = (tmp[i+1] + tmp[i] - 2.0*S[i])/(dx[i]*dx[i]);
            }

            primitiveConst_[0] = 0.0;
            for (int i = 1; i < size_ - 1; ++i) {
                primitiveConst_[i] = primitiveConst_[i-1]
                    + dx[i-1] *
                    (yBegin_[i-1] + dx[i-1] *
                     (a_[i-1]/2.0 + dx[i-1] *
                      (b_[i-1]/3.0 + dx[i-1] * c_[i-1]/4.0)));
            }
        }
コード例 #3
0
        public override void update()
        {
            Vector        tmp = new Vector(size_);
            List <double> dx  = new InitializedList <double>(size_ - 1),
                          S   = new InitializedList <double>(size_ - 1);

            for (int i = 0; i < size_ - 1; ++i)
            {
                dx[i] = xBegin_[i + 1] - xBegin_[i];
                S[i]  = (yBegin_[i + 1] - yBegin_[i]) / dx[i];
            }

            // first derivative approximation
            if (da_ == CubicInterpolation.DerivativeApprox.Spline)
            {
                TridiagonalOperator L = new TridiagonalOperator(size_);
                for (int i = 1; i < size_ - 1; ++i)
                {
                    L.setMidRow(i, dx[i], 2.0 * (dx[i] + dx[i - 1]), dx[i - 1]);
                    tmp[i] = 3.0 * (dx[i] * S[i - 1] + dx[i - 1] * S[i]);
                }

                // left boundary condition
                switch (leftType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setFirstRow(dx[1] * (dx[1] + dx[0]), (dx[0] + dx[1]) * (dx[0] + dx[1]));
                    tmp[0] = S[0] * dx[1] * (2.0 * dx[1] + 3.0 * dx[0]) + S[1] * dx[0] * dx[0];
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setFirstRow(1.0, 0.0);
                    tmp[0] = leftValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setFirstRow(2.0, 1.0);
                    tmp[0] = 3.0 * S[0] - leftValue_ * dx[0] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                case CubicInterpolation.BoundaryCondition.Lagrange:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // right boundary condition
                switch (rightType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setLastRow(-(dx[size_ - 2] + dx[size_ - 3]) * (dx[size_ - 2] + dx[size_ - 3]),
                                 -dx[size_ - 3] * (dx[size_ - 3] + dx[size_ - 2]));
                    tmp[size_ - 1] = -S[size_ - 3] * dx[size_ - 2] * dx[size_ - 2] -
                                     S[size_ - 2] * dx[size_ - 3] * (3.0 * dx[size_ - 2] + 2.0 * dx[size_ - 3]);
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setLastRow(0.0, 1.0);
                    tmp[size_ - 1] = rightValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setLastRow(1.0, 2.0);
                    tmp[size_ - 1] = 3.0 * S[size_ - 2] + rightValue_ * dx[size_ - 2] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                case CubicInterpolation.BoundaryCondition.Lagrange:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // solve the system
                tmp = L.solveFor(tmp);
            }
            else     // local schemes
            {
                if (size_ == 2)
                {
                    tmp[0] = tmp[1] = S[0];
                }
                else
                {
                    switch (da_)
                    {
                    case CubicInterpolation.DerivativeApprox.FourthOrder:
                        throw new NotImplementedException("FourthOrder not implemented yet");
                        break;

                    case CubicInterpolation.DerivativeApprox.Parabolic:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            tmp[i] = (dx[i - 1] * S[i] + dx[i] * S[i - 1]) / (dx[i] + dx[i - 1]);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;
                        break;

                    case CubicInterpolation.DerivativeApprox.FritschButland:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            double Smin = Math.Min(S[i - 1], S[i]);
                            double Smax = Math.Max(S[i - 1], S[i]);
                            tmp[i] = 3.0 * Smin * Smax / (Smax + 2.0 * Smin);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.Akima:
                        throw new NotImplementedException("Akima not implemented yet");
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.Kruger:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            if (S[i - 1] * S[i] < 0.0)
                            {
                                // slope changes sign at point
                                tmp[i] = 0.0;
                            }
                            else
                            {
                                // slope will be between the slopes of the adjacent
                                // straight lines and should approach zero if the
                                // slope of either line approaches zero
                                tmp[i] = 2.0 / (1.0 / S[i - 1] + 1.0 / S[i]);
                            }
                        }
                        // end points
                        tmp[0]         = (3.0 * S[0] - tmp[1]) / 2.0;
                        tmp[size_ - 1] = (3.0 * S[size_ - 2] - tmp[size_ - 2]) / 2.0;
                        break;

                    default:
                        throw new ArgumentException("unknown scheme");
                    }
                }
            }

            monotonicityAdjustments_.Erase();

            // Hyman monotonicity constrained filter
            if (monotonic_)
            {
                double correction;
                double pm, pu, pd, M;
                for (int i = 0; i < size_; ++i)
                {
                    if (i == 0)
                    {
                        if (tmp[i] * S[0] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]),
                                                  Math.Abs(3.0 * S[0]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction != tmp[i])
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else if (i == size_ - 1)
                    {
                        if (tmp[i] * S[size_ - 2] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), Math.Abs(3.0 * S[size_ - 2]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction != tmp[i])
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else
                    {
                        pm = (S[i - 1] * dx[i] + S[i] * dx[i - 1]) /
                             (dx[i - 1] + dx[i]);
                        M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i - 1]), Math.Abs(S[i])),
                                           Math.Abs(pm));
                        if (i > 1)
                        {
                            if ((S[i - 1] - S[i - 2]) * (S[i] - S[i - 1]) > 0.0)
                            {
                                pd = (S[i - 1] * (2.0 * dx[i - 1] + dx[i - 2])
                                      - S[i - 2] * dx[i - 1]) /
                                     (dx[i - 2] + dx[i - 1]);
                                if (pm * pd > 0.0 && pm * (S[i - 1] - S[i - 2]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pd)));
                                }
                            }
                        }
                        if (i < size_ - 2)
                        {
                            if ((S[i] - S[i - 1]) * (S[i + 1] - S[i]) > 0.0)
                            {
                                pu = (S[i] * (2.0 * dx[i] + dx[i + 1]) - S[i + 1] * dx[i]) /
                                     (dx[i] + dx[i + 1]);
                                if (pm * pu > 0.0 && -pm * (S[i] - S[i - 1]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pu)));
                                }
                            }
                        }
                        if (tmp[i] * pm > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), M);
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction != tmp[i])
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                }
            }


            // cubic coefficients
            for (int i = 0; i < size_ - 1; ++i)
            {
                a_[i] = tmp[i];
                b_[i] = (3.0 * S[i] - tmp[i + 1] - 2.0 * tmp[i]) / dx[i];
                c_[i] = (tmp[i + 1] + tmp[i] - 2.0 * S[i]) / (dx[i] * dx[i]);
            }

            primitiveConst_[0] = 0.0;
            for (int i = 1; i < size_ - 1; ++i)
            {
                primitiveConst_[i] = primitiveConst_[i - 1]
                                     + dx[i - 1] *
                                     (yBegin_[i - 1] + dx[i - 1] *
                                      (a_[i - 1] / 2.0 + dx[i - 1] *
                                       (b_[i - 1] / 3.0 + dx[i - 1] * c_[i - 1] / 4.0)));
            }
        }