/************************************************************************* * Internal AutoGK subroutine * eps<0 - error * eps=0 - automatic eps selection * * width<0 - error * width=0 - no width requirements *************************************************************************/ private static void autogkinternalprepare(double a, double b, double eps, double xwidth, ref autogkinternalstate state) { // // Save settings // state.a = a; state.b = b; state.eps = eps; state.xwidth = xwidth; // // Prepare RComm structure // state.rstate.ia = new int[3 + 1]; state.rstate.ra = new double[8 + 1]; state.rstate.stage = -1; }
/************************************************************************* Internal AutoGK subroutine *************************************************************************/ private static bool autogkinternaliteration(autogkinternalstate state) { bool result = new bool(); double c1 = 0; double c2 = 0; int i = 0; int j = 0; double intg = 0; double intk = 0; double inta = 0; double v = 0; double ta = 0; double tb = 0; int ns = 0; double qeps = 0; int info = 0; // // Reverse communication preparations // I know it looks ugly, but it works the same way // anywhere from C++ to Python. // // This code initializes locals by: // * random values determined during code // generation - on first subroutine call // * values from previous call - on subsequent calls // if( state.rstate.stage>=0 ) { i = state.rstate.ia[0]; j = state.rstate.ia[1]; ns = state.rstate.ia[2]; info = state.rstate.ia[3]; c1 = state.rstate.ra[0]; c2 = state.rstate.ra[1]; intg = state.rstate.ra[2]; intk = state.rstate.ra[3]; inta = state.rstate.ra[4]; v = state.rstate.ra[5]; ta = state.rstate.ra[6]; tb = state.rstate.ra[7]; qeps = state.rstate.ra[8]; } else { i = 497; j = -271; ns = -581; info = 745; c1 = -533; c2 = -77; intg = 678; intk = -293; inta = 316; v = 647; ta = -756; tb = 830; qeps = -871; } if( state.rstate.stage==0 ) { goto lbl_0; } if( state.rstate.stage==1 ) { goto lbl_1; } if( state.rstate.stage==2 ) { goto lbl_2; } // // Routine body // // // initialize quadratures. // use 15-point Gauss-Kronrod formula. // state.n = 15; gkq.gkqgenerategausslegendre(state.n, ref info, ref state.qn, ref state.wk, ref state.wg); if( info<0 ) { state.info = -5; state.r = 0; result = false; return result; } state.wr = new double[state.n]; for(i=0; i<=state.n-1; i++) { if( i==0 ) { state.wr[i] = 0.5*Math.Abs(state.qn[1]-state.qn[0]); continue; } if( i==state.n-1 ) { state.wr[state.n-1] = 0.5*Math.Abs(state.qn[state.n-1]-state.qn[state.n-2]); continue; } state.wr[i] = 0.5*Math.Abs(state.qn[i-1]-state.qn[i+1]); } // // special case // if( (double)(state.a)==(double)(state.b) ) { state.info = 1; state.r = 0; result = false; return result; } // // test parameters // if( (double)(state.eps)<(double)(0) || (double)(state.xwidth)<(double)(0) ) { state.info = -1; state.r = 0; result = false; return result; } state.info = 1; if( (double)(state.eps)==(double)(0) ) { state.eps = 100000*math.machineepsilon; } // // First, prepare heap // * column 0 - absolute error // * column 1 - integral of a F(x) (calculated using Kronrod extension nodes) // * column 2 - integral of a |F(x)| (calculated using modified rect. method) // * column 3 - left boundary of a subinterval // * column 4 - right boundary of a subinterval // if( (double)(state.xwidth)!=(double)(0) ) { goto lbl_3; } // // no maximum width requirements // start from one big subinterval // state.heapwidth = 5; state.heapsize = 1; state.heapused = 1; state.heap = new double[state.heapsize, state.heapwidth]; c1 = 0.5*(state.b-state.a); c2 = 0.5*(state.b+state.a); intg = 0; intk = 0; inta = 0; i = 0; lbl_5: if( i>state.n-1 ) { goto lbl_7; } // // obtain F // state.x = c1*state.qn[i]+c2; state.rstate.stage = 0; goto lbl_rcomm; lbl_0: v = state.f; // // Gauss-Kronrod formula // intk = intk+v*state.wk[i]; if( i%2==1 ) { intg = intg+v*state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta+Math.Abs(v)*state.wr[i]; i = i+1; goto lbl_5; lbl_7: intk = intk*(state.b-state.a)*0.5; intg = intg*(state.b-state.a)*0.5; inta = inta*(state.b-state.a)*0.5; state.heap[0,0] = Math.Abs(intg-intk); state.heap[0,1] = intk; state.heap[0,2] = inta; state.heap[0,3] = state.a; state.heap[0,4] = state.b; state.sumerr = state.heap[0,0]; state.sumabs = Math.Abs(inta); goto lbl_4; lbl_3: // // maximum subinterval should be no more than XWidth. // so we create Ceil((B-A)/XWidth)+1 small subintervals // ns = (int)Math.Ceiling(Math.Abs(state.b-state.a)/state.xwidth)+1; state.heapsize = ns; state.heapused = ns; state.heapwidth = 5; state.heap = new double[state.heapsize, state.heapwidth]; state.sumerr = 0; state.sumabs = 0; j = 0; lbl_8: if( j>ns-1 ) { goto lbl_10; } ta = state.a+j*(state.b-state.a)/ns; tb = state.a+(j+1)*(state.b-state.a)/ns; c1 = 0.5*(tb-ta); c2 = 0.5*(tb+ta); intg = 0; intk = 0; inta = 0; i = 0; lbl_11: if( i>state.n-1 ) { goto lbl_13; } // // obtain F // state.x = c1*state.qn[i]+c2; state.rstate.stage = 1; goto lbl_rcomm; lbl_1: v = state.f; // // Gauss-Kronrod formula // intk = intk+v*state.wk[i]; if( i%2==1 ) { intg = intg+v*state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta+Math.Abs(v)*state.wr[i]; i = i+1; goto lbl_11; lbl_13: intk = intk*(tb-ta)*0.5; intg = intg*(tb-ta)*0.5; inta = inta*(tb-ta)*0.5; state.heap[j,0] = Math.Abs(intg-intk); state.heap[j,1] = intk; state.heap[j,2] = inta; state.heap[j,3] = ta; state.heap[j,4] = tb; state.sumerr = state.sumerr+state.heap[j,0]; state.sumabs = state.sumabs+Math.Abs(inta); j = j+1; goto lbl_8; lbl_10: lbl_4: // // method iterations // lbl_14: if( false ) { goto lbl_15; } // // additional memory if needed // if( state.heapused==state.heapsize ) { mheapresize(ref state.heap, ref state.heapsize, 4*state.heapsize, state.heapwidth); } // // TODO: every 20 iterations recalculate errors/sums // if( (double)(state.sumerr)<=(double)(state.eps*state.sumabs) || state.heapused>=maxsubintervals ) { state.r = 0; for(j=0; j<=state.heapused-1; j++) { state.r = state.r+state.heap[j,1]; } result = false; return result; } // // Exclude interval with maximum absolute error // mheappop(ref state.heap, state.heapused, state.heapwidth); state.sumerr = state.sumerr-state.heap[state.heapused-1,0]; state.sumabs = state.sumabs-state.heap[state.heapused-1,2]; // // Divide interval, create subintervals // ta = state.heap[state.heapused-1,3]; tb = state.heap[state.heapused-1,4]; state.heap[state.heapused-1,3] = ta; state.heap[state.heapused-1,4] = 0.5*(ta+tb); state.heap[state.heapused,3] = 0.5*(ta+tb); state.heap[state.heapused,4] = tb; j = state.heapused-1; lbl_16: if( j>state.heapused ) { goto lbl_18; } c1 = 0.5*(state.heap[j,4]-state.heap[j,3]); c2 = 0.5*(state.heap[j,4]+state.heap[j,3]); intg = 0; intk = 0; inta = 0; i = 0; lbl_19: if( i>state.n-1 ) { goto lbl_21; } // // F(x) // state.x = c1*state.qn[i]+c2; state.rstate.stage = 2; goto lbl_rcomm; lbl_2: v = state.f; // // Gauss-Kronrod formula // intk = intk+v*state.wk[i]; if( i%2==1 ) { intg = intg+v*state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta+Math.Abs(v)*state.wr[i]; i = i+1; goto lbl_19; lbl_21: intk = intk*(state.heap[j,4]-state.heap[j,3])*0.5; intg = intg*(state.heap[j,4]-state.heap[j,3])*0.5; inta = inta*(state.heap[j,4]-state.heap[j,3])*0.5; state.heap[j,0] = Math.Abs(intg-intk); state.heap[j,1] = intk; state.heap[j,2] = inta; state.sumerr = state.sumerr+state.heap[j,0]; state.sumabs = state.sumabs+state.heap[j,2]; j = j+1; goto lbl_16; lbl_18: mheappush(ref state.heap, state.heapused-1, state.heapwidth); mheappush(ref state.heap, state.heapused, state.heapwidth); state.heapused = state.heapused+1; goto lbl_14; lbl_15: result = false; return result; // // Saving state // lbl_rcomm: result = true; state.rstate.ia[0] = i; state.rstate.ia[1] = j; state.rstate.ia[2] = ns; state.rstate.ia[3] = info; state.rstate.ra[0] = c1; state.rstate.ra[1] = c2; state.rstate.ra[2] = intg; state.rstate.ra[3] = intk; state.rstate.ra[4] = inta; state.rstate.ra[5] = v; state.rstate.ra[6] = ta; state.rstate.ra[7] = tb; state.rstate.ra[8] = qeps; return result; }
/************************************************************************* Internal AutoGK subroutine eps<0 - error eps=0 - automatic eps selection width<0 - error width=0 - no width requirements *************************************************************************/ private static void autogkinternalprepare(double a, double b, double eps, double xwidth, autogkinternalstate state) { // // Save settings // state.a = a; state.b = b; state.eps = eps; state.xwidth = xwidth; // // Prepare RComm structure // state.rstate.ia = new int[3+1]; state.rstate.ra = new double[8+1]; state.rstate.stage = -1; }
public override void init() { internalstate = new autogkinternalstate(); rstate = new rcommstate(); }
public override alglib.apobject make_copy() { autogkinternalstate _result = new autogkinternalstate(); _result.a = a; _result.b = b; _result.eps = eps; _result.xwidth = xwidth; _result.x = x; _result.f = f; _result.info = info; _result.r = r; _result.heap = (double[,])heap.Clone(); _result.heapsize = heapsize; _result.heapwidth = heapwidth; _result.heapused = heapused; _result.sumerr = sumerr; _result.sumabs = sumabs; _result.qn = (double[])qn.Clone(); _result.wg = (double[])wg.Clone(); _result.wk = (double[])wk.Clone(); _result.wr = (double[])wr.Clone(); _result.n = n; _result.rstate = (rcommstate)rstate.make_copy(); return _result; }
public autogkstate() { internalstate = new autogkinternalstate(); rstate = new rcommstate(); }
/************************************************************************* * Internal AutoGK subroutine *************************************************************************/ private static bool autogkinternaliteration(ref autogkinternalstate state) { bool result = new bool(); double c1 = 0; double c2 = 0; int i = 0; int j = 0; double intg = 0; double intk = 0; double inta = 0; double v = 0; double ta = 0; double tb = 0; int ns = 0; double qeps = 0; int info = 0; // // Reverse communication preparations // I know it looks ugly, but it works the same way // anywhere from C++ to Python. // // This code initializes locals by: // * random values determined during code // generation - on first subroutine call // * values from previous call - on subsequent calls // if (state.rstate.stage >= 0) { i = state.rstate.ia[0]; j = state.rstate.ia[1]; ns = state.rstate.ia[2]; info = state.rstate.ia[3]; c1 = state.rstate.ra[0]; c2 = state.rstate.ra[1]; intg = state.rstate.ra[2]; intk = state.rstate.ra[3]; inta = state.rstate.ra[4]; v = state.rstate.ra[5]; ta = state.rstate.ra[6]; tb = state.rstate.ra[7]; qeps = state.rstate.ra[8]; } else { i = 497; j = -271; ns = -581; info = 745; c1 = -533; c2 = -77; intg = 678; intk = -293; inta = 316; v = 647; ta = -756; tb = 830; qeps = -871; } if (state.rstate.stage == 0) { goto lbl_0; } if (state.rstate.stage == 1) { goto lbl_1; } if (state.rstate.stage == 2) { goto lbl_2; } // // Routine body // // // initialize quadratures. // use 15-point Gauss-Kronrod formula. // state.n = 15; gkq.gkqgenerategausslegendre(state.n, ref info, ref state.qn, ref state.wk, ref state.wg); if (info < 0) { state.info = -5; state.r = 0; result = false; return(result); } state.wr = new double[state.n]; for (i = 0; i <= state.n - 1; i++) { if (i == 0) { state.wr[i] = 0.5 * Math.Abs(state.qn[1] - state.qn[0]); continue; } if (i == state.n - 1) { state.wr[state.n - 1] = 0.5 * Math.Abs(state.qn[state.n - 1] - state.qn[state.n - 2]); continue; } state.wr[i] = 0.5 * Math.Abs(state.qn[i - 1] - state.qn[i + 1]); } // // special case // if ((double)(state.a) == (double)(state.b)) { state.info = 1; state.r = 0; result = false; return(result); } // // test parameters // if ((double)(state.eps) < (double)(0) | (double)(state.xwidth) < (double)(0)) { state.info = -1; state.r = 0; result = false; return(result); } state.info = 1; if ((double)(state.eps) == (double)(0)) { state.eps = 1000 * AP.Math.MachineEpsilon; } // // First, prepare heap // * column 0 - absolute error // * column 1 - integral of a F(x) (calculated using Kronrod extension nodes) // * column 2 - integral of a |F(x)| (calculated using modified rect. method) // * column 3 - left boundary of a subinterval // * column 4 - right boundary of a subinterval // if ((double)(state.xwidth) != (double)(0)) { goto lbl_3; } // // no maximum width requirements // start from one big subinterval // state.heapwidth = 5; state.heapsize = 1; state.heapused = 1; state.heap = new double[state.heapsize, state.heapwidth]; c1 = 0.5 * (state.b - state.a); c2 = 0.5 * (state.b + state.a); intg = 0; intk = 0; inta = 0; i = 0; lbl_5: if (i > state.n - 1) { goto lbl_7; } // // obtain F // state.x = c1 * state.qn[i] + c2; state.rstate.stage = 0; goto lbl_rcomm; lbl_0: v = state.f; // // Gauss-Kronrod formula // intk = intk + v * state.wk[i]; if (i % 2 == 1) { intg = intg + v * state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta + Math.Abs(v) * state.wr[i]; i = i + 1; goto lbl_5; lbl_7: intk = intk * (state.b - state.a) * 0.5; intg = intg * (state.b - state.a) * 0.5; inta = inta * (state.b - state.a) * 0.5; state.heap[0, 0] = Math.Abs(intg - intk); state.heap[0, 1] = intk; state.heap[0, 2] = inta; state.heap[0, 3] = state.a; state.heap[0, 4] = state.b; state.sumerr = state.heap[0, 0]; state.sumabs = Math.Abs(inta); goto lbl_4; lbl_3: // // maximum subinterval should be no more than XWidth. // so we create Ceil((B-A)/XWidth)+1 small subintervals // ns = (int)Math.Ceiling(Math.Abs(state.b - state.a) / state.xwidth) + 1; state.heapsize = ns; state.heapused = ns; state.heapwidth = 5; state.heap = new double[state.heapsize, state.heapwidth]; state.sumerr = 0; state.sumabs = 0; j = 0; lbl_8: if (j > ns - 1) { goto lbl_10; } ta = state.a + j * (state.b - state.a) / ns; tb = state.a + (j + 1) * (state.b - state.a) / ns; c1 = 0.5 * (tb - ta); c2 = 0.5 * (tb + ta); intg = 0; intk = 0; inta = 0; i = 0; lbl_11: if (i > state.n - 1) { goto lbl_13; } // // obtain F // state.x = c1 * state.qn[i] + c2; state.rstate.stage = 1; goto lbl_rcomm; lbl_1: v = state.f; // // Gauss-Kronrod formula // intk = intk + v * state.wk[i]; if (i % 2 == 1) { intg = intg + v * state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta + Math.Abs(v) * state.wr[i]; i = i + 1; goto lbl_11; lbl_13: intk = intk * (tb - ta) * 0.5; intg = intg * (tb - ta) * 0.5; inta = inta * (tb - ta) * 0.5; state.heap[j, 0] = Math.Abs(intg - intk); state.heap[j, 1] = intk; state.heap[j, 2] = inta; state.heap[j, 3] = ta; state.heap[j, 4] = tb; state.sumerr = state.sumerr + state.heap[j, 0]; state.sumabs = state.sumabs + Math.Abs(inta); j = j + 1; goto lbl_8; lbl_10: lbl_4: // // method iterations // lbl_14: if (false) { goto lbl_15; } // // additional memory if needed // if (state.heapused == state.heapsize) { mheapresize(ref state.heap, ref state.heapsize, 4 * state.heapsize, state.heapwidth); } // // TODO: every 20 iterations recalculate errors/sums // TODO: one more criterion to prevent infinite loops with too strict Eps // if ((double)(state.sumerr) <= (double)(state.eps * state.sumabs)) { state.r = 0; for (j = 0; j <= state.heapused - 1; j++) { state.r = state.r + state.heap[j, 1]; } result = false; return(result); } // // Exclude interval with maximum absolute error // mheappop(ref state.heap, state.heapused, state.heapwidth); state.sumerr = state.sumerr - state.heap[state.heapused - 1, 0]; state.sumabs = state.sumabs - state.heap[state.heapused - 1, 2]; // // Divide interval, create subintervals // ta = state.heap[state.heapused - 1, 3]; tb = state.heap[state.heapused - 1, 4]; state.heap[state.heapused - 1, 3] = ta; state.heap[state.heapused - 1, 4] = 0.5 * (ta + tb); state.heap[state.heapused, 3] = 0.5 * (ta + tb); state.heap[state.heapused, 4] = tb; j = state.heapused - 1; lbl_16: if (j > state.heapused) { goto lbl_18; } c1 = 0.5 * (state.heap[j, 4] - state.heap[j, 3]); c2 = 0.5 * (state.heap[j, 4] + state.heap[j, 3]); intg = 0; intk = 0; inta = 0; i = 0; lbl_19: if (i > state.n - 1) { goto lbl_21; } // // F(x) // state.x = c1 * state.qn[i] + c2; state.rstate.stage = 2; goto lbl_rcomm; lbl_2: v = state.f; // // Gauss-Kronrod formula // intk = intk + v * state.wk[i]; if (i % 2 == 1) { intg = intg + v * state.wg[i]; } // // Integral |F(x)| // Use rectangles method // inta = inta + Math.Abs(v) * state.wr[i]; i = i + 1; goto lbl_19; lbl_21: intk = intk * (state.heap[j, 4] - state.heap[j, 3]) * 0.5; intg = intg * (state.heap[j, 4] - state.heap[j, 3]) * 0.5; inta = inta * (state.heap[j, 4] - state.heap[j, 3]) * 0.5; state.heap[j, 0] = Math.Abs(intg - intk); state.heap[j, 1] = intk; state.heap[j, 2] = inta; state.sumerr = state.sumerr + state.heap[j, 0]; state.sumabs = state.sumabs + state.heap[j, 2]; j = j + 1; goto lbl_16; lbl_18: mheappush(ref state.heap, state.heapused - 1, state.heapwidth); mheappush(ref state.heap, state.heapused, state.heapwidth); state.heapused = state.heapused + 1; goto lbl_14; lbl_15: result = false; return(result); // // Saving state // lbl_rcomm: result = true; state.rstate.ia[0] = i; state.rstate.ia[1] = j; state.rstate.ia[2] = ns; state.rstate.ia[3] = info; state.rstate.ra[0] = c1; state.rstate.ra[1] = c2; state.rstate.ra[2] = intg; state.rstate.ra[3] = intk; state.rstate.ra[4] = inta; state.rstate.ra[5] = v; state.rstate.ra[6] = ta; state.rstate.ra[7] = tb; state.rstate.ra[8] = qeps; return(result); }