function sprintf(fstring)
  { var pad = function(str,ch,len)
      { var ps='';
        for(var i=0; i<Math.abs(len); i++) ps+=ch;
        return len>0?str+ps:ps+str;
      }
    var processFlags = function(flags,width,rs,arg)
      { var pn = function(flags,arg,rs)
          { if(arg>=0)
              { if(flags.indexOf(' ')>=0) rs = ' ' + rs;
                else if(flags.indexOf('+')>=0) rs = '+' + rs;
              }
            else
                rs = '-' + rs;
            return rs;
          }
        var iWidth = parseInt(width,10);
        if(width.charAt(0) == '0')
          { var ec=0;
            if(flags.indexOf(' ')>=0 || flags.indexOf('+')>=0) ec++;
            if(rs.length<(iWidth-ec)) rs = pad(rs,'0',rs.length-(iWidth-ec));
            return pn(flags,arg,rs);
          }
        rs = pn(flags,arg,rs);
        if(rs.length<iWidth)
          { if(flags.indexOf('-')<0) rs = pad(rs,' ',rs.length-iWidth);
            else rs = pad(rs,' ',iWidth - rs.length);
          }    
        return rs;
      }
    var converters = new Array();
    converters['c'] = function(flags,width,precision,arg)
      { if(typeof(arg) == 'number') return String.fromCharCode(arg);
        if(typeof(arg) == 'string') return arg.charAt(0);
        return '';
      }
    converters['d'] = function(flags,width,precision,arg)
      { return converters['i'](flags,width,precision,arg); 
      }
    converters['u'] = function(flags,width,precision,arg)
      { return converters['i'](flags,width,precision,Math.abs(arg)); 
      }
    converters['i'] =  function(flags,width,precision,arg)
      { var iPrecision=parseInt(precision);
        var rs = ((Math.abs(arg)).toString().split('.'))[0];
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        return processFlags(flags,width,rs,arg); 
      }
    converters['E'] = function(flags,width,precision,arg) 
      { return (converters['e'](flags,width,precision,arg)).toUpperCase();
      }
    converters['e'] =  function(flags,width,precision,arg)
      { iPrecision = parseInt(precision);
        if(isNaN(iPrecision)) iPrecision = 6;
        rs = (Math.abs(arg)).toExponential(iPrecision);
        if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs.replace(/^(.*)(e.*)$/,'$1.$2');
        return processFlags(flags,width,rs,arg);        
      }
    converters['f'] = function(flags,width,precision,arg)
      { iPrecision = parseInt(precision);
        if(isNaN(iPrecision)) iPrecision = 6;
        rs = (Math.abs(arg)).toFixed(iPrecision);
        if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs + '.';
        return processFlags(flags,width,rs,arg);
      }
    converters['G'] = function(flags,width,precision,arg)
      { return (converters['g'](flags,width,precision,arg)).toUpperCase();
      }
    converters['g'] = function(flags,width,precision,arg)
      { iPrecision = parseInt(precision);
        absArg = Math.abs(arg);
        rse = absArg.toExponential();
        rsf = absArg.toFixed(6);
        if(!isNaN(iPrecision))
          { rsep = absArg.toExponential(iPrecision);
            rse = rsep.length < rse.length ? rsep : rse;
            rsfp = absArg.toFixed(iPrecision);
            rsf = rsfp.length < rsf.length ? rsfp : rsf;
          }
        if(rse.indexOf('.')<0 && flags.indexOf('#')>=0) rse = rse.replace(/^(.*)(e.*)$/,'$1.$2');
        if(rsf.indexOf('.')<0 && flags.indexOf('#')>=0) rsf = rsf + '.';
        rs = rse.length<rsf.length ? rse : rsf;
        return processFlags(flags,width,rs,arg);        
      }  
    converters['o'] = function(flags,width,precision,arg)
      { var iPrecision=parseInt(precision);
        var rs = Math.round(Math.abs(arg)).toString(8);
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        if(flags.indexOf('#')>=0) rs='0'+rs;
        return processFlags(flags,width,rs,arg); 
      }
    converters['X'] = function(flags,width,precision,arg)
      { return (converters['x'](flags,width,precision,arg)).toUpperCase();
      }
    converters['x'] = function(flags,width,precision,arg)
      { var iPrecision=parseInt(precision);
        arg = Math.abs(arg);
        var rs = Math.round(arg).toString(16);
        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
        if(flags.indexOf('#')>=0) rs='0x'+rs;
        return processFlags(flags,width,rs,arg); 
      }
    converters['s'] = function(flags,width,precision,arg)
      { var iPrecision=parseInt(precision);
        var rs = arg;
        if(rs.length > iPrecision) rs = rs.substring(0,iPrecision);
        return processFlags(flags,width,rs,0);
      }
    farr = fstring.split('%');
    retstr = farr[0];
    fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
    for(var i=1; i<farr.length; i++)
      { fps=fpRE.exec(farr[i]);
        if(!fps) continue;
        if(arguments[i]!=null) retstr+=converters[fps[4]](fps[1],fps[2],fps[3],arguments[i]);
        retstr += fps[5];
      }
    return retstr;
  }


function Log10(x){
	return Math.log(x) / Math.log(10);
}
function roundto(x,dp){
	return (Math.round(x*Math.pow(10,dp))/Math.pow(10,dp));
}
function sqr(x){
	return Math.pow(x,2);
}
function so_clearInnerHTML(obj) {
	var nObj;
	nObj = obj.cloneNode(false);
	obj.parentNode.insertBefore(nObj,obj);
	obj.parentNode.removeChild(obj);
}
/*
function replace_text(obj, txt) {
	so_clearInnerHTML(document.getElementById(obj));
	document.getElementById(obj).appendChild(document.createTextNode(txt));	
}
*/
/*
function replace_text(obj, txt) {
var t = document.createTextNode(txt);
var n1 = document.getElementById(obj);
var n2 = n1.cloneNode(false);
var p = n1.parentNode;
p.insertBefore(n2,n1);
n2.appendChild(t);	
p.removeChild(n1);
}
*/



function replace_text(obj, txt) {
if (document.all) {
  //isIE
  document.all[obj].innerHTML = txt;
} else {
  //isNotIE
  document.getElementById(obj).innerHTML = txt;
}
}


function speed( flg ) {
	var fs;
	var fhz;
	var fm;
	r = document.x.result;
	if (document.x.wlunit[0].checked) {
		mfact = 1.0;
		r.value = sprintf(" #     (hz)     (m)") + "\n";
		replace_text('txtsos', "speed of sound (m/s)" );
	}
	else {
		mfact = 3.408;
		r.value = sprintf(" #     (hz)    (ft)") + "\n";
		replace_text('txtsos', "speed of sound (ft/s)" );
	}
	fs = document.getElementById('sos');
	fhz = document.getElementById('hz');
	fm = document.getElementById('m');
	sos = Calculate_SoS();
	fs.value = Math.round(100*sos)/100;
//	fs.value = Math.round(100*sos*mfact)/100;
	if ( flg ) {
		v1 = sos / fhz.value;
		v2 = Math.round(100*fhz.value)/100;
		fm.value = Math.round(1000*v1/mfact)/1000;
	}
	else {
		v2 = Math.round(100*sos / fm.value*mfact)/100;
		v1 = fm.value * mfact;
		fhz.value = Math.round(100*v2)/100;
	}
	freq = v2;
	afstand = v1;
	for ( i = 0; i < 100; i++ ) {
		r.value += sprintf("%2d %8.2f %7.3f",i,freq,afstand/mfact) + "\n";
		afstand = v1 / (i+2);
		freq += v2;
		if ( freq > 22100 ) break;
	}
}

function Calculate_SoS() {
	var TT;
	var T;// temperature deg C
	var P;// pressure
	var Rh;// relative humidity
	var C;// speed
	var Xc, Xw;// Mole fraction of carbon dioxide and water vapour
	var H;// respectively molecular concentration of water vapour
	var C1;// Intermediate calculations
	var C2;
	var C3;
	var ENH;
	var PSV;
	var PSV1;
	var PSV2;
	var T_kel;// ambient temperature (Kelvin)
	var StrMsg; // alert text
	var Kelvin = 273.15; // For converting to Kelvin
	var e = 2.71828182845904523536;
	// Getvariables from form
	TT = Number(document.x.T.value);
	P = Number(document.x.P.value)*1000.0;
	Rh = Number(document.x.Rh.value);
	// Check that sensible numbers were entered
	if ((Rh > 100)|| (Rh<0)){
	StrMsg = "Relative humidity must be between 0 and 100%";
	document.x.Rh.focus=true;
	alert('Data out of range: ' + StrMsg);
	return false;
	}
	if (document.x.tempunit[0].checked) { // C
		T_kel = Kelvin + TT; // Measured ambient temp
		T = TT;
	}
	else { // F
		T_kel = (TT + 459.67) / 1.8;
		T = 100/(212-32) * (TT - 32 )
	}

	// Molecular concentration of water vapour calculated from Rh
	// using Giacomos method by Davis (1991) as implemented in DTU report 11b-1997
	ENH = 3.14*Math.pow(10,-8)*P + 1.00062 + sqr(T)*5.6*Math.pow(10,-7);
	// These commented lines correspond to values used in Cramer (Appendix)
	// PSV1 = sqr(T_kel)*1.2811805*Math.pow(10,-5)-1.9509874*Math.pow(10,-2)*T_kel ;
	// PSV2 = 34.04926034-6.3536311*Math.pow(10,3)/T_kel;
	PSV1 = sqr(T_kel)*1.2378847*Math.pow(10,-5)-1.9121316*Math.pow(10,-2)*T_kel;
	PSV2 = 33.93711047-6.3431645*Math.pow(10,3)/T_kel;
	PSV = Math.pow(e,PSV1)*Math.pow(e,PSV2);
	H = Rh*ENH*PSV/P;
	Xw = H/100.0;
	//Xc = 314.0*Math.pow(10,-6);
	Xc = 400.0*Math.pow(10,-6);
	// Speed calculated using the method
	// of Cramer from JASA vol 93 pg 2510
	C1 = 0.603055*T + 331.5024 - sqr(T)*5.28*Math.pow(10,-4) + (0.1495874*T + 51.471935 -sqr(T)*7.82*Math.pow(10,-4))*Xw;
	C2 = (-1.82*Math.pow(10,-7)+3.73*Math.pow(10,-8)*T-sqr(T)*2.93*Math.pow(10,-10))*P+(-85.20931-0.228525*T+sqr(T)*5.91*Math.pow(10,-5))*Xc;
	C3 = sqr(Xw)*2.835149 - sqr(P)*2.15*Math.pow(10,-13) + sqr(Xc)*29.179762 + 4.86*Math.pow(10,-4)*Xw*P*Xc;
	C = C1 + C2 - C3;
	// return C to the document
	return roundto(C,2);
}
