// Copyright Martin A. Shields, 1998.

function WarpCalc( w ) {
	if( isNaN( w )) { WarpError(); return; }
	if( w<0 || w>=10 ) { WarpError(); return; }
	document.warp.speed.value = WarpSpeed( w );
}

function SpeedCalc( v ) {
	// This will calculate a warp value for a specific speed
	if( isNaN( v )) { SpeedErr(); return; }
	if( v<0 ) { SpeedErr(); return; }
	document.warp.wf.value = FindWarp( v );
}

function FindWarp( v ) {
	with( Math ) {
		h = 0.0001;
		
		// First step is to make an educated guess:
		wmin = 0;
		wmax = 10;
		if( v > 1600 ) {
			w = 10 - pow( 304.329 / ( v - 1516), 1.4218 );
			if( w + h > 10 )
				h = (10 - w ) / 2;
			wmin = 9;
		} else
			w = pow( v, 0.3 );

		// Now impliment Newton's method, but record best...
		dv    = 1;
		for( cnt=1; cnt < 20 && dv > 0.00001; cnt++ ) {
			w0 = w;
			dv = ( WarpSpeed( w + h ) - WarpSpeed( w - h ) ) / 2 / h;
			w  = w - (WarpSpeed( w ) - v) / dv;
			if( w >= 10 ) {
				w = (wmin + wmax) / 2;
			}
			if( w + h >= 10 )
				h = (10 - w)/2;
			if( w - h < 0 )
				h = w/2;
			ws = WarpSpeed( w );
			if( ws < v )
				if( w > wmin )
					wmin = w;
			if( ws > v )
				if( w < wmax )
					wmax = w;
			dv = abs(ws - v);
		}
		
		// Sometimes Newton's method is not sufficient (esp. around v=20000),
		// so I use a BFI approach:
		if( dv > 0.0001 ) {
			for( cnt=1; cnt < 60; cnt++) {
				w  = (wmin + wmax) / 2;
				ws = WarpSpeed( w );
				if( ws < v && w > wmin )
					wmin = w;
				if( ws > v && w < wmax )
					wmax = w;
			}
		}
		return w;
	}
}

function WarpSpeed2( w ) {
	// Dominic Berry's equation with my variables inserted
	with( Math ) {
		a = 0.036528749373;
		n = 1.79522947028;
		c = 0;
		if( w > 9 ) {
			c = a * pow( -log(10 - w), n );
		}
		return round(pow(w,10/3 + c));
	}
}

function WarpSpeed( w ) {
	with( Math) {
		a = 0.20467 * exp(-0.0058*pow(log(10000*(10-w))/LN10,5));
		b = 1+(2*cos(10*PI*log(8/(10*(10-w)))/LN10)-1)/3*exp(-49.369*pow(log(8/(10*(10-w)))/LN10,4));
		c = 1+1.88269/PI*(PI/2-atan(pow(10,w)*log(2000*(10-w))/LN10));
		return round(pow(w,10/3*(1+(a*b*c))));
	}
}

function WarpError() {
	document.warp.wf.value = "";
	document.warp.speed.value = "";
	alert("You must enter a number between 0 and 10.");
	document.warp.wf.focus();
}

function SpeedErr() {
	document.warp.wf.value = "";
	document.warp.speed.value = "";
	alert("Speed must be a positive number.");
	document.warp.speed.focus();
}

