/* dc_sweep.c  93.12.19
 * Copyright 1983-1992   Albert Davis
 * dc analysis sweep
 */
#include "ecah.h"
#include "branch.h"
#include "dc.h"
#include "error.h"
#include "io.h"
#include "mode.h"
#include "options.h"
#include "status.h"
#include "declare.h"
/*--------------------------------------------------------------------------*/
	void	dc_sweep(dc_t*);
static	void	dc_first(dc_t*,int);
static	int	dc_next(dc_t*,int);
/*--------------------------------------------------------------------------*/
extern       struct ioctrl io;
extern const struct options opt;
extern 	     struct status stats;
extern int   bypass_ok;
extern int   inc_mode;
/*--------------------------------------------------------------------------*/
void dc_sweep(dc_t *dc)
{
 int converged;
 
 tr_head(dc->start[0], dc->stop[0], dc->linswp[0], " ");
 bypass_ok = NO;
 inc_mode = BAD;
 if (dc->cont){
    trestor();
 }
 
 dc_first(dc,0);
 io.suppresserrors = dc->trace < tVERBOSE ;
 converged = tr_solve(opt.itl[1],dc->trace);
 if (!converged)
    error(bWARNING, "did not converge\n");
 dc_out(dc);
 
 while (dc_next(dc,0)){
    io.suppresserrors = dc->trace < tVERBOSE;
    converged = tr_solve(opt.itl[2],dc->trace);
    if (!converged)
       error(bWARNING, "did not converge\n");
    dc_out(dc);
 }
}
/*--------------------------------------------------------------------------*/
static void dc_first(dc_t *dc, int ii)
{
 *dc->sweep[ii] = dc->start[ii];
 expand_branch(dc->zap[ii]);
 
 if (dc->reverse){
    dc->reverse = NO;
    while (dc_next(dc,ii))
       /* nothing */;
    dc->reverse = YES;
    dc_next(dc,ii);
 }
 dc->printnow = YES;
 stats.control[cSTEPCAUSE] = scUSER;
}
/*--------------------------------------------------------------------------*/
static int dc_next(dc_t *dc, int ii)
{
 int ok = NO;
 if (dc->linswp[ii]){
    double fudge = dc->step[ii] / 10.;
    if (dc->step[ii] == 0.){
       ok = NO;
    }else{
       if (!dc->reverse){
	  *(dc->sweep[ii]) += dc->step[ii];
	  ok=inorder(dc->start[ii]-fudge,*(dc->sweep[ii]),dc->stop[ii]+fudge);
	  if (!ok  &&  dc->loop)
	     dc->reverse = YES;
       }
       if (dc->reverse){
	  *(dc->sweep[ii]) -= dc->step[ii];
	  ok=inorder(dc->start[ii]-fudge,*(dc->sweep[ii]),dc->stop[ii]+fudge);
       }
    }
 }else{
    double fudge = pow(dc->step[ii], .1);
    if (dc->step[ii] == 1.){
       ok = NO;
    }else{
       if (!dc->reverse){
	  *(dc->sweep[ii]) *= dc->step[ii];
	  ok=inorder(dc->start[ii]/fudge,*(dc->sweep[ii]),dc->stop[ii]*fudge);
	  if (!ok  &&  dc->loop)
	     dc->reverse = YES;       
       }
       if (dc->reverse){
	  *(dc->sweep[ii]) /= dc->step[ii];
	  ok=inorder(dc->start[ii]/fudge,*(dc->sweep[ii]),dc->stop[ii]*fudge);
       }
    }
 }
 expand_branch(dc->zap[ii]);
 dc->printnow = YES;
 stats.control[cSTEPCAUSE] = scUSER;
 return ok;
}
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
