From: <Saved by Microsoft Internet Explorer 5>
Subject: Venn Diagrams and Probability
Date: Mon, 4 Nov 2002 12:05:18 +0900
MIME-Version: 1.0
Content-Type: multipart/related;
	boundary="----=_NextPart_000_0000_01C283FA.710A0560";
	type="text/html"
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2600.0000

This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C283FA.710A0560
Content-Type: text/html;
	charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable
Content-Location: http://stat-www.berkeley.edu/users/stark/Java/Venn.htm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>Venn Diagrams and Probability</TITLE>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Dwindows-1252">
<META content=3D"MSHTML 6.00.2713.1100" name=3DGENERATOR></HEAD>
<BODY>
<SCRIPT language=3DJavaScript1.2=20
src=3D"http://stat-www.berkeley.edu/users/stark/Java/irGrade.js">=0A=
</SCRIPT>

<H1 align=3Dcenter>Venn Diagrams and Probability </H1>
<P align=3Dcenter><APPLET height=3D340 archive=3DPbsGui.zip width=3D480 =
code=3DVenn.class><PARAM NAME=3D"height" VALUE=3D"340"><PARAM =
NAME=3D"archive" VALUE=3D"PbsGui.zip"><PARAM NAME=3D"width" =
VALUE=3D"480"><PARAM NAME=3D"code" VALUE=3D"Venn.class"><PARAM =
NAME=3D"codeBase" =
VALUE=3D"http://stat-www.berkeley.edu/users/stark/Java/">
   You need Java to see this.</APPLET> </P>
<P>Venn diagrams are a way of visualizing sets. This applet lets you =
highlight=20
the set A, the set B, the universal set S, the empty set {}, the =
complement of A=20
(Ac), the complement of B (Bc), the intersection of A and B (AB), the =
union of A=20
and B (A or B), the intersection of the complement of A with B (AcB), =
and the=20
intersection of A with the complement of B (ABc). One can think of the =
relative=20
area of a set to the area of S as a probability. The picture uses that =
analogy:=20
the numbers P(A) and P(B) are proportional to the area of A and the area =
of B,=20
respectively; P(AB) is the area of the intersection of A and B, and P(A =
or B) is=20
the area of the union of A and B. </P>
<P>You can drag the <A=20
href=3D"http://stat-www.berkeley.edu/users/stark/SticiGui/Text/gloss.htm#=
event">events</A>=20
A and B around, which changes the probability of their intersection and =
of their=20
union. When A and B do not overlap, they are said to be <A=20
href=3D"http://stat-www.berkeley.edu/users/stark/SticiGui/Text/gloss.htm#=
disjoint">disjoint=20
or mutually exclusive</A>. When the probability of the intersection of A =
and B=20
equals the product of the probability of A and the probability of B =
(when P(AB)=20
=3D P(A)=D7P(B)), A and B are <A=20
href=3D"http://stat-www.berkeley.edu/users/stark/SticiGui/Text/gloss.htm#=
independent">independent</A>.=20
Try to drag A or B to make P(AB) =3D P(A)=D7P(B); notice how hard it is =
to make the=20
overlap just right: independence is a very special relationship between =
events.=20
The scrollbars let you adjust the probability of A and the probability =
of B.=20
</P>
<SCRIPT=20
language=3DJavaScript1.2><!--=0A=
writeMiscFooter('../SticiGui');=0A=
// -->=0A=
</SCRIPT>
</BODY></HTML>

------=_NextPart_000_0000_01C283FA.710A0560
Content-Type: application/octet-stream
Content-Transfer-Encoding: quoted-printable
Content-Location: http://stat-www.berkeley.edu/users/stark/Java/irGrade.js

// script irGrade:  interactive, real-time grading; html formatting; =
statistical functions,=0A=
//                  linear algebra=0A=
// copyright 1997, 1998, 1999, 2000, 2001, 2002. P.B. Stark, =
stark@stat.berkeley.edu=0A=
// Version 1.0=0A=
// All rights reserved.=0A=
=0A=
// !!!!Beginning of the code!!!!=0A=
=0A=
var irGradeModTime =3D '2002/06/10/1110';=0A=
                                   // modification date and time=0A=
var today =3D (new Date()).toLocaleString();=0A=
var copyYr =3D '1997--2002. ';       // copyright years=0A=
var theChapters =3D =
[-1,0,1,2,3.1,3.2,3.3,4.1,4.2,4.3,5.1,5.2,5.3,6,7,8.1,8.2,9,=0A=
                   =
10,11,12,13,14.1,14.2,14.3,15,16.1,16.2,17.1,17.2,18,19.1,19.2,=0A=
                   20.1,20.2,20.3,21,22,23,24,25=0A=
                  ];               // list of the chapters=0A=
var cookieExpireDays =3D 10;         // days for the cookies to endure=0A=
var theChapter;                    // current chapter=0A=
var type =3D 'LA';                   // default question type is =
'literal answer'=0A=
var newStyleAnswer =3D true;         // flag for pop-up versus inline=0A=
var ansText =3D ' ';                 // to display correct answer=0A=
var pCtr =3D 1;                      // counter for problems=0A=
var qCtr =3D 1;                      // counter for questions=0A=
//var sCtr =3D 0;                      // counter for solved exercises=0A=
var fCtr =3D 0;                      // counter for footnotes=0A=
//var sEx =3D new Array();             // array for exercise numbers of =
solved exercises=0A=
//var sEnum =3D 0;                     // counter for displaying =
solutions=0A=
var footnotes =3D new Array();       // array of footnotes=0A=
var key =3D new Array();             // key for self-graded exercises=0A=
var boxList =3D new Array();         // list of images for self-graded =
exercises=0A=
var longKey =3D new Array();         // long answers for exercises=0A=
var solutionCode =3D new Array();    // javascript code to evaluate =
after writing solution=0A=
var setNum;                        // current problem set number=0A=
var isLab =3D false;                 // is this a problem set?=0A=
var pbsURL =3D 'http://www.stat.berkeley.edu/~stark';=0A=
                                   // P.B. Stark's URL=0A=
var pbsRef =3D '<a href=3D"' + pbsURL + '" target=3D"_top" ' +=0A=
    ' onmouseout=3D"window.status=3DdefaultStatus;return(true);" ' +=0A=
    ' onmouseover=3D"window.status=3D\'P.B. Stark\';return(true);">P.B. =
Stark</a>';=0A=
                                   // link to author=0A=
var fudgeFactor =3D 0.01;            // relative tolerance for imprecise =
numerical answers=0A=
var absFudge =3D 1.e-20;             // absolute tolerance for =
identically zero answers=0A=
var wrongHtm =3D '<p><center><font size=3D"+1" color=3D"red">Sorry, =
wrong answer.</font></center></p>';=0A=
                           // message for wrong answer=0A=
var rightHtm =3D '<p><center><font size=3D"+1" =
color=3D"green">Correct!</font></center></p>';=0A=
                           // message for right answer=0A=
var dsmsHtm =3D  '<p><center> <input type=3D"button" name=3D"dismiss" =
value=3D"Close" ' +=0A=
        ' onClick=3D"self.close()"></center></p>';=0A=
                           // to go on when answer is right=0A=
var startHtm =3D '<html> <head></head> <body><form>';=0A=
var endHtm =3D '</form></body> </html>';=0A=
var showAnsHtm =3D '<p><center> <input type=3D"button" ' +=0A=
        'name=3D"tryAgain" value=3D"Try again" ' +=0A=
        ' onClick=3D"self.close()"></center></p>' +=0A=
        '<p><center> <input type=3D"button" ' +=0A=
        'name=3D"showMe" value=3D"Show me the answer" ' +=0A=
        'onClick=3D"document.clear();document.write(htmStuff);" ' +=0A=
        ' </center></p>';       // to go on or show answer when answer =
is wrong=0A=
var inlinePrefix=3D"Q#:a#:";=0A=
var bigPi =3D "3141592653";=0A=
var rmin =3D 2.3e-308;            // for numerical analysis=0A=
var eps =3D 2.3e-16;              // ditto=0A=
var maxIterations =3D 100;        // default iteration limit for =
iterative algorithms=0A=
var continueLab;=0A=
var htmStuff;=0A=
var randSeed;                   // seed of random number generator=0A=
var CA =3D false;=0A=
var sectionContext;             // store chapter-specific initialization =
script=0A=
var qImgSrc =3D '../Graphics/answer_unknown.gif';=0A=
var rightImgSrc =3D '../Graphics/answer_good.gif';=0A=
var wrongImgSrc =3D '../Graphics/answer_bad.gif';=0A=
var alphabet =3D =
['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p',=0A=
        'q','r','s','t','u','v','w','x','y','z'=0A=
        ];=0A=
var ALPHABET =3D =
['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',=0A=
        'Q','R','S','T','U','V','W','X','Y','Z'=0A=
        ];=0A=
var Alphabet =3D ALPHABET;=0A=
var cardinals =3D =
['zero','one','two','three','four','five','six','seven','eight','nine','t=
en',=0A=
            =
'eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','=
eighteen',=0A=
            =
'nineteen','twenty','twenty-one','twenty-two','twenty-three','twenty-four=
',=0A=
            =
'twenty-five','twenty-six','twenty-seven','twenty-eight','twenty-nine','t=
hirty',=0A=
            =
'thirty-one','thirty-two','thirty-three','thirty-four','thirty-five','thi=
rty-six',=0A=
            =
'thirty-seven','thirty-eight','thirty-nine','fourty','fourty-one','fourty=
-two',=0A=
            =
'fourty-three','fourty-four','fourty-five','fourty-six','fourty-seven','f=
ourty-eight',=0A=
            =
'fourty-nine','fifty','fifty-one','fifty-two','fifty-three','fifty-four',=
'fifty-five',=0A=
            =
'fifty-six','fifty-seven','fifty-eight','fifty-nine','sixty','sixty-one',=
'sixty-two',=0A=
            =
'sixty-three','sixty-four','sixty-five','sixty-six','sixty-seven','sixty-=
eight',=0A=
            =
'sixty-nine','seventy','seventy-one','seventy-two','seventy-three','seven=
ty-four',=0A=
            =
'seventy-five','seventy-six','seventy-seven','seventy-eight','seventy-nin=
e',=0A=
            =
'eighty','eighty-one','eighty-two','eighty-three','eighty-four','eighty-f=
ive',=0A=
            =
'eighty-six','eighty-seven','eighty-eight','eighty-nine','ninety',=0A=
            =
'ninety-one','ninety-two','ninety-three','ninety-four','ninety-five',=0A=
            =
'ninety-six','ninety-seven','ninety-eight','ninety-nine','one hundred'=0A=
            ];=0A=
var Cardinals =3D =
['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','T=
en',=0A=
            =
'Eleven','Twelve','Thirteen','Fourteen','Fifteen','Sixteen','Seventeen','=
Eighteen',=0A=
            =
'Nineteen','Twenty','Twenty-one','Twenty-two','Twenty-three','Twenty-four=
',=0A=
            =
'Twenty-five','Twenty-six','Twenty-seven','Twenty-eight','Twenty-nine','T=
hirty',=0A=
            =
'Thirty-one','Thirty-two','Thirty-three','Thirty-four','Thirty-five','Thi=
rty-six',=0A=
            =
'Thirty-seven','Thirty-eight','Thirty-nine','Fourty','Fourty-one','Fourty=
-two',=0A=
            =
'Fourty-three','Fourty-four','Fourty-five','Fourty-six','Fourty-seven','F=
ourty-eight',=0A=
            =
'Fourty-nine','Fifty','Fifty-one','Fifty-two','Fifty-three','Fifty-four',=
'Fifty-five',=0A=
            =
'Fifty-six','Fifty-seven','Fifty-eight','Fifty-nine','Sixty','Sixty-one',=
'Sixty-two',=0A=
            =
'Sixty-three','Sixty-four','Sixty-five','Sixty-six','Sixty-seven','Sixty-=
eight',=0A=
            =
'Sixty-nine','Seventy','Seventy-one','Seventy-two','Seventy-three','Seven=
ty-four',=0A=
            =
'Seventy-five','Seventy-six','Seventy-seven','Seventy-eight','Seventy-nin=
e',=0A=
            =
'Eighty','Eighty-one','Eighty-two','Eighty-three','Eighty-four','Eighty-f=
ive',=0A=
            =
'Eighty-six','Eighty-seven','Eighty-eight','Eighty-nine','Ninety',=0A=
            =
'Ninety-one','Ninety-two','Ninety-three','Ninety-four','Ninety-five',=0A=
            =
'Ninety-six','Ninety-seven','Ninety-eight','Ninety-nine','One hundred'=0A=
            ];=0A=
var ordinals =3D =
['zeroth','first','second','third','fourth','fifth','sixth','seventh','ei=
ghth',=0A=
            =
'ninth','tenth','eleventh','twelfth','thirteenth','fourteenth','fifteenth=
',=0A=
            =
'sixteenth','seventeenth','eighteenth','ninteenth','twentieth','twenty-fi=
rst',=0A=
            =
'twenty-second','twenty-third','twenty-fourth','twenty-fifth','twenty-six=
th',=0A=
            =
'twenty-seventh','twenty-eighth','twenty-ninth','thirtieth','thirty-first=
',=0A=
            =
'thirty-second','thirty-third','thirty-fourth','thirty-fifth','thirty-six=
th',=0A=
            =
'thirty-seventh','thirty-eighth','thirty-ninth','fourtieth','fourty-first=
',=0A=
            =
'fourty-second','fourty-third','fourty-fourth','fourty-fifth','fourty-six=
th',=0A=
            =
'fourty-seventh','fourty-eighth','fourty-ninth','fiftieth','fifty-first',=0A=
            =
'fifty-second','fifty-third','fifty-fourth','fifty-fifth','fifty-sixth',=0A=
            =
'fifty-seventh','fifty-eighth','fifty-ninth','sixtieth','sixty-first',=0A=
            =
'sixty-second','sixty-third','sixty-fourth','sixty-fifth','sixty-sixth',=0A=
            =
'sixty-seventh','sixty-eighth','sixty-ninth','seventieth','seventy-first'=
,=0A=
            =
'seventy-second','seventy-third','seventy-fourth','seventy-fifth','sevent=
y-sixth',=0A=
            =
'seventy-seventh','seventy-eighth','seventy-ninth','eightieth','eighty-fi=
rst',=0A=
            =
'eighty-second','eighty-third','eighty-fourth','eighty-fifth',=0A=
            =
'eighty-sixth','eighty-seventh','eighty-eightth','eighty-ninth','ninetiet=
h',=0A=
            =
'ninety-first','ninety-second','ninety-third','ninety-fourth','ninety-fif=
th',=0A=
            =
'ninety-sixth','ninety-seventh','ninety-eighth','ninety-ninth','hundredth=
'=0A=
            ];=0A=
var iteratives =3D ['no times','once','twice','thrice'];=0A=
for (var i=3D4; i < cardinals.length; i++) {=0A=
    iteratives[i] =3D cardinals[i] + ' times';=0A=
}=0A=
var primes =3D [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, =
53];=0A=
var nPrimes =3D [0, 0, 1, 2, 2, 3, 3, 4, 4, 4,           // 0-9=0A=
               4, 5, 5, 6, 6, 6, 6, 7, 7, 8,           // 10-19=0A=
               8, 8, 8, 9, 9, 9, 9, 9, 9, 10,          // 20-29=0A=
               10, 11, 11, 11, 11, 11, 11, 12, 12, 12, // 30-39=0A=
               12, 13, 13, 14, 14, 14, 14, 15, 15, 15, // 40-49=0A=
               15, 15, 15, 16];                        // 50-53=0A=
var allTheChars =3D =
'~\`!1@2#3$4%5^6&7*8(9)0_-+=3DQqWwEeRrTtYyUuIiOoPp{[}]|\\AaSsDdFfGgHhJjKk=
Ll:;' +=0A=
                  '\"\'ZzXxCcVvBbNnMm<,>.?/';=0A=
var faces =3D =
['Ace','two','three','four','five','six','seven','eight','nine','ten','Ja=
ck',=0A=
         'Queen','King'];=0A=
var suits =3D ['spades','hearts','diamonds','clubs'];=0A=
var colors =3D ['red','orange','yellow','green','blue','indigo','violet',=0A=
              =
'black','white','gray','silver','gold','brown','aqua','teal',=0A=
              'fuschia','magenta','cyan','sage','turquoise','chartreuse',=0A=
              =
'mauve','periwinkle','umber','brick','marigold','seafoam','coral',=0A=
              'purple','grape','cherry','beige','copper','sienna','baby =
blue'=0A=
             ];=0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
//  FUNCTION LIBRARY=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
// =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D  STRING HANDLERS and =
HTML GENERATORS =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
function trimBlanks(s){=0A=
    if (s =3D=3D null || s.length =3D=3D 0 ) { return(s); }=0A=
    while (s.charAt(s.length-1) =3D=3D ' ' ) {      // trim trailing =
blanks=0A=
        s =3D s.substring(0, s.length-1);=0A=
    }=0A=
    while (s.charAt(0) =3D=3D ' ') {                // trim leading =
blanks=0A=
        s =3D s.substring(1, s.length);=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function allBlanks(s) {=0A=
    if (s =3D=3D null || trimBlanks(s).length =3D=3D 0) {=0A=
        return(true);=0A=
    } else {=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function removeAllBlanks(s){=0A=
    if (s =3D=3D null || s.length =3D=3D 0 ) {=0A=
        return(s);=0A=
    }=0A=
    while (s.indexOf(' ') > -1 ) {=0A=
        s =3D s.substring(0, s.indexOf(' ')) + s.substring(s.indexOf(' =
')+1, s.length);=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function makeTopLevel(nameString,features) {=0A=
   // ensures the window is a top level window with name nameString=0A=
    if (window !=3D top) {=0A=
        window.open(window.location,nameString,features);=0A=
        window.close();=0A=
        parent.close();=0A=
    } else {=0A=
        window.name=3DnameString;=0A=
    }=0A=
    return(true);=0A=
}=0A=
=0A=
function makeTopLevel(nameString){=0A=
    if (window !=3D top) {=0A=
        window.open(window.location,nameString,=0A=
            'toolbar=3Dyes,location=3Dyes,status=3Dyes');=0A=
        window.close();=0A=
        parent.close();=0A=
    } else window.name=3DnameString;=0A=
    return(true);=0A=
}=0A=
=0A=
function makeTopLevel(){=0A=
    if (window !=3D top) {=0A=
        window.open(window.location,'',=0A=
            'toolbar=3Dyes,location=3Dyes,status=3Dyes');=0A=
        window.close();=0A=
        parent.close();=0A=
    }=0A=
    return(true);=0A=
}=0A=
=0A=
function sticiRef() {=0A=
  // pops up a  window with the pronunciation of  SticiGui=0A=
    sticiWin =3D  window.open('','sticiWin',=0A=
                =
'toolbar=3Dno,location=3Dno,directories=3Dno,status=3Dno,scrollbars=3Dyes=
,'+=0A=
                =
'resizable=3Dyes,width=3D200,height=3D30,top=3D5,left=3D5');=0A=
    sticiWin.document.write('<html><head><title>How do you say =
that?</title>' +=0A=
            '</head><body><script language=3D"JavaScript">' +=0A=
            'setTimeout("window.close()",3000)' +=0A=
            '</script><h3 align=3D\"center\">Pronounced</h3>' +=0A=
            '<h3 align=3D\"center\">\"Sticky-Gooey\"</h3>' +=0A=
            '</body></html>');=0A=
    sticiWin.document.close();=0A=
    sticiWin.focus();=0A=
    return(true);=0A=
}=0A=
=0A=
function glossRef(lnk) {=0A=
// opens a glossary window, if not already open, and displays the =
glossary entry=0A=
// referred to in the link.=0A=
    window.open(lnk, target=3D"glossWin");=0A=
    return(true);=0A=
}=0A=
=0A=
function trimToLowerCase(s) {=0A=
// trim trailing blanks, convert to lower case=0A=
    if (s =3D=3D null || s.length =3D=3D 0 ) {=0A=
        return(s);=0A=
    }=0A=
    return(trimBlanks(s.toLowerCase()));=0A=
}=0A=
=0A=
function allLetters(s){=0A=
// return true if all characters in string s are letters (or trailing =
blanks)=0A=
    var trimS =3D trimToLowerCase(s);=0A=
    var alpha=3D' -abcdefghijklmnopqrstuvwxyz';=0A=
    var truth =3D true;=0A=
    for (var i =3D 0; i < trimS.length; i++) {=0A=
        if(alpha.indexOf(trimS.charAt(i)) < 0) {=0A=
            truth =3D false;=0A=
        }=0A=
    }=0A=
    return(truth);=0A=
}=0A=
=0A=
function removeCommas(s) { // removes commas from a putative number=0A=
    return(removeString(',',s));=0A=
}=0A=
=0A=
function removeString(str,s) { // removes instances of the string str =
from s.=0A=
                               // kluge to avoid regular expressions=0A=
    var sOut =3D s;=0A=
    var s1;=0A=
    var strLen =3D str.length;=0A=
    var inx =3D s.indexOf(str);=0A=
    while (inx > -1) {=0A=
        s1 =3D s.substring(0,inx);=0A=
        if (inx < (s.length - strLen) ) {=0A=
            s1 +=3D s.substring(inx+strLen, s.length);=0A=
        }=0A=
        s =3D s1;=0A=
        inx =3D s.indexOf(str);=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function removeStrings(strArr,s) {=0A=
    for (var j=3D0; j < strArr.length; j++) {=0A=
        s =3D removeString(strArr[j], s);=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function parsePercent(s) {=0A=
// parse a number that contains a % sign to turn it into a decimal =
fraction=0A=
    var value;=0A=
    if (s.indexOf('%') =3D=3D -1) {=0A=
        value =3D parseFloat(trimBlanks(removeCommas(s)))=0A=
    } else {=0A=
        while (s.indexOf('%') !=3D -1) {=0A=
            s =3D s.substring(0,s.indexOf('%')) +=0A=
                s.substring(s.indexOf('%')+1,s.length)=0A=
        }=0A=
        value =3D parseFloat(trimBlanks(removeCommas(s)))/100;=0A=
    }=0A=
    return(value);=0A=
}=0A=
=0A=
function evalNum(s) { // try to evaluate a string as a numeric value=0A=
    var value;=0A=
    var dmy =3D s + ' ';=0A=
    dmy =3D dmy.replace(/\%/g,'\/100');=0A=
    dmy =3D dmy.replace(/,/g,'');=0A=
    if ( typeof(s) =3D=3D 'undefined' || s =3D=3D null || !s.match(/[^ =
]/) ) {=0A=
        value =3D 'NaN';=0A=
    } else if ( dmy.match(/[^1234567890+*\/.ed() -]/i) ) {=0A=
        value =3D 'NaN';=0A=
    } else if ( !dmy.match(/[1234567890]/) ) {=0A=
        value =3D 'NaN';=0A=
    } else {=0A=
        eval('value =3D ' + dmy + ';');=0A=
    }=0A=
    return(value);=0A=
}=0A=
=0A=
function parseMultiple(option) {=0A=
  // pre-processes multiple selections so that checkAnswer can be used =
to grade them=0A=
    var response =3D '';=0A=
    for (var i=3D0; i < option.length; i++) {=0A=
        if (option[i].selected) {=0A=
            response +=3D trimToLowerCase(option[i].value) + ',' ;=0A=
        }=0A=
    }=0A=
    if (response.charAt(response.length - 1) =3D=3D ',') {  // trim =
trailing comma=0A=
        response =3D response.substring(0, response.length - 1);=0A=
    }=0A=
    return(response);=0A=
}=0A=
=0A=
function getFormElementIndex(q) {=0A=
 // finds the form element named q and returns its index.=0A=
    for (var inx =3D0; inx < document.forms[0].elements.length; inx++) {=0A=
        if (document.forms[0].elements[inx].name =3D=3D q)=0A=
        return(inx);=0A=
    }=0A=
    alert('Error #1 in irGrade.getFormElementIndex(): Form element ' + q =
+ ' is missing!');=0A=
    return('document.forms[0].length');=0A=
}=0A=
=0A=
function findNum(s) {=0A=
// if s is an integer or its string representation, returns s.=0A=
// if not, tries to remove characters to=0A=
// leave an int, and returns that int.=0A=
    var i =3D parseInt(s);=0A=
    if ( !isNaN(i)) {=0A=
        return(i);=0A=
    } else {=0A=
        var q =3D '';=0A=
        for (var j=3D0; j < s.length; j++) {=0A=
            var dum =3D q;=0A=
            if (!isNaN(parseInt(dum + s.charAt(j)))) {=0A=
                q +=3D s.charAt(j);=0A=
            }=0A=
        }=0A=
        return(q);=0A=
    }=0A=
}=0A=
=0A=
function vFindNum(s) { // finds numbers in a string array=0A=
    var a =3D new Array(s.length);=0A=
    for (var i=3D0; i < s.length; i++) { a[i] =3D findNum(s[i]);}=0A=
    return(a);=0A=
}=0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 COOKIE MANIPULATION =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=0A=
=0A=
function expireTimeString(ed) {=0A=
    var now =3D new Date();=0A=
    var expire =3D new Date();=0A=
    var cookDays;=0A=
    if (typeof(ed) =3D=3D 'undefined' || ed =3D=3D null) {=0A=
        cookDays =3D cookieExpireDays;=0A=
    } else {=0A=
        cookDays =3D ed;=0A=
    }=0A=
    expire.setTime(now.getTime() + cookDays*60*60*1000*24);=0A=
    return(expire.toGMTString());=0A=
}=0A=
=0A=
function getCookieVal(cook,key){ // gets the value of key within the =
cookie cook=0A=
    var searchStr =3D cook + '&';=0A=
    var val =3D null;=0A=
    var pat =3D key + '=3D';=0A=
    var inx =3D searchStr.indexOf(pat);=0A=
    if (inx > -1){=0A=
        searchStr =3D searchStr.substring(inx + pat.length, =
searchStr.length);=0A=
        val =3D unescape(searchStr.substring(0, searchStr.indexOf('&')));=0A=
    }=0A=
    return(val);=0A=
}=0A=
=0A=
function getCookieArray(cook,stem,len) { // gets an array from the cookie=0A=
    var ansArr =3D new Array(len);=0A=
    for (var i=3D0; i < len; i++) {=0A=
        ansArr[i] =3D getCookieVal(cook, stem + i.toString());=0A=
    }=0A=
    return(ansArr);=0A=
}=0A=
=0A=
function setCookieArray(arr,stem) { // make a cookie-like string from =
the array arr=0A=
    var ansStr =3D '';=0A=
    for (var i=3D0; i < arr.length; i++) {=0A=
        ansStr +=3D stem + i.toString() + '=3D' + arr[i] + '&';=0A=
    }=0A=
    if (ansStr.substr(ansStr.length-1,1) =3D=3D '&') {=0A=
        ansStr =3D ansStr.substring(0, ansStr.length - 1);=0A=
    }=0A=
    return(ansStr);=0A=
}=0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 PROBLEM AND GRADING SUBROUTINES =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
function numToMultiple(opt,ans) { // finds the multiple choice closest =
to ans=0A=
    var dif =3D Math.abs(parsePercent(opt[0]) - ans);=0A=
    var aVal =3D 'a';=0A=
    for (var i=3D1; i < opt.length; i++) {=0A=
        var d2 =3D Math.abs(parsePercent(opt[i]) - ans);=0A=
        if (d2 < dif) {=0A=
            dif =3D d2;=0A=
            aVal =3D alphabet[i];=0A=
        }=0A=
    }=0A=
    return(aVal);=0A=
}=0A=
=0A=
function hiddenInput(string, val){  // hidden input with name=3D"string" =
and value=3D"val"=0A=
    var s =3D "<input type=3D\"hidden\" name=3D\"" + string + "\" =
value=3D\"" + val + "\">";=0A=
    return(s);=0A=
}=0A=
=0A=
function textExercise(size,q,ca,checkFun) {=0A=
  // text input area of "size" size, name q, and appropriate onChange()=0A=
    var s =3D "<input type=3D\"text\" size=3D\"" + size + "\" name=3D\"" =
+ q + "\" ";=0A=
    var cf =3D true;=0A=
    if (typeof(checkFun) =3D=3D 'undefined' || checkFun =3D=3D null) {=0A=
        cf =3D false;=0A=
    }=0A=
    if (ca =3D=3D null || ca ) {=0A=
        if (!cf) {=0A=
            s +=3D "onChange=3D\"checkAnswer(name,value);\"";=0A=
        } else {=0A=
            s +=3D "onChange=3D\"checkAnswer(name,checkFun(value));\"";=0A=
        }=0A=
    } else if (cf) {=0A=
            s +=3D "onChange =3D \"set???  "; // FIX ME! Placeholder for =
functional grading=0A=
    }=0A=
    s +=3D " >";=0A=
    return(s);=0A=
}=0A=
=0A=
function textProblem(size,q) {  // makes text input area of "size" size, =
name "q"=0A=
    var s =3D "<input type=3D\"text\" size=3D\"" + size + "\" name=3D\"" =
+ q + "\">";=0A=
    return(s);=0A=
}=0A=
=0A=
function startExercise(q) {  // writes html to start an exercise, =
numbered q=0A=
    var s;=0A=
    if (HI) {=0A=
        s =3D "<strong>Problem " + q.toString() + ".</strong>";=0A=
    } else {=0A=
        s =3D "<strong>Exercise " + q.toString() + ".</strong>";=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function startProblem(q) {  // writes html to start a problem, numbered q=0A=
    var s;=0A=
    if (HI) {=0A=
        s =3D "<strong>Problem " + q.toString() + ".</strong>";=0A=
    } else {=0A=
        s =3D "<strong>Exercise " + q.toString() + ".</strong>";=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function startSolution(q) {  // html to start a solution, numbered q=0A=
    var s;=0A=
    if (HI) {=0A=
        s =3D "<strong>Solution to Problem " + q.toString() + =
".</strong>";=0A=
    } else {=0A=
        s =3D "<strong>Solution to Exercise " + q.toString() + =
".</strong>";=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function writeSelectExercise(mult, q, opt, ans) {=0A=
    document.writeln(selectExerciseString(mult, q, opt, ans));=0A=
    return(true);=0A=
}=0A=
=0A=
function selectExerciseString(mult, q, opt, ans) {=0A=
    var name =3D 'Q' + q.toString();=0A=
    var s =3D selectExercise(mult, name, opt, CA);=0A=
    if (CA) {=0A=
        if (mult) {=0A=
            s +=3D '<input type=3D"button" name=3D"B' + q +=0A=
                '" value=3D"Check Answer" onclick=3D"checkAnswer(\'' + =
name +=0A=
                '\',parseMultiple(' + name +'.options))">';=0A=
        }=0A=
        if (newStyleAnswer !=3D null && newStyleAnswer) {=0A=
            boxList[q - 1] =3D document.images.length;=0A=
            s +=3D '<a href=3D"javascript:void(0)" ' +=0A=
                ' onClick=3D"giveAnswer(\'Q' + q + '\');">' +=0A=
                ' <img src=3D"' + qImgSrc + '" ' +=0A=
                ' border=3D"1" align=3D"top"></a>';=0A=
        }=0A=
    }=0A=
    key[q - 1] =3D ans;=0A=
    return(s);=0A=
}=0A=
=0A=
function writeTextExercise(size, q, ans) {  // does all the printing for =
a textfield exercise=0A=
    document.writeln(textExercise(size, 'Q' + q, CA));=0A=
    var cf =3D false;=0A=
    if (typeof(ans) =3D=3D 'function') { // TO DO: allow functional =
checks of answers.=0A=
        cf =3D true;=0A=
    }=0A=
    if (CA) {=0A=
        if (newStyleAnswer !=3D null && newStyleAnswer) {=0A=
            boxList[q - 1] =3D document.images.length;=0A=
            document.writeln('<a href=3D"javascript:void(0)" ' +=0A=
                ' onMouseOver=3D"status=3D\'click to see the =
answer\';return(true)" ' +=0A=
                ' onMouseOut=3D"status=3DdefaultStatus;return(true);" ' +=0A=
                ' onClick=3D"giveAnswer(\'Q' + q + '\');">' +=0A=
                ' <img src=3D"' + qImgSrc + '" ' +=0A=
                ' border=3D"1" align=3D"top" alt=3D"click to see the =
answer"></a>');=0A=
        }=0A=
    }=0A=
    key[q - 1] =3D ans;=0A=
    return(true);=0A=
}=0A=
=0A=
function writeRadioExercise(q, opt, ans) {  // write a radio exercise=0A=
    document.writeln(radioExercise('Q'+q, opt, CA));=0A=
    if (CA) {=0A=
        if  (newStyleAnswer !=3D null && newStyleAnswer) {=0A=
            boxList[q - 1] =3D document.images.length;=0A=
            document.writeln('<a href=3D"javascript:void(0)" ' +=0A=
                ' onClick=3D"giveAnswer(\'Q' + q + '\');">' +=0A=
                ' <img src=3D"' + qImgSrc + '" ' +=0A=
                ' border=3D"1" align=3D"top"></a>');=0A=
        }=0A=
    }=0A=
    key[q-1] =3D ans;=0A=
    return(true);=0A=
}=0A=
=0A=
function radioExercise(q, opt, ca){  // makes a collection of radio =
inputs.=0A=
    var s =3D "";=0A=
    var oplen =3D opt.length;=0A=
    for (var i =3D 0; i < oplen; i++) {=0A=
        s  +=3D '<input type=3D"radio" name=3D"' + q + '" value=3D"' + =
alphabet[i] + '" ';=0A=
        if (ca =3D=3D null || ca) {=0A=
            s +=3D 'onClick=3D"checkAnswer(name,value);"';=0A=
        }=0A=
        s +=3D '>\n' + alphabet[i] + ') ' + opt[i] + '<br>\n';=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function selectExercise(mult, q, opt, ca) {=0A=
   // makes a select with multiple=3Dmult, name q.=0A=
   // if mult, makes the size large enough to show all options.=0A=
   // otherwise size=3D1;  opt is a 1 by array.=0A=
    var s;=0A=
    var size;=0A=
    var oplen =3D opt.length;=0A=
    if (mult) { // leave room for all the answers to be visible.=0A=
        size=3D oplen+1;=0A=
    } else {=0A=
        size =3D 1;=0A=
    }=0A=
    var s =3D '<select name=3D"' + q + '" size=3D"' + size + '" ';=0A=
    if (mult) {=0A=
        s +=3D 'multiple=3D"' + mult + '" ';=0A=
    }=0A=
    if ((ca =3D=3D null || ca) && !mult) {=0A=
        s +=3D 'onChange =
=3D"checkAnswer(name,options[selectedIndex].value);"';=0A=
    }=0A=
    s +=3D '>\n <option>?</option>\n';=0A=
    if (oplen <=3D 26) {=0A=
        for (var i=3D0; i < oplen; i++) {=0A=
            s +=3D '<option value=3D"' + alphabet[i] + '">' + =
ALPHABET[i] +=0A=
                ': ' + opt[i] + '</option>\n';=0A=
        }=0A=
    } else {=0A=
        for (var i=3D0; i < oplen; i++) {=0A=
            s +=3D '<option value=3D"' + (i+1).toString() + '">' +=0A=
                (i+1).toString() + ': ' + opt[i] + '</option>\n';=0A=
        }=0A=
    }=0A=
    s +=3D '</select>';=0A=
    return(s);=0A=
}=0A=
=0A=
function scoreProblem(truth,response){=0A=
    var answer =3D parseKey(truth);=0A=
    response =3D trimToLowerCase(response);=0A=
    var rsp;=0A=
    var correctness;=0A=
    if (response =3D=3D null) {=0A=
        correctness =3D false;=0A=
    } else if (type =3D=3D 'WC') {=0A=
        rsp =3D trimBlanks(response);=0A=
        if (rsp.length > 0) {correctness =3D true};=0A=
    } else if (type =3D=3D 'LA') {=0A=
        // try to parse as number; if fail, take literal.=0A=
        rsp =3D evalNum(response);=0A=
        if (!isNaN(rsp)) {=0A=
            response =3D rsp;=0A=
//        if (response.indexOf('%') !=3D -1) {=0A=
//            rsp =3D parsePercent(response);=0A=
//            if (!isNaN(rsp)) {=0A=
//                response =3D rsp;=0A=
//            }=0A=
//        } else if =
(!isNaN(parseFloat(trimBlanks(removeCommas(response))))) {=0A=
//            response =3D =
parseFloat(trimBlanks(removeCommas(response)));=0A=
        }=0A=
        if (answer.toString() =3D=3D response.toString()) {=0A=
            correctness =3D true;=0A=
        } else {=0A=
            correctness =3D false;=0A=
        }=0A=
    } else if (type =3D=3D 'RG') {=0A=
        var r =3D evalNum(response);=0A=
        if ((answer[0] <=3D r) && (r <=3D answer[1])) {=0A=
            correctness =3D true;=0A=
        } else {correctness =3D false;}=0A=
    } else if (type =3D=3D 'MA') {=0A=
        correctness =3D false;=0A=
        for (var i=3D0; i < answer.length; i++) {=0A=
            if (response =3D=3D answer[i]) {=0A=
                correctness =3D true;=0A=
            }=0A=
        }=0A=
    } else if (type =3D=3D 'MR') {=0A=
        correctness =3D false;=0A=
        resArray =3D response.split(',');=0A=
        resArray.sort()=0A=
        if (resArray.length =3D=3D answer.length) {=0A=
            correctness =3D true;=0A=
            for (var i=3D0; i < answer.length; i++ ) {=0A=
                if (answer[i] !=3D trimToLowerCase(resArray[i])) {=0A=
                    correctness =3D false;=0A=
                }=0A=
            }=0A=
        }=0A=
    }=0A=
    return(correctness);=0A=
}=0A=
=0A=
function parseKey(s) {=0A=
// parses the answer keys for interactive grading.  See header.=0A=
    s =3D trimBlanks(s.toLowerCase()) // use only lower-case letters=0A=
    var answer;=0A=
    if (s.indexOf(':') !=3D -1) {          // solution is a range=0A=
        answer =3D s.split(':')=0A=
        if (answer.length !=3D 2) { alert('Error #1 in =
irGrade.parseKey(): bad range syntax!') }=0A=
        type =3D 'RG'             // answer is of type range (RG)=0A=
        for (var i=3D0; i < answer.length; i++) {=0A=
            answer[i] =3D parsePercent(answer[i]);=0A=
            if (isNaN(answer[i])){=0A=
                alert('Error #2 in irGrade.parseKey(): unparsable number =
in range!');=0A=
            }=0A=
        }=0A=
        ansText =3D answer[0] + ' to ' + answer[1];=0A=
    } else if (s.indexOf('&') !=3D -1 ){ // multiple required answers; =
assume all=0A=
                                       // are letters=0A=
        answer =3D s.split('&');=0A=
        type =3D 'MR'                    // answer is of type multiple =
required (MR)=0A=
        for (var i=3D0; i < answer.length; i++ ) {=0A=
            answer[i] =3D trimBlanks(answer[i].toLowerCase());=0A=
            answer.sort();=0A=
        }=0A=
        ansText =3D answer[0];=0A=
        for (var i=3D1; i < answer.length; i++) {=0A=
            ansText +=3D ' and ' + answer[i];=0A=
        }=0A=
    } else if (s.indexOf('|') !=3D -1 ){ // multiple answers accepted; =
assume all=0A=
                                       // are letters=0A=
        answer =3D s.split('|');=0A=
        type =3D 'MA';                   // answer is of type multiple =
accepted (MA)=0A=
        for (var i=3D0; i < answer.length; i++ ) {=0A=
            answer[i] =3D trimBlanks(answer[i].toLowerCase());=0A=
        }=0A=
        ansText =3D answer[0];=0A=
        for (var i=3D1; i < answer.length; i++) {=0A=
            ansText +=3D ' or ' + answer[i];=0A=
        }=0A=
    } else if (s =3D=3D '*') {=0A=
        type =3D 'WC';                   // wildcard=0A=
        answer =3D '*';=0A=
        ansText =3D 'any non-blank answer';=0A=
    } else {                           // answer is literal=0A=
        type =3D 'LA'                    // literal answer (LA)=0A=
        answer =3D parsePercent(s);=0A=
        if (isNaN(answer)) {=0A=
            answer =3D trimBlanks(s.toLowerCase());=0A=
        }=0A=
        ansText =3D answer;=0A=
    }=0A=
    return(answer);=0A=
}=0A=
=0A=
function setCourse(inx) {=0A=
    setCourseSpecs(inx);=0A=
    document.applets[0].getSidFile(courses[inx][1] + sFileBase);=0A=
    return(document.applets[0].setBox(courses[inx][1] + dFileBase));=0A=
}=0A=
=0A=
function setCourseSpecs(inx) {=0A=
    course =3D courses[inx][1];=0A=
    courseName =3D courses[inx][2];=0A=
    teacher =3D courses[inx][3];=0A=
    teacherName =3D courses[inx][4];=0A=
    gPath =3D courses[inx][5];=0A=
    dFile =3D cRoot + course + dFileBase;=0A=
    var sFile =3D cRoot + course + sFileBase;=0A=
}=0A=
=0A=
function setDFile(inx) {=0A=
    setCourseSpecs(inx);=0A=
    document.forms[0].elements["dFile"].value =3D dFile;=0A=
    document.forms[0].elements["class"].value =3D courses[inx][1];=0A=
    return(true);=0A=
}=0A=
=0A=
function writeCourseOptions(fun) {=0A=
    document.writeln('<font color=3D"green">Course:</font><select =
name=3D"course" ' +=0A=
                     'onchange=3D"' + fun + =
'(options[selectedIndex].value);">');=0A=
    for (var i=3D0; i < courses.length; i++ ) {=0A=
        document.writeln('<option value=3D"' + =
(courses[i][0]).toString() + '">' +=0A=
            (courses[i][2]).toString() + '</option>');=0A=
    }=0A=
    document.writeln('</select>');=0A=
    return(true);=0A=
}=0A=
=0A=
function spawnGradePage(theForm) {=0A=
    if (validateLablet(theForm)) {=0A=
        var scorQStr =3D scoreBase + "class=3D" + course + "&gpath=3D" + =
gPath +=0A=
                        "&teacher=3D" + teacher;=0A=
        var queryURL =3D queryBase + "class=3D" + course + "&gpath=3D" + =
gPath +=0A=
                        "&teacher=3D" + teacher + "&sid=3D" + =
theForm.sid.value +=0A=
                        "&passwd=3D" + escape(theForm.sid.value) + =
"&dFile=3D" + dFile +=0A=
                        "&querylist=3D" + queryList;=0A=
        var histURL  =3D '../Grades/scoreHist.htm';=0A=
        gradePage =3D =
open('',"gradePage",'toolbar=3Dyes,location=3Dno,directories=3Dno,status=3D=
yes,'+=0A=
            'scrollbars=3Dyes,resizable=3Dyes');=0A=
        gradePage.document.open();=0A=
        gradePage.scorQStr =3D scorQStr;=0A=
        gradePage.teacherName =3D teacherName;=0A=
        gradePage.courseName =3D courseName;=0A=
        gradePage.semester =3D semester;=0A=
        gradePage.document.writeln("<html><head><title>SticiGui Grade =
Query</title></head>");=0A=
        gradePage.document.writeln("<frameset rows=3D\"*,300\">");=0A=
        gradePage.document.writeln("<frame name=3D\"queryWin\" src=3D\"" =
+ queryURL + "\"" +=0A=
            " frameborder=3D\"1\" framespacing=3D\"0\" border=3D\"1\">");=0A=
        gradePage.document.writeln("<frame name=3D\"histWin\" src=3D\"" =
+ histURL + "\"" +=0A=
            " frameborder=3D\"1\" framespacing=3D\"0\" border=3D\"1\">");=0A=
        gradePage.document.writeln("</frameset></html>");=0A=
        gradePage.document.close();=0A=
        return(true);=0A=
    } else {=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function spawnProblem(theForm,i) {=0A=
    if (validateLablet(theForm)) {=0A=
        var ck =3D document.cookie;=0A=
        var fname =3D formStemName + i.toString();=0A=
        var assigned =3D document.applets[0].isAssigned(fname);=0A=
        if (!assigned) {=0A=
                    alert('This problem set is not yet assigned.\n' +=0A=
                            'Try again later.');=0A=
                    return(false);=0A=
        }=0A=
        var sstr =3D  crypt("sid" + theForm.sid.value, =
theForm.sid.value) + '=3D';=0A=
        if (ck.indexOf(sstr) < 0){=0A=
            var rs =3D (theForm.sid.value).toString();=0A=
            if (rs.length < 10){ =0A=
                 rs +=3D rs;=0A=
            }=0A=
            randSeed =3D parseInt(rs.substr(0,Math.min(10,rs.length)));=0A=
            setSubmitCookie("sid", theForm, true);=0A=
            ck =3D document.cookie;=0A=
            if (ck.indexOf(sstr) < 0){=0A=
                alert('Error #1 in irGrade.spawnProblem()!\n' +=0A=
                      'Make sure your browser is configured to accept =
cookies.\n' +=0A=
                      'Clear existing cookies and try again.');=0A=
                return(false);=0A=
            }=0A=
        }=0A=
        var ss =3D ck.substring(ck.indexOf(sstr) + sstr.length, =
ck.length);=0A=
        if (ss.indexOf(';') > -1) {ss =3D =
ss.substring(0,ss.indexOf(';'))};=0A=
        var cl =3D crypt(ss, theForm.sid.value);=0A=
        var instr =3D '../Problems/set' + i.toString() + 'i.htm';=0A=
        var appl  =3D '../Problems/set' + i.toString() + 'j.htm';=0A=
        lablet =3D =
open('',"lablet",'toolbar=3Dno,location=3Dno,directories=3Dno,status=3Dno=
,'+=0A=
            'scrollbars=3Dyes,resizable=3Dyes');=0A=
        lablet.document.open();=0A=
        lablet.continueLab =3D cl;=0A=
        var reveal =3D document.applets[0].revealKey(fname);=0A=
        var allowSubmit =3D document.applets[0].allowSubmit(fname);=0A=
        lablet.reveal =3D reveal;=0A=
        lablet.allowSubmit =3D allowSubmit;=0A=
        lablet.dFile =3D dFile;=0A=
        lablet.course =3D course;=0A=
        lablet.teacher =3D teacher;=0A=
        lablet.document.writeln("<html><head><title>SticiGui Problem Set =
" + i=0A=
                +"</title></head>");=0A=
        lablet.document.writeln("<frameset rows=3D\"*,300\">");=0A=
        lablet.document.writeln("<frame name=3D\"instrWin\" src=3D\"" + =
instr + "\"" +=0A=
            " frameborder=3D\"1\" framespacing=3D\"0\" border=3D\"1\">");=0A=
        lablet.document.writeln("<frame name=3D\"appletWin\" src=3D\"" + =
appl + "\"" +=0A=
            " frameborder=3D\"1\" framespacing=3D\"0\" border=3D\"1\">");=0A=
        lablet.document.writeln("</frameset></html>");=0A=
        lablet.document.close();=0A=
        return(true);=0A=
    } else {=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function checkAnswer(number, response) {=0A=
  // check response against key[number-1].  If number is not an integer,=0A=
  // calls findNum(number) to remove characters to try to leave an =
integer.=0A=
    var theQuestion =3D findNum(number);=0A=
    var truth =3D scoreProblem(key[theQuestion-1],response);=0A=
    if (truth) {=0A=
        document.images[boxList[theQuestion-1]].src =3D rightImgSrc;=0A=
    } else {=0A=
        document.images[boxList[theQuestion-1]].src =3D wrongImgSrc;=0A=
    }=0A=
    return(truth);=0A=
}=0A=
=0A=
function isAnswered(qVal) { // checks whether the student answered a =
question=0A=
    var n =3D findNum(qVal) - 1;=0A=
    var iA =3D false;=0A=
    var inx;=0A=
    var el =3D document.forms[0].elements[qVal];=0A=
    var qT =3D el.type;=0A=
    if (qT =3D=3D 'select-one') {=0A=
        inx =3D el.selectedIndex;=0A=
        if (inx > 0) {=0A=
            iA =3D true;=0A=
        }=0A=
    } else if (qT =3D=3D 'select-multiple') {=0A=
        resp =3D parseMultiple(el.options);=0A=
        if (resp !=3D null && resp !=3D '' && resp !=3D '?') {=0A=
            iA =3D true;=0A=
        }=0A=
    } else if (qT =3D=3D 'text') {=0A=
        resp =3D el.value;=0A=
        if (resp !=3D null && resp !=3D '' && removeAllBlanks(resp) !=3D =
null &&=0A=
                 removeAllBlanks(resp).length > 0) {=0A=
            iA =3D true;=0A=
        }=0A=
    } else if (qT =3D=3D 'radio') { // incomprehensible bugs with this=0A=
        for (var i=3D0; i < el.length; i++) {=0A=
            if (el[i].checked) {=0A=
                iA =3D true;=0A=
            }=0A=
        }=0A=
    } else if ( typeof(qT) =3D=3D 'undefined' || qT =3D=3D null ) { // =
assume it is a radio=0A=
        for (var i=3D0; i < el.length; i++) {=0A=
            if (el[i].checked) {=0A=
                iA =3D true;=0A=
            }=0A=
        }=0A=
    } else {=0A=
        alert('Error #1 in irGrade.js.isAnswered(): input type ' + qT +=0A=
           ' is not supported!');=0A=
    }=0A=
    return(iA);=0A=
}=0A=
=0A=
=0A=
function giveAnswer(number) {=0A=
 // display the answer to question[number] in a new window, provided the =
student has=0A=
 // tried to answer the question=0A=
    answer =3D parseKey(key[findNum(number)-1]);=0A=
    ansWin =3D window.open('','ansWin',=0A=
        'toolbar=3Dno,location=3Dno,directories=3Dno,status=3Dno,' +=0A=
        'scrollbars=3Dyes,resizable=3Dyes,width=3D230,height=3D160');=0A=
    ansWin.document.write(startHtm);=0A=
    if (isAnswered(number)) {=0A=
        ansWin.document.write('<p align=3D"center"><b>The correct answer =
is <br> \n' +=0A=
           '<font color=3D"green">' + ansText + '</font></b>.</p>\n' + =
dsmsHtm + endHtm);=0A=
    } else {=0A=
        ansWin.document.write('<p align=3D"center"><b>You must answer =
before you can ' +=0A=
                   'see the solution.</b>' + dsmsHtm + endHtm);=0A=
    }=0A=
    return(true);=0A=
}=0A=
=0A=
function validEmail(e) { // checks whether e appears to be a valid email =
address=0A=
    var okEmailChars=3D"._-@:%0123456789abcdefghijklmnopqrstuvwxyz";=0A=
    var truth =3D true;=0A=
    if (e =3D=3D null || e.length =3D=3D 0) {=0A=
        truth=3Dfalse;=0A=
    } else {=0A=
        et =3D trimToLowerCase(e);=0A=
        if (et.indexOf('@') =3D=3D -1 ||=0A=
            ( (et.lastIndexOf('.') !=3D et.length - 4 ) &&=0A=
              (et.lastIndexOf('.') !=3D et.length - 3 ) ) )=0A=
            truth =3D false;=0A=
        else if (et.indexOf('@') !=3D et.lastIndexOf('@')) {=0A=
            truth =3D false;=0A=
        } else {=0A=
            for (var i=3D0; i < et.length; i++) {=0A=
                if(okEmailChars.indexOf(et.charAt(i)) < 0) {truth =3D =
false;}=0A=
            }=0A=
        }=0A=
    }=0A=
    return(truth);=0A=
}=0A=
=0A=
function validSID(s){ // check whether SID is valid=0A=
    var digits=3D"0123456789";=0A=
    var truth =3D false;=0A=
    if (s.length =3D=3D 8 && s.charAt(0) =3D=3D "1" || s.length =3D=3D =
9) {=0A=
        truth =3D true;=0A=
        for (var i=3D0; i < s.length; i++){=0A=
            if (digits.indexOf(s.charAt(i)) < 0) {truth =3D false;}=0A=
        }=0A=
    }=0A=
    return(truth);=0A=
}=0A=
=0A=
function validateLabletSubmit(theForm){=0A=
// check that various form entries are filled in correctly, submit or =
cancel=0A=
    if (validateLablet(theForm)){=0A=
        return(labletSubmit(theForm));=0A=
    } else {=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function labletSubmit(theForm) {=0A=
    theForm.submitTime =3D new Date();=0A=
    confirmStr =3D 'Your assignment is ready to submit, ' +=0A=
        theForm.firstName.value + ' ' +=0A=
        theForm.lastName.value +=0A=
        '.\nPress \"OK\" to submit it now, or \"Cancel\" to return to =
the assignment.';=0A=
    if (confirm(confirmStr)){=0A=
        setExtraInputs(theForm);=0A=
        setSubmitCookie(setNum.toString(),theForm,false);=0A=
        document.forms[1].action =3D =
"http://www.stat.berkeley.edu/cgi-bin/grader";=0A=
        var s =3D collectResponses(theForm,true,true);=0A=
        document.forms[1].elements['contents'].value =3D crypt(s,bigPi);=0A=
        document.forms[1].submit();=0A=
        return(true);=0A=
    } else {=0A=
        alert("Your assignment has NOT been submitted.");=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function validateLablet(theForm) {=0A=
    if (theForm.lastName.value =3D=3D null || =
theForm.lastName.value.length =3D=3D 0 ||=0A=
             allBlanks(theForm.lastName.value) ) {=0A=
        alert('Last Name is missing');=0A=
        theForm.lastName.focus();=0A=
        return(false);=0A=
    } else if (!allLetters(theForm.lastName.value) ) {=0A=
        alert('Illegal character(s) in Last Name');=0A=
        theForm.lastName.focus();=0A=
        return(false);=0A=
    } else if (theForm.firstName.value =3D=3D null ||=0A=
          theForm.firstName.value.length =3D=3D 0 || =
allBlanks(theForm.firstName.value)) {=0A=
        alert('First Name is missing');=0A=
        theForm.firstName.focus();=0A=
        return(false);=0A=
    } else if (!allLetters(theForm.firstName.value) ) {=0A=
        alert('Illegal character(s) in First Name');=0A=
        theForm.firstName.focus();=0A=
        return(false);=0A=
    } else if ( !validEmail(theForm.email.value)) {=0A=
        alert('Email address is missing or invalid');=0A=
        theForm.email.focus();=0A=
        return(false);=0A=
    } else if (!document.applets[0].acceptSid(theForm.sid.value)) {=0A=
        alert('This SID is not enrolled.\nDid you set the course =
correctly?');=0A=
        theForm.sid.focus();=0A=
        return(false);=0A=
    } else if (!validSID(theForm.sid.value)) {=0A=
        alert('Invalid password');=0A=
        theForm.sid.focus();=0A=
        return(false);=0A=
    } else if =
(!document.applets[0].isOkPasswd(trimBlanks(theForm.sid.value),=0A=
             trimBlanks(theForm.email.value))) {=0A=
        alert('This email address is not enrolled, or does not match the =
SID.\n' +=0A=
              'Did you set the course correctly?');=0A=
        theForm.email.focus();=0A=
        return(false);=0A=
    } else {=0A=
        theForm.lastName.value =3D trimBlanks(theForm.lastName.value);=0A=
        theForm.firstName.value =3D trimBlanks(theForm.firstName.value);=0A=
        theForm.email.value =3D trimBlanks(theForm.email.value);=0A=
        theForm.sid.value =3D trimBlanks(theForm.sid.value);=0A=
        return(true);=0A=
    }=0A=
}=0A=
=0A=
function saveResponses(fname,theForm,saveAns) {=0A=
    if(setSubmitCookie(fname,theForm,false)) {=0A=
        confirm('Your answers have been saved as a cookie on your =
computer.\n' +=0A=
               'Cookies are NOT RELIABLE storage--do not count on =
them!\n' +=0A=
               'You should write your answers down, too.\n' +=0A=
               'The cookie will be erased automatically in ' + =0A=
               cookieExpireDays.toString() + ' days.');=0A=
        return(true);=0A=
    } else {=0A=
        alert('Error #1 in irGrade.saveResponses:\nYour answers have NOT =
been saved!\n' +=0A=
                'Something went wrong.');=0A=
        return(false);=0A=
    }=0A=
}=0A=
=0A=
function setSubmitCookie(fff,theForm,idInfo){=0A=
    var s =3D collectResponses(theForm,false,idInfo);=0A=
    document.cookie =3D crypt(fff + theForm.sid.value, =
theForm.sid.value) +=0A=
          "=3D" + crypt(s, theForm.sid.value) + ";EXPIRES=3D" + =
expireTimeString();=0A=
    return(true);=0A=
}=0A=
=0A=
function recoverResponses() {=0A=
    if (continueLab =3D=3D null) {=0A=
        return(false);=0A=
    } else {=0A=
        var theSid =3D getCookieVal(continueLab,"sid");=0A=
        var thePw =3D theSid;=0A=
        var tv =3D false;=0A=
        var theForm =3D document.forms[0];=0A=
        var ascStr =3D crypt(setNum.toString() + theSid, thePw)+ "=3D";=0A=
        var searchStr =3D document.cookie;=0A=
        var startInx =3D searchStr.indexOf(ascStr);=0A=
        if (startInx < 0 ) {=0A=
            return(false);=0A=
        }=0A=
        searchStr =3D =
searchStr.substring(startInx+ascStr.length,searchStr.length);=0A=
        var endInx =3D searchStr.indexOf(";");=0A=
        if (endInx > -1 ) {=0A=
            searchStr =3D searchStr.substring(0,endInx);=0A=
        }=0A=
        searchStr =3D crypt(searchStr,thePw) + "&";=0A=
        var qName;=0A=
        var aText;=0A=
        var inx;=0A=
        var ampInx;=0A=
        var elem;=0A=
        for (var i=3D0; i < theForm.elements.length; i++) {=0A=
            qName =3D theForm.elements[i].name + '=3D';=0A=
            if (qName.indexOf("Q") =3D=3D 0) {=0A=
                elem =3D theForm.elements[i];=0A=
                if (elem.type =3D=3D "select-multiple") {=0A=
                    while (searchStr.indexOf(qName) > -1) {=0A=
                           inx =3D searchStr.indexOf(qName);=0A=
                           searchStr =3D =
searchStr.substring(inx+qName.length,searchStr.length);=0A=
                           ampInx =3D searchStr.indexOf('&');=0A=
                           qText =3D =
unescape(searchStr.substring(0,ampInx));=0A=
                           // search for option to select=0A=
                           var ag =3D false;=0A=
                           for (var j=3D0; j < elem.length; j++) {=0A=
                                if (elem[j].value =3D=3D qText) {=0A=
                                    elem.options[j].selected =3D true;=0A=
                                    ag =3D true;=0A=
                                }=0A=
                           }=0A=
                    }=0A=
                    // if (CA && ag){=0A=
                        //tv =3D checkAnswer(qName.substr(0,qName.length =
- 1),=0A=
                        //  parseMultiple(theForm.elements[i].options));=0A=
                    //}=0A=
                } else if (elem.type =3D=3D 'select-one') {=0A=
                       inx =3D searchStr.indexOf(qName);=0A=
                       if (inx > -1){=0A=
                           searchStr =3D =
searchStr.substring(inx+qName.length,searchStr.length);=0A=
                           ampInx =3D searchStr.indexOf('&');=0A=
                           qText =3D =
unescape(searchStr.substring(0,ampInx));=0A=
                           // search for option to select=0A=
                           for (var j=3D0; j < elem.length; j++) {=0A=
                             if (elem[j].value =3D=3D qText) {=0A=
                                elem.options[j].selected =3D true;=0A=
                             }=0A=
                           }=0A=
                    }=0A=
                    // if (CA) {=0A=
                    //  var si =3D =
theForm.elements[i].options.selectedIndex;=0A=
                    //  if (si !=3D null) {=0A=
                    //      tv =3D =
checkAnswer(qName.substr(0,qName.length - 1),=0A=
                    //      elem.options[si].value);=0A=
                    //  }=0A=
                    //}=0A=
                } else if (elem.type =3D=3D 'text') {=0A=
                       inx =3D searchStr.indexOf(qName);=0A=
                       if (inx > -1) {=0A=
                           searchStr =3D searchStr.substring(=0A=
                                inx+qName.length,searchStr.length);=0A=
                           ampInx =3D searchStr.indexOf('&');=0A=
                           qText =3D =
unescape(searchStr.substring(0,ampInx));=0A=
                           elem.value =3D qText;=0A=
                       }=0A=
                       // if (CA) {=0A=
                       //       var dba =3D trimBlanks(elem.value);=0A=
                        //  if (dba.length > 0) {=0A=
                     //             tv =3D =
checkAnswer(qName.substr(0,qName.length - 1),=0A=
                     //                              elem.value);=0A=
                        //  }=0A=
                        //}=0A=
                } else if (elem.type =3D=3D null || elem.type =3D=3D =
'radio' || =0A=
                           elem.type =3D=3D 'undefined') {=0A=
                    inx =3D searchStr.indexOf(qName);=0A=
                       if (inx > -1){=0A=
                           searchStr =3D =
searchStr.substring(inx+qName.length,searchStr.length);=0A=
                           ampInx =3D searchStr.indexOf('&');=0A=
                           qText =3D =
unescape(searchStr.substring(0,ampInx));=0A=
                           if (elem.value =3D=3D qText) {=0A=
                                elem.checked =3D true;=0A=
                           }=0A=
                       }=0A=
                } else {=0A=
                    alert('Error #1 in irGrade.recoverResponses(): =
unsupported problem type ' +=0A=
                        elem.type + '!');=0A=
                    return(false);=0A=
                }=0A=
            }=0A=
        }=0A=
    }=0A=
    return(true);=0A=
}=0A=
=0A=
function collectResponses(theForm,saveAs,saveId) {=0A=
    var typ;=0A=
    var nam;=0A=
    var s =3D '';=0A=
    s +=3D 'randSeed=3D' + escape(randSeed) + '&';=0A=
    for (var i=3D0; i < theForm.elements.length; i++) {=0A=
        typ =3D theForm.elements[i].type;=0A=
        nam =3D theForm.elements[i].name;=0A=
        if (typ =3D=3D "button" || typ =3D=3D "submit" || typ =3D=3D =
"reset") {=0A=
        } else if (!saveId && (nam =3D=3D "lastName" || nam =3D=3D =
"firstName" ||=0A=
                             nam =3D=3D "sid" || nam =3D=3D "sid2" || =
nam =3D=3D "email" ||=0A=
                             nam =3D=3D "passwd" || nam =3D=3D =
"passwd2")) {=0A=
        } else if (typ =3D=3D "select-one") {=0A=
            s +=3D escape(nam) + "=3D" +=0A=
                 escape(theForm.elements[i].options[=0A=
                   theForm.elements[i].options.selectedIndex].value)+ =
"&";=0A=
        } else if (typ =3D=3D "select-multiple") {=0A=
            for (var j=3D0; j < theForm.elements[i].options.length; j++) =
{=0A=
                if (theForm.elements[i].options[j].selected) {=0A=
                    s +=3D escape(nam) + "=3D" +=0A=
                        escape(theForm.elements[i].options[j].value) + =
"&";=0A=
                }=0A=
            }=0A=
        } else if (typ =3D=3D "radio") {=0A=
            if (theForm.elements[i].checked) {=0A=
                s +=3D escape(nam) + '=3D' +=0A=
                    escape(theForm.elements[i].value) + '&';=0A=
            }=0A=
        } else {=0A=
            s +=3D escape(nam) + "=3D" + =
escape(theForm.elements[i].value) + "&";=0A=
        }=0A=
    }=0A=
    if (saveAs) {=0A=
        for (var i=3D0; i < key.length; i++) {=0A=
            s +=3D escape('a' + (i+1).toString()) + '=3D' + =
escape(key[i].toString()) + '&';=0A=
        }=0A=
    }=0A=
    if (s[s.length-1] =3D=3D "&") {=0A=
        s =3D s.substring(0,s.length - 1);=0A=
    }=0A=
    return(s);=0A=
}=0A=
=0A=
function labSetUp(seed, sn) {=0A=
    isLab =3D true;=0A=
    sectionContext =3D 'function setSectionContext() { \n' =0A=
    window.name=3D 'seti';=0A=
    setNum =3D sn;=0A=
    HI =3D true;=0A=
    if (typeof(parent.reveal) =3D=3D 'undefined') {=0A=
        CA =3D 'invalid';=0A=
    } else {=0A=
        CA =3D parent.reveal;=0A=
    }=0A=
    if (seed !=3D "SeEd") {=0A=
        rand =3D new rng(parseInt(seed));=0A=
    } else {=0A=
        continueLab =3D parent.continueLab;=0A=
        if (continueLab =3D=3D null || CA =3D=3D 'invalid') {=0A=
            alert('Error #1 in irGrade.labSetUp()!\n' +=0A=
                'Problem Set not initialized correctly.\n' +=0A=
                'You must use the Problem Set Form to go to this =
page.\n' +=0A=
                'If you did, make sure your browser is configured to =
accept cookies, ' +=0A=
                ' and try again.\n ');=0A=
            document.close();=0A=
            window.close();=0A=
            return(false);=0A=
        } else {=0A=
            var searchStr =3D continueLab + '&';=0A=
            var pat =3D "randSeed=3D";=0A=
            var inx =3D searchStr.indexOf(pat);=0A=
            if (inx < 0) {=0A=
                alert('Error #2 in irGrade.labSetUp()!\n' +=0A=
                    'Problem Set not recovered correctly.\n' +=0A=
                    'Questions may have changed!');=0A=
                rand =3D new rng();=0A=
            } else {=0A=
                searchStr =3D searchStr.substring(=0A=
                    inx + pat.length, searchStr.length);=0A=
                randSeed =3D =
unescape(searchStr.substring(0,searchStr.indexOf('&')));=0A=
                rand =3D new rng(randSeed);=0A=
            }=0A=
        }=0A=
    }=0A=
    randSeed =3D rand.getSeed();=0A=
    writeProblemSetHeader(setNum);=0A=
    return(true);=0A=
}=0A=
=0A=
function setRequiredInputs(theForm) {=0A=
    theForm.elements['lastName'].value =3D  =
getCookieVal(continueLab,"lastName");=0A=
    theForm.elements['firstName'].value =3D =
getCookieVal(continueLab,"firstName");=0A=
    theForm.elements['email'].value =3D =
getCookieVal(continueLab,"email");=0A=
    theForm.elements['sid'].value =3D getCookieVal(continueLab,"sid");=0A=
    theForm.elements['sid2'].value =3D getCookieVal(continueLab,"sid");=0A=
    theForm.elements['passwd'].value =3D getCookieVal(continueLab,"sid");=0A=
    theForm.elements['passwd2'].value =3D =
getCookieVal(continueLab,"sid");=0A=
    return(true);=0A=
}=0A=
=0A=
function setExtraInputs(theForm) {=0A=
    theForm.elements['inlinekey'].value =3D inlinePrefix + =
(qCtr-1).toString();=0A=
    theForm.elements['dFile'].value =3D parent.dFile;=0A=
    theForm.elements['teacher'].value =3D parent.teacher;=0A=
    theForm.elements['class'].value =3D parent.course;=0A=
    theForm.elements['extrainfo'].value =3D escape("seed=3D" + =
randSeed.toString() +=0A=
        "&irGradeVersion=3D" + irGradeModTime.toString());=0A=
    var nRight =3D 0;=0A=
    var qVal;=0A=
    var resp;=0A=
    var qType;=0A=
    for (var i=3D1; i < qCtr; i++) {=0A=
        qVal =3D 'Q' + i.toString();=0A=
        qType =3D theForm.elements[qVal].type;=0A=
        if (qType =3D=3D 'select-one') {=0A=
            resp =3D theForm.elements[qVal].options[=0A=
               theForm.elements[qVal].options.selectedIndex].value;=0A=
        } else if (qType =3D=3D 'select-multiple') {=0A=
            resp =3D parseMultiple(theForm.elements[qVal].options);=0A=
        } else if (qType =3D=3D 'text') {=0A=
            resp =3D theForm.elements[qVal].value;=0A=
        } else if (qType =3D=3D 'radio') {=0A=
            if (theForm.elements[qVal].checked) {=0A=
                resp =3D theForm.elements[qVal].value;=0A=
            }=0A=
        } else if (qType =3D=3D null || qType =3D=3D 'undefined') { // =
radio too!=0A=
            if (theForm.elements[qVal].checked) {=0A=
                resp =3D theForm.elements[qVal].value;=0A=
            }=0A=
        } else {=0A=
            alert('Error #1 in irGrade.setExtraInputs(): Input type ' + =
qType +=0A=
               ' in question ' + qVal + ' is not supported!');=0A=
        }=0A=
        if (scoreProblem(key[i-1],resp)) nRight++;=0A=
    }=0A=
    theForm.elements['score'].value =3D roundToDig(100*nRight/(qCtr - =
1),2).toString();=0A=
    return(true);=0A=
}=0A=
=0A=
function killApplets() { // dispose of applets when leaving the page=0A=
    for (var i =3D 0; i < document.applets.length; i++) {=0A=
        document.applets[i].stop();=0A=
        document.applets[i].destroy();=0A=
    }=0A=
    return(true);=0A=
}=0A=
    =0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D SPECIAL HTML GENERATORS =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
function chapterSetUp(seed, chNum, titStr) {=0A=
    theChapter =3D null;=0A=
    for (var i=3D0; i < theChapters.length; i++) {=0A=
        if (theChapters[i].toString() =3D=3D chNum.toString()) {=0A=
            theChapter =3D i;=0A=
        }=0A=
    }=0A=
    if (theChapter =3D=3D null) {=0A=
        alert('Error in irGrade.chapterSetUp(): chapter ' + chNum +=0A=
              ' is not in the index!');=0A=
        theChapter =3D 0;=0A=
    }=0A=
    var statStr;=0A=
    if (seed !=3D "SeEd") {=0A=
        rand =3D new rng(parseInt(seed));=0A=
    } else {=0A=
        rand =3D new rng();=0A=
    }=0A=
    window.name =3D "bookWin";=0A=
    if (typeof(titStr) =3D=3D 'undefined' || titStr =3D=3D null ) {=0A=
        statStr =3D "Chapter " + (theChapters[theChapter]).toString();=0A=
    } else {=0A=
        statStr =3D titStr;=0A=
    }=0A=
    defaultStatus =3D "SticiGui " + statStr;=0A=
    document.writeln('<head><title>' + defaultStatus + '</title>' +=0A=
                     '<base target=3D"glossWin"></head>');=0A=
    document.writeln("<h1 align=3D\"center\"><a href=3D\"../index.htm\" =
" +=0A=
            " target=3D\"_top\">SticiGui</a> " + statStr + "</h1>");=0A=
    CA =3D (1=3D=3D1);=0A=
    HI =3D false;=0A=
    randSeed =3D rand.getSeed();=0A=
    sectionContext =3D 'function setSectionContext() { \n' =0A=
    return(true);=0A=
}=0A=
=0A=
function examSetUp(seed, sName, sn) {=0A=
    isLab =3D false;=0A=
    sectionContext =3D 'function setSectionContext() { \n' =0A=
    window.name=3D 'seti';=0A=
    examName =3D sName;=0A=
    examNum =3D sn;=0A=
    HI =3D true;=0A=
    if (seed !=3D "SeEd") {=0A=
        rand =3D new rng(parseInt(seed));=0A=
    } else {=0A=
        rand =3D new rng();=0A=
    }=0A=
    randSeed =3D rand.getSeed();=0A=
    writeExamHeader(examName, examNum.toString() + '.' + =
randSeed.toString() );=0A=
    defaultStatus =3D 'SticiGui ' + examName + ' ' + examNum.toString();=0A=
    return(true);=0A=
}=0A=
=0A=
function writeExamHeader(exNam, exVer) {=0A=
    document.writeln("<form name=3D\"labletForm\" method=3D\"POST\">");=0A=
    document.writeln("<h1 align=3D\"center\"><a href=3D\"../index.htm\" =
target=3D\"_new\">" +=0A=
        "SticiGui</a> " + exNam + '</h1><h3 align=3D"center"> Version ' =
+ =0A=
        exVer.toString() + '</h3>');=0A=
    return(true);=0A=
}=0A=
=0A=
function setApplets() {=0A=
    if (  (typeof (document.forms) !=3D 'undefined') && (document.forms =
!=3D null) &&=0A=
            (document.forms.length > 0 ) && !isLab )  {=0A=
        sectionContext +=3D 'document.forms[0].reset();\n';=0A=
    }=0A=
    if (isLab) {=0A=
        sectionContext +=3D 'recoverResponses();\n';=0A=
    }=0A=
    sectionContext +=3D '}';=0A=
    eval(sectionContext);=0A=
    setSectionContext();=0A=
}=0A=
=0A=
function writeProblemSetFooter() {=0A=
    document.writeln('<div align=3D"center"><center><table ' +=0A=
                        'border=3D"0" cellspacing=3D"1"><tr><td>');=0A=
    if (parent.allowSubmit) {=0A=
        document.writeln('<input type=3D"button" name=3D"subBut" ' +=0A=
            ' value=3D"Submit for Grading" ' +=0A=
            ' onClick=3D"labletSubmit(this.form);">');=0A=
        document.writeln('<input type=3D"button" name=3D"saveBut" =
value=3D"Save Answers" ' +=0A=
        ' onClick=3D"saveResponses(setNum.toString(),this.form,false)"> =
');=0A=
    } else {=0A=
        document.writeln(' <input type=3D"reset" name=3D"reset" =
value=3D"Clear Form"> ');=0A=
    }=0A=
    document.writeln('</td></tr></table></center></div><p>&nbsp;</p> ');=0A=
    document.writeln('</form><form method=3D"POST"><input =
type=3D"hidden" name=3D"contents"></form>');=0A=
    printFootnotes();=0A=
    writeMiscFooter(false);=0A=
    return(true);=0A=
}=0A=
=0A=
function writeSolution(p,text,evalStr) {=0A=
    longKey[p-1] =3D text;=0A=
    solutionCode[p-1] =3D evalStr;=0A=
    document.writeln('<br><a href=3D"#solution_' + p.toString() +=0A=
        '" target=3D"_self">Solution</a>.');=0A=
    return(true);=0A=
}=0A=
=0A=
function writeFootnote(p,label,text) {=0A=
    footnotes[p] =3D text;=0A=
    document.writeln('<sup><a href=3D"#footnote_' + p.toString() +=0A=
        '" target=3D"_self">' + label.toString() + '</a></sup>');=0A=
    return(true);=0A=
}=0A=
=0A=
function printFootnotes() {=0A=
    if (footnotes.length > 0) {=0A=
        document.writeln('<hr size=3D"3" width=3D"70%" =
align=3D"center"><h3 align=3D"center">' +=0A=
            'Footnotes</h3>');=0A=
        for (var i=3D0; i < footnotes.length; i++ ) {=0A=
            if (typeof(footnotes[i]) !=3D 'undefined') {=0A=
               document.writeln('<p><a name=3D"footnote_' + i.toString() =
+ '"></a>' +=0A=
                  '<strong>Footnote ' + (i+1).toString() + '.</strong> ' =
+=0A=
                  footnotes[i] + '</p>');=0A=
            }=0A=
        }=0A=
    }=0A=
}=0A=
=0A=
function writeChapterFooter() {=0A=
    printFootnotes();=0A=
    if (longKey.length > 0 ) {=0A=
        document.writeln('<hr size=3D"3" width=3D"70%" =
align=3D"center"><h3 align=3D"center">' +=0A=
            'Solutions to Selected Exercises</h3>');=0A=
        for (var i=3D0; i < longKey.length; i++ ) {=0A=
            if (typeof(longKey[i]) !=3D 'undefined') {=0A=
               document.writeln('<p><a name=3D"solution_' + =
(i+1).toString() + '"></a>' +=0A=
                  '<strong>Solution to exercise ' + (i+1).toString() + =
'.</strong> ' +=0A=
                  longKey[i] + '</p>');=0A=
            }=0A=
            if (typeof(solutionCode[i]) !=3D 'undefined' && =
solutionCode[i] !=3D null=0A=
                               && solutionCode[i] !=3D "") {=0A=
                eval(solutionCode[i]);=0A=
            }=0A=
        }=0A=
    }=0A=
    document.writeln('<hr size=3D"3" width=3D"70%" align=3D"center"><h3 =
align=3D"center">');=0A=
    if (theChapter > 1) {=0A=
        document.writeln('<a href=3D"ch' + =
(theChapters[theChapter-1]).toString() + '.htm" ' +=0A=
            'target=3D"_self" =
onmouseout=3D"window.status=3DdefaultStatus;return(true);" ' +=0A=
            'onmouseover=3D"window.status=3D\'Chapter ' + =
(theChapters[theChapter-1]).toString() +=0A=
            '\';return(true);">Chapter ' + =
(theChapters[theChapter-1]).toString() + =0A=
            '</a> <small>(previous)</small>&nbsp;&nbsp;|&nbsp;&nbsp; ') ;=0A=
    }=0A=
    document.writeln('Chapter ' + theChapters[theChapter] + ' =
<small>(current)</small> ');=0A=
    if (theChapter < theChapters.length - 1) {=0A=
        document.writeln('&nbsp;&nbsp;|&nbsp;&nbsp;' +=0A=
            '<a href=3D"ch' + (theChapters[theChapter+1]).toString() + =
'.htm" ' +=0A=
            'target=3D"_self"  =
onmouseout=3D"window.status=3DdefaultStatus;return(true);" ' +=0A=
            'onmouseover=3D"window.status=3D\'Chapter ' + =
(theChapters[theChapter+1]).toString() +=0A=
            '\';return(true);">Chapter ' + =
(theChapters[theChapter+1]).toString() + =0A=
            '</a> <small>(next)</small><br> ') ;=0A=
    }=0A=
    document.writeln('<a href=3D"toc.htm" target=3D"_self" ' +=0A=
            'onmouseout=3D"window.status=3DdefaultStatus;return(true);" =
' +=0A=
            'onmouseover=3D"window.status=3D\'Table of =
Contents\';return(true);">' +=0A=
            'Text Table of Contents</a><br> ' +=0A=
            '<a href=3D"../Problems/index.htm" target=3D"_self" ' +=0A=
            'onmouseout=3D"window.status=3DdefaultStatus;return(true);" =
' +=0A=
            'onmouseover=3D"window.status=3D\'Computer-graded =
assignments\';return(true);">' +=0A=
            'Problem Sets</a><br>' +=0A=
            '<a href=3D"gloss.htm" =
onmouseout=3D"window.status=3DdefaultStatus;return(true);" ' +=0A=
            'onmouseover=3D"window.status=3D\'Extensive statistical =
glossary\';return(true);">' +=0A=
            'Glossary</a><br> ' +=0A=
            '<a href=3D"../index.htm" target=3D"_top" ' +=0A=
            'onmouseout=3D"window.status=3DdefaultStatus;return(true);" =
' +=0A=
            'onmouseover=3D"window.status=3D\'SticiGui =
Home\';return(true);">' +=0A=
            'SticiGui Home</a> </h3> ');=0A=
    writeMiscFooter(false);=0A=
    return(true);=0A=
}=0A=
=0A=
function writeMiscFooter(sr) {=0A=
    var stra =3D '<h3 align=3D"center"><a href=3D"';=0A=
    var strb =3D '/index.htm" target=3D"_top" =
onmouseout=3D"window.status=3DdefaultStatus;return(true);" ' +=0A=
               ' onmouseover=3D"window.status=3D\'SticiGui =
Home\';return(true);">' +=0A=
               'SticiGui Home</a></h3>';=0A=
    if (typeof(sr) =3D=3D 'boolean') {=0A=
        if (sr) {=0A=
           document.writeln(stra + '..' + strb);=0A=
        }=0A=
    } else {=0A=
        document.writeln(stra + sr + strb);=0A=
    }=0A=
    document.write('<p><font color=3D"#FF0000"><small>&copy;' + copyYr + =
pbsRef +=0A=
        '. All rights reserved.</small></font><br><small>Last generated =
' + today +=0A=
        '. ');=0A=
    if ( !(typeof(pageModDate) =3D=3D 'undefined') && !(pageModDate =
=3D=3D null) ) {=0A=
        document.write('Content last modified ' + pageModDate + '. ');=0A=
    }=0A=
    document.writeln('</small></p>');=0A=
    return(true);=0A=
}=0A=
=0A=
function writeProblemSetHeader(sn) {=0A=
    document.writeln("<form name=3D\"labletForm\" method=3D\"POST\">");=0A=
    var formName =3D "SticiGuiSet" + sn.toString();=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"formname\" =
value=3D\"" +=0A=
                formName + "\">");=0A=
    continueLab =3D parent.continueLab;=0A=
    if (continueLab =3D=3D null) {=0A=
        alert('Error #1 in irGrade.writeProblemSetHeader()!\n' +=0A=
            'The problem set is not correctly initialized.\n' +=0A=
            'Make sure your browser is set up to accept cookies and try =
again.');=0A=
        document.close();=0A=
        window.close();=0A=
        return(false);=0A=
    } else {=0A=
        document.writeln("<input type=3D\"hidden\" name=3D\"lastName\" =
value=3D\" \">" +=0A=
            " <input type=3D\"hidden\" name=3D\"firstName\" value=3D\" =
\">" +=0A=
            " <input type=3D\"hidden\" name=3D\"email\" value=3D\" \">" +=0A=
            " <input type=3D\"hidden\" name=3D\"sid\" value=3D\" \">" +=0A=
            " <input type=3D\"hidden\" name=3D\"sid2\" value=3D\" \">" +=0A=
            " <input type=3D\"hidden\" name=3D\"passwd\" value=3D\" \">" =
+=0A=
            " <input type=3D\"hidden\" name=3D\"passwd2\" value=3D\" =
\">");=0A=
    }=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"inlinekey\"" +=0A=
        "value=3D\" \">");=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"dFile\"" +=0A=
        " value=3D\" \">");=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"teacher\" =
value=3D\" \">");=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"class\" =
value=3D\" \">");=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"score\" =
value=3D\" \">");=0A=
    document.writeln("<input type=3D\"hidden\" name=3D\"extrainfo\" =
value=3D\" \">");=0A=
    setRequiredInputs(document.forms[0]);=0A=
    document.writeln("<h1 align=3D\"center\"><a href=3D\"../index.htm\" =
target=3D\"_new\">" +=0A=
        "SticiGui</a> Problem Set "=0A=
        + sn.toString() + "</h1>");=0A=
    return(true);=0A=
}=0A=
=0A=
function makeOptions(ans, pert, dig, extra) { // make a set of numerical =
options as answers,=0A=
                                              // converted to strings =
with dig digits of=0A=
                                              // precision. each answer =
is perturbed by a=0A=
                                              // signed multiple of pert.=0A=
                                              // extra is appended to =
each answer=0A=
    if (typeof(dig) =3D=3D "undefined" || dig =3D=3D null) {=0A=
        dig =3D 0;=0A=
    }=0A=
    if (typeof(extra) =3D=3D "undefined" || extra =3D=3D null) {=0A=
        extra =3D "";=0A=
    }=0A=
    var rs =3D listOfRandSigns(5);=0A=
    var rawOpt =3D new Array(5);=0A=
    for (var i=3D0; i < 5; i++) {=0A=
        rawOpt[i] =3D commify(roundToDig(ans + i*rs[i]*pert,dig)) + =
extra;=0A=
    }=0A=
    var optPerm =3D randPermutation(rawOpt,"inverse");=0A=
    optPerm[1] =3D alphabet[optPerm[1][0]];=0A=
    return(optPerm);=0A=
}=0A=
=0A=
function makeRangeOptions(t, lo, hi, loLim, hiLim, dig, extra, iterLim) =
{ =0A=
             // make multiple choice options=0A=
             // t is truth, lo is starting lower limit, hi is starting =
upper limit,=0A=
             // loLim is ultimate lower limit, hiLim is ultimate upper =
limit,=0A=
             // dig is digits of precision, extra is appended to each  =
answer=0A=
             // steps up and down by 10% until t is within 0.3 of the =
space between=0A=
             // answers of one of the answers=0A=
    var pertFac =3D 0.07;      // amount by which to move endpoints each =
iteration=0A=
    var closeFac =3D 0.35;     // how much closer should answer be to =
one endpoint?=0A=
    var av;=0A=
    var altern =3D false;      // alternate moving upper and lower =
endpoints=0A=
    if (typeof(extra) =3D=3D 'undefined' || extra =3D=3D null) {=0A=
        extra =3D "";=0A=
    }=0A=
    if (typeof(dig) =3D=3D 'undefined' || dig =3D=3D null) {=0A=
        dig =3D 2;=0A=
    }=0A=
    var ok =3D false;=0A=
    var lim =3D 0;=0A=
    var maxIt;=0A=
    if (typeof(iterLim) =3D=3D 'undefined' || iterLim =3D=3D null) {=0A=
        maxIt =3D maxIterations;=0A=
    } else {=0A=
        maxIt =3D iterLim;=0A=
    }=0A=
    while(!ok && lim <=3D maxIt) {=0A=
       var ans =3D linspace(lo,hi,5);=0A=
       var d =3D closeFac*(ans[1]-ans[0]);    // want to be =
significantly closer to one end=0A=
       if (t <=3D ans[0] ) {=0A=
           av =3D alphabet[0];=0A=
           ok =3D true;=0A=
       } else if ( t >=3D ans[4]) {=0A=
           av =3D alphabet[4];=0A=
           ok =3D true;=0A=
       } else {=0A=
           for (i=3D0; i < ans.length; i++) {=0A=
              if (Math.abs(t - ans[i]) <=3D d) {=0A=
                 ok =3D true;=0A=
                 av =3D alphabet[i];=0A=
              }=0A=
            }=0A=
            if (altern) {=0A=
                lo =3D loLim + (1.0 - pertFac)*(lo-loLim);=0A=
                altern =3D !altern;=0A=
            } else {=0A=
                hi =3D hi + pertFac*(hiLim-hi);=0A=
                altern =3D !altern;=0A=
            }=0A=
        }=0A=
        if (lim++ =3D=3D maxIt) {=0A=
            av =3D alphabet[0];=0A=
            var ref =3D Math.abs(t-ans[0]);=0A=
            for (var i=3D1; i < ans.length; i++ ) {=0A=
                var nref =3D Math.abs(t-ans[i]);=0A=
                if (nref < ref) {=0A=
                    ref =3D nref;=0A=
                    av =3D alphabet[i];=0A=
                }=0A=
            }=0A=
            ok =3D true;=0A=
            alert('Error #1 in irGrade.makeRangeOptions: maximum =
iterations exceeded in ' +=0A=
                  'problem ' + (pCtr-1).toString() + '.\nPlease report =
this to your ' +=0A=
                  'instructor.');=0A=
        }=0A=
    }=0A=
    var opt =3D new Array(ans.length);=0A=
    for (i=3D0; i < ans.length; i++) {=0A=
       opt[i] =3D (roundToDig(ans[i],dig)).toString()+ extra;=0A=
    }=0A=
    var out =3D new Array(2);=0A=
    out[0] =3D opt;=0A=
    out[1] =3D av;=0A=
    return(out);=0A=
}=0A=
=0A=
function makeProbOptions(t, lo, hi, dig, iter) {=0A=
    if (typeof(dig) =3D=3D 'undefined' || dig =3D=3D null) {=0A=
        dig =3D 0;=0A=
    }=0A=
    return(makeRangeOptions(100*t,100*lo,100*hi,0,100,dig,'%', iter));=0A=
}=0A=
=0A=
function truthTable(title, valArr) { // make a 2 by 2 truth table=0A=
    if (valArr.length < 4) {=0A=
        alert('Error #1 in irGrade.truthTable: number of truth values is =
' + valArr.length);=0A=
        return(null);=0A=
    } else {=0A=
        return(truthTableHeader(title) +=0A=
            valArr[0] + '</td><td align=3D"center">' +=0A=
            valArr[1] +=0A=
            '</td></tr><tr><td align=3D"right" =
bgcolor=3D"lightblue">F</td><td></td>' +=0A=
            '<td align=3D"center">' +=0A=
            valArr[2] + '</td><td align=3D"center">' +=0A=
            valArr[3] + '</td><tr></table></center></div>'=0A=
        );=0A=
     }=0A=
}=0A=
=0A=
function writeTruthTable(title, valArr) {=0A=
    document.writeln(truthTable(title, valArr));=0A=
    return(true);=0A=
}=0A=
=0A=
function truthTableHeader(title) {=0A=
    return( '<div align=3D"center"><center><table border=3D"2" =
cellspacing=3D"2">' +=0A=
            '<tr><td colspan=3D"4" align=3D"center" =
bgcolor=3D"lightblue">Truth table for ' +=0A=
            title + '</td></tr><tr><td></td>' +=0A=
            '<td align=3D"right" bgcolor=3D"lightblue"><em>p</em></td>' +=0A=
            '<td align=3D"center" bgcolor=3D"lightblue">T</td>' +=0A=
            '<td align=3D"center" bgcolor=3D"lightblue">F</td></tr><tr>' =
+=0A=
            '<td align=3D"right" =
bgcolor=3D"lightblue"><em>q</em></td><td align=3D"center"></td>' +=0A=
            '<td align=3D"center"></td></tr><tr><td align=3D"right" =
bgcolor=3D"lightblue">T</td>' +=0A=
            '<td></td><td align=3D"center">');=0A=
}=0A=
=0A=
function writeTruthTableProblem(title, ansArr) { // 2 by 2 truth table =
problem=0A=
    var opt =3D ['T','F'];=0A=
    document.writeln(truthTableHeader(title));=0A=
    var solArr =3D new Array(ansArr.length);=0A=
    if ( (typeof(ansArr)).toLowerCase() =3D=3D 'function') {=0A=
        trueArr =3D [true, false];=0A=
        for (var i=3D0; i < 2; i++ ) {=0A=
            for (var j=3D0; j < 2; j++) {=0A=
                var inx =3D j + 2*i;=0A=
                if (ansArr(trueArr[j], trueArr[i])) {=0A=
                    solArr[inx] =3D 'a';=0A=
                } else {=0A=
                    solArr[inx] =3D 'b';=0A=
                }=0A=
            }=0A=
        }=0A=
    } else {=0A=
        for (var i=3D0; i < ansArr.length; i++) {=0A=
            if (ansArr[i]) {=0A=
                solArr[i] =3D 'a';=0A=
            } else {=0A=
                solArr[i] =3D 'b';=0A=
            }=0A=
        }=0A=
    }=0A=
    writeSelectExercise(false,qCtr++,opt,solArr[0]);=0A=
    document.writeln('</td><td align=3D"center">');=0A=
    writeSelectExercise(false,qCtr++,opt,solArr[1]);=0A=
    document.writeln('</td></tr><tr><td align=3D"right" =
bgcolor=3D"lightblue">F</td><td></td>' +=0A=
                     '<td align=3D"center">');=0A=
    writeSelectExercise(false,qCtr++,opt,solArr[2]);=0A=
    document.writeln('</td><td align=3D"center">');=0A=
    writeSelectExercise(false,qCtr++,opt,solArr[3]);=0A=
    document.writeln('</td><tr></table></center></div>');=0A=
}=0A=
=0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
// =3D=3D=3Dformatting functions and html generators=3D=3D=3D=3D=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
=0A=
=0A=
function commify(num) { // punctuate number strings greater than 1,000 =
in magnitude=0A=
    var str;=0A=
    var strA =3D (removeAllBlanks(num.toString())).toLowerCase();=0A=
    if ( (strA.indexOf('e') > -1) || (strA.indexOf('d') > -1) ) {=0A=
        str =3D strA;  // don't mess with exponential notation=0A=
    } else {=0A=
        str =3D strA;=0A=
        var curLoc =3D str.length;=0A=
        if ( str.indexOf('.') > -1 ) {=0A=
            curLoc =3D str.indexOf('.');=0A=
        }=0A=
        var negSign =3D str.indexOf('-');=0A=
        for (var loc =3D curLoc-4; loc > negSign; loc -=3D 3) {=0A=
            str =3D str.substr(0,loc+1) + ',' + str.substr(loc+1, =
str.length);=0A=
        }=0A=
    }=0A=
    return(str);=0A=
}=0A=
            =0A=
            =0A=
        =0A=
function writeBlankLines(k) {  // blank space=0A=
    if ( (typeof(k) =3D=3D 'undefined') || (k =3D=3D null) || (k < 0) ) {=0A=
        k =3D 1;=0A=
    }=0A=
    for (var i=3D0; i < k; i++) {=0A=
        document.writeln('<p>&nbsp;</p>');=0A=
    }=0A=
}=0A=
=0A=
function roundToDig(num,dig) { // rounds a number to dig digits after =
the decimal place=0A=
    var powOfTen =3D Math.pow(10,dig);=0A=
    var fmt =3D Math.round(num*powOfTen)/powOfTen;=0A=
    return(fmt);=0A=
}=0A=
=0A=
function doubleToStr(num,dig) {=0A=
  // returns a string representation of num, rounded to dig digits after =
the decimal=0A=
    return(removeAllBlanks(roundToDig(num,dig).toString()));=0A=
}=0A=
=0A=
function doubleToRange(num,fudge) {=0A=
  // returns a string range of num +/- fudge, separated by a colon=0A=
    var dig =3D -Math.floor(Math.log(Math.abs(fudge))/Math.log(10)) + 1;=0A=
    var s =3D roundToDig(num,dig);=0A=
    var range =3D doubleToStr(s - Math.abs(fudge),dig) + ":" +=0A=
                          doubleToStr(s+ Math.abs(fudge),dig);=0A=
    range =3D range.replace(/ /g,'');=0A=
    return(range);=0A=
}=0A=
=0A=
function numToRange(num,fudge) {=0A=
  // returns a string range of num +/- fudge, separated by a colon=0A=
    if ( (typeof(fudge) =3D=3D 'undefined') || (fudge =3D=3D null) ) {=0A=
        fudge =3D fudgeFactor*num;=0A=
    }=0A=
    if (fudge =3D=3D 0) {=0A=
        fudge =3D absFudge;=0A=
    }=0A=
    return(doubleToRange(num,Math.abs(fudge)));=0A=
}=0A=
=0A=
function numToOrdinal(num) { // turns integer into string, appends =
appropriate suffix=0A=
    var st =3D (roundToDig(num,0)).toString();=0A=
    var suffArray =3D =
["th","st","nd","rd","th","th","th","th","th","th"];=0A=
    var finalDig =3D parseInt(st.substr(st.length-1,st.length));=0A=
    return(st + suffArray[finalDig]);=0A=
}=0A=
=0A=
function listToTable(header,list,orientation,centering,print,ft) {=0A=
  // formats an array of arrays as an html table=0A=
    if (typeof(centering) =3D=3D 'undefined' || centering =3D=3D null) {=0A=
        centering =3D "right";=0A=
    }=0A=
    if (typeof(print) =3D=3D 'undefined') {=0A=
        print =3D true;=0A=
    }=0A=
    if (typeof(ft) =3D=3D 'undefined' || ft =3D=3D null) {=0A=
        ft =3D "";=0A=
        eft =3D "";=0A=
    } else {=0A=
        ft =3D '<font size=3D"' + ft + '">';=0A=
        eft =3D '</font>';=0A=
    }=0A=
    var rows =3D list.length;=0A=
    var cols;=0A=
    if (typeof(list[0]) !=3D 'object') {=0A=
        cols=3Dnull;=0A=
    } else {=0A=
        cols =3D list[0].length;=0A=
    }=0A=
    var str =3D "<div align=3D\"center\"><center><table border=3D\"2\">";=0A=
    if (cols =3D=3D null || cols =3D=3D 1) {=0A=
        str +=3D"<tr>";=0A=
        str +=3D"<td align=3D\"" + centering + "\"> " + ft + header +eft =
+ "</td>\n";=0A=
        if (orientation =3D=3D "standard") {=0A=
            for (var j=3D0; j < rows; j++) {=0A=
                str +=3D"<td align=3D\"" + centering + "\"> " + ft + =
list[j] + eft + " </td>\n";=0A=
            }=0A=
            str +=3D"</tr>";=0A=
        } else if (orientation =3D=3D "transpose") {=0A=
            str +=3D"</tr>";=0A=
            for (var j=3D0; j < rows; j++) {=0A=
                str +=3D"<tr>";=0A=
                str +=3D"<td align=3D\"" + centering + "\"> " + ft + =
list[j] + eft + " </td>\n";=0A=
                str +=3D"</tr>";=0A=
            }=0A=
        } else {=0A=
            alert("Error 1 in irGrade.listToTable: unsupported =
orientation " + orientation);=0A=
        }=0A=
    } else {=0A=
        if (orientation =3D=3D "standard") {=0A=
            for (var j =3D 0; j < rows; j++) {=0A=
                str +=3D "<tr>";=0A=
                str +=3D "<td align=3D\"" + centering + "\">" + ft + =
header[j] + eft + "</td>\n";=0A=
                for (var i=3D0; i < cols; i++) {=0A=
                    str +=3D "<td align=3D\"" + centering + "\">" +=0A=
                        ft + list[j][i] + eft + "</td>";=0A=
                }=0A=
                str +=3D"</tr>";=0A=
            }=0A=
         } else if (orientation =3D=3D "transpose") {=0A=
            str +=3D "<tr>";=0A=
            for (var i=3D0; i < header.length; i++) {=0A=
                str +=3D "<td align=3D\"" + centering + "\">" + ft + =
header[i] + eft + "</td>\n";=0A=
            }=0A=
            str +=3D "</tr>";=0A=
            for (var j =3D 0; j < cols; j++) {=0A=
                str +=3D "<tr>";=0A=
                for (var i=3D0; i < rows; i++) {=0A=
                    str +=3D "<td align=3D\"" + centering + "\">" + ft + =
list[i][j] + eft + "</td>\n";=0A=
                }=0A=
                str +=3D"</tr>";=0A=
            }=0A=
         } else {=0A=
            alert("Error 2 in irGrade.listToTable: unsupported =
orientation " + orientation);=0A=
         }=0A=
    }=0A=
    str +=3D "</table></center></div>";=0A=
    if (print) {=0A=
        document.writeln(str);=0A=
        return(true);=0A=
    } else {=0A=
        return(str);=0A=
    }=0A=
 }=0A=
=0A=
function arrayToRow(v,alignment) {=0A=
 // makes a row of a table from the elements of the array v, with =
specified alignment=0A=
    document.writeln("<tr>");=0A=
    for (var i=3D0; i < v.length; i++) {=0A=
        document.write('<td align=3D\"right\">');=0A=
        document.write(v[i].toString());=0A=
        document.writeln("</td>");=0A=
    }=0A=
    document.writeln("</tr>");=0A=
    return(true);=0A=
}=0A=
=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=0A=
// =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 STATISTICAL SUBROUTINES =
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=0A=
=0A=
function mean(list) { // computes the mean of the list=0A=
    return(vSum(list)/list.length);=0A=
}=0A=
=0A=
function vMult(a, list) { // multiply a vector times a scalar=0A=
    var list2 =3D new Array(list.length);=0A=
    for (var i=3D0; i < list.length; i++) {=0A=
        list2[i] =3D a*list[i];=0A=
    }=0A=
    return(list2);=0A=
}=0A=
=0A=
function vPointwiseMult(list1, list2) { // componentwise multiplication =
of two vectors=0A=
    var list3 =3D Math.NaN;=0A=
    if (list1.length !=3D list2.length) {=0A=
        alert('Error #1 in irGrade.vPointwiseMult: vector lengths do not =
match!');=0A=
    } else {=0A=
        list3 =3D new Array(list1.length);=0A=
        for (var i=3D0; i < list1.length; i++) {=0A=
            list3[i] =3D list1[i]*list2[i];=0A=
        }=0A=
    }=0A=
    return(list3);=0A=
}=0A=
        =0A=
function vFloor(list) { // takes floor of all components=0A=
    var list2 =3D new Array(list.length);=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        list2[i] =3D Math.floor(list[i]);=0A=
    }=0A=
    return(list2);=0A=
}=0A=
=0A=
function vCeil(list) { // takes ceil of all components=0A=
    var list2 =3D new Array(list.length);=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        list2[i] =3D Math.ceil(list[i]);=0A=
    }=0A=
    return(list2);=0A=
}=0A=
=0A=
function vRoundToInts(list) { // round all components to the nearest int=0A=
    var list2 =3D new Array(list.length);=0A=
    var tmp;=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        list2[i] =3D Math.floor(list[i]);=0A=
        if (list[i] - list2[i] >=3D 0.5) {=0A=
            list2[i]++;=0A=
        }=0A=
    }=0A=
    return(list2);=0A=
}=0A=
=0A=
function vSum(list) { // computes the sum of the elements of list=0A=
    var tot =3D 0.0;=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        tot +=3D list[i];=0A=
    }=0A=
    return(tot);=0A=
}=0A=
=0A=
function vCum(list) { // vector of cumulative sum=0A=
    var list2 =3D list;=0A=
    for (var i =3D 1; i < list.length; i++ ) {=0A=
        list2[i] +=3D list2[i-1];=0A=
    }=0A=
    return(list2);=0A=
}=0A=
=0A=
function vZero(n) { // returns a vector of zeros of length n=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        list[i] =3D 0.0;=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function vOne(n) { // returns a vector of ones of length n=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        list[i] =3D 1.0;=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function twoNorm(list) { // two norm of a vector=0A=
    var tn =3D 0.0;=0A=
    for (var i=3D0; i < list.length; i++) {=0A=
        tn +=3D list[i]*list[i];=0A=
    }=0A=
    return(Math.sqrt(tn));=0A=
}=0A=
=0A=
function convolve(a,b) { // convolve two lists=0A=
    var c =3D new Array(a.length + b.length - 1);=0A=
    var left; var right;=0A=
    for (var i=3D0; i < a.length + b.length - 1; i++) {=0A=
        c[i] =3D 0;=0A=
        right =3D Math.min(i+1, a.length);=0A=
        left =3D Math.max(0, i - b.length + 1);=0A=
        for (var j=3Dleft; j < right; j++) {=0A=
            c[i] +=3D a[j]*b[b.length - i - 1 + j];=0A=
        }=0A=
    }=0A=
    return(c);=0A=
}=0A=
=0A=
function nFoldConvolve(a,n) {=0A=
    var b =3D a;=0A=
    for (var i=3D0; i < n; i++ ) {=0A=
        b =3D convolve(b,a);=0A=
    }=0A=
    return(b);=0A=
}=0A=
=0A=
function numberLessThan(a,b) { // numerical ordering for javascript sort =
function=0A=
    var diff =3D parseFloat(a)-parseFloat(b);=0A=
    if (diff < 0) {=0A=
        return(-1);=0A=
    } else if (diff =3D=3D 0) {=0A=
        return(0);=0A=
    } else {=0A=
        return(1);=0A=
    }=0A=
}=0A=
=0A=
function numberGreaterThan(a,b) { // numerical ordering for javascript =
sort function=0A=
    var diff =3D parseFloat(a)-parseFloat(b);=0A=
    if (diff < 0) {=0A=
        return(1);=0A=
    } else if (diff =3D=3D 0) {=0A=
        return(0);=0A=
    } else {=0A=
        return(-1);=0A=
    }=0A=
}=0A=
=0A=
function sd(list) { // computes the SD of the list=0A=
    ave =3D mean(list);=0A=
    ssq =3D 0;=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        ssq +=3D (list[i] - ave)*(list[i] - ave);=0A=
    }=0A=
    ssq =3D Math.sqrt(ssq/list.length);=0A=
    return(ssq);=0A=
}=0A=
=0A=
function sampleSd(list) { // computes the sample SD of the list=0A=
    ave =3D mean(list);=0A=
    ssq =3D 0;=0A=
    for (var i =3D 0; i < list.length; i++) {=0A=
        ssq +=3D (list[i] - ave)*(list[i] - ave);=0A=
    }=0A=
    ssq =3D Math.sqrt(ssq/(list.length - 1.0));=0A=
    return(ssq);=0A=
}=0A=
=0A=
function corr(list1, list2) {=0A=
// computes the correlation coefficient of list1 and list2=0A=
    if (list1.length !=3D list2.length) {=0A=
        alert("Error #1 in irGrade.corr(): lists have different =
lengths!");=0A=
        return(Math.NaN);=0A=
    } else {=0A=
        var ave1 =3D mean(list1);=0A=
        var ave2 =3D mean(list2);=0A=
        var sd1 =3D sd(list1);=0A=
        var sd2 =3D sd(list2);=0A=
        var cc =3D 0.0;=0A=
        for (var i=3D0; i < list1.length; i++) {=0A=
            cc +=3D (list1[i] - ave1)*(list2[i] - ave2);=0A=
        }=0A=
        cc /=3D sd1*sd2*list1.length;=0A=
        return(cc);=0A=
    }=0A=
}=0A=
=0A=
function percentile(list,p) { // finds the pth percentile of list=0A=
    var n =3D list.length;=0A=
    var sList =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) sList[i] =3D list[i].valueOf();=0A=
    sList.sort(numberLessThan);=0A=
    var ppt =3D Math.max(Math.ceil(p*n/100),1);=0A=
    return(sList[ppt-1]);=0A=
}=0A=
=0A=
function listOfRandSigns(n) { // random +-1 vector=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        var rn =3D rand.next();=0A=
        if (rn < 0.5) {=0A=
            list[i] =3D -1;=0A=
        } else {=0A=
            list[i] =3D 1;=0A=
        }=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function listOfRandUniforms(n, lo, hi) { // n random variables uniform =
on (lo, hi)=0A=
    if ( (typeof(lo) =3D=3D 'undefined') || (lo =3D=3D null) ) {=0A=
        lo =3D 0.0;=0A=
    }=0A=
    if ( (typeof(hi) =3D=3D 'undefined') || (hi =3D=3D null) ) {=0A=
            hi =3D 1.0;=0A=
    }=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        list[i] =3D lo + (hi-lo)*rand.next();=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function listOfRandInts(n, lo, hi) { // n random integers between lo and =
hi=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        list[i] =3D Math.floor((hi+1 - lo)*rand.next()) + lo;=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function listOfDistinctRandInts(n, lo, hi) { // n dintinct random =
integers between lo and hi=0A=
    var list =3D new Array(n);=0A=
    var trial;=0A=
    var i=3D0;=0A=
    var unique;=0A=
    while (i < n) {=0A=
        trial =3D Math.floor((hi+1 - lo)*rand.next()) + lo;=0A=
        unique =3D true;=0A=
        for (var j =3D 0; j < i; j++) {=0A=
            if (trial =3D=3D list[j]) unique =3D false;=0A=
        }=0A=
        if (unique) {=0A=
            list[i] =3D trial;=0A=
            i++;=0A=
        }=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function randomSample(list, ssize, replace) {=0A=
  // sample from list, size ssize w/ or w/o replacement.=0A=
  // default is without replacement=0A=
    var sample =3D new Array();=0A=
    var indices =3D new Array();=0A=
    if (replace !=3D null && replace ) {=0A=
        indices =3D listOfRandInts(ssize,0,list.length-1);=0A=
    } else {=0A=
        indices =3D listOfDistinctRandInts(ssize,0,list.length - 1);=0A=
    }=0A=
    for (var i=3D0; i < ssize; i++) {=0A=
        sample[i] =3D list[indices[i]];=0A=
    }=0A=
    return(sample) ;=0A=
}=0A=
=0A=
function multinomialSample(pVec, n) { // multinomial sample of size n =
with probabilities pVec=0A=
    pVec =3D vMult(1.0/vSum(pVec), pVec); // renormalize in case=0A=
    var pCum =3D vCum(pVec);=0A=
    var counts =3D vZero(pVec.length);=0A=
    var rv;=0A=
    var inx;=0A=
    for (var i=3D0; i < n; i++) {=0A=
        rv =3D rand.next();=0A=
        inx =3D 0;=0A=
        while ( (rv > pCum[inx]) && (inx < n) ) {=0A=
            inx++;=0A=
        }=0A=
        counts[inx]++;=0A=
    }=0A=
    return(counts);=0A=
}=0A=
=0A=
function normPoints(n, mu, s, dig) {   // n normals with expected value =
mu, sd s, rounded to dig=0A=
    var round =3D true;=0A=
    if ( (typeof(dig) =3D=3D 'undefined') || (dig =3D=3D null) ) {=0A=
        var round =3D false;=0A=
    }=0A=
    var xVal =3D new Array(n);=0A=
    if (round) {=0A=
        for (var i=3D0; i < n; i++) {=0A=
            xVal[i] =3D roundToDig(mu + s*rNorm(),dig);=0A=
        }=0A=
    } else {=0A=
        for (var i=3D0; i < n; i++) {=0A=
            xVal[i] =3D mu + s*rNorm(),dig;=0A=
        }=0A=
    }=0A=
    return(xVal);=0A=
}=0A=
=0A=
function cNormPoints(n, r) {=0A=
 // generate pseudorandom normal bivariate w/ specified realized =
correlation coefficient=0A=
    var xVal =3D new Array(n);=0A=
    var yVal =3D new Array(n);=0A=
    for (var i=3D0; i<n ; i++ ) {=0A=
        xVal[i]=3D rNorm();=0A=
        yVal[i] =3D rNorm();=0A=
    }=0A=
    var rAtt =3D corr(xVal, yVal);=0A=
    var s =3D sgn(rAtt)*sgn(r);=0A=
    var xBarAtt =3D mean(xVal);=0A=
    var yBarAtt =3D mean(yVal);=0A=
    var xSdAtt =3D sd(xVal);=0A=
    var ySdAtt =3D sd(yVal);=0A=
    var pred =3D new Array(n);=0A=
    var resid =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        xVal[i] =3D (xVal[i] - xBarAtt)/xSdAtt;=0A=
        pred[i] =3D s*rAtt*xVal[i]*ySdAtt+ yBarAtt;=0A=
        resid[i] =3D s*yVal[i] - pred[i];=0A=
    }=0A=
    var resNrm =3D rms(resid);=0A=
    for (var i =3D 0; i < n; i++) {=0A=
        yVal[i] =3D Math.sqrt(1.0-r*r)*resid[i]/resNrm + r*xVal[i];=0A=
    }=0A=
    var ymnmx =3D vMinMax(yVal);=0A=
    var xmnmx =3D vMinMax(xVal);=0A=
    var xscl =3D 9.5/(xmnmx[1] - xmnmx[0]);=0A=
    var yscl =3D 9.5/(ymnmx[1] - ymnmx[0]);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        xVal[i] =3D (xVal[i] - xmnmx[0]) * xscl  + 1.0;=0A=
        yVal[i] =3D (yVal[i] - ymnmx[0]) * yscl + 1.0;=0A=
    }=0A=
    var lists =3D new Array(xVal,yVal);=0A=
    return(lists);=0A=
}// ends cNormPoints=0A=
=0A=
function listOfRandReals(n,lo,hi) { // n-vector of uniforms on [lo, hi]=0A=
    var list =3D new Array(n);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        list[i] =3D (hi - lo)*rand.next() + lo;=0A=
    }=0A=
    return(list);=0A=
}=0A=
=0A=
function rNorm() {  // standard normal pseudorandom variable=0A=
    var y =3D normInv(rand.next());=0A=
    return(y);=0A=
} // ends rNorm()=0A=
=0A=
function normCdf(y) { // normal distribution cumulative distribution =
function=0A=
   return(0.5*erfc(-y*0.7071067811865475));=0A=
}=0A=
=0A=
function erfc(x) { // error function=0A=
     var xbreak =3D 0.46875;     // for normal cdf=0A=
// coefficients for |x| <=3D 0.46875=0A=
    var a =3D [3.16112374387056560e00, 1.13864154151050156e02,=0A=
             3.77485237685302021e02, 3.20937758913846947e03,=0A=
             1.85777706184603153e-1];=0A=
    var b =3D [2.36012909523441209e01, 2.44024637934444173e02,=0A=
            1.28261652607737228e03, 2.84423683343917062e03];=0A=
// coefficients for 0.46875 <=3D |x| <=3D 4.0=0A=
    var c =3D [5.64188496988670089e-1, 8.88314979438837594e00,=0A=
             6.61191906371416295e01, 2.98635138197400131e02,=0A=
             8.81952221241769090e02, 1.71204761263407058e03,=0A=
             2.05107837782607147e03, 1.23033935479799725e03,=0A=
             2.15311535474403846e-8];=0A=
    var d =3D [1.57449261107098347e01, 1.17693950891312499e02,=0A=
             5.37181101862009858e02, 1.62138957456669019e03,=0A=
             3.29079923573345963e03, 4.36261909014324716e03,=0A=
             3.43936767414372164e03, 1.23033935480374942e03];=0A=
// coefficients for |x| > 4.0=0A=
    var p =3D [3.05326634961232344e-1, 3.60344899949804439e-1,=0A=
             1.25781726111229246e-1, 1.60837851487422766e-2,=0A=
             6.58749161529837803e-4, 1.63153871373020978e-2];=0A=
    var q =3D [2.56852019228982242e00, 1.87295284992346047e00,=0A=
             5.27905102951428412e-1, 6.05183413124413191e-2,=0A=
             2.33520497626869185e-3];=0A=
    var y, z, xnum, xden, result, del;=0A=
=0A=
/*=0A=
Translation of a FORTRAN program by W. J. Cody,=0A=
Argonne National Laboratory, NETLIB/SPECFUN, March 19, 1990.=0A=
The main computation evaluates near-minimax approximations=0A=
from "Rational Chebyshev approximations for the error function"=0A=
by W. J. Cody, Math. Comp., 1969, PP. 631-638.=0A=
*/=0A=
=0A=
//  evaluate  erf  for  |x| <=3D 0.46875=0A=
=0A=
    if(Math.abs(x) <=3D xbreak) {=0A=
        y =3D Math.abs(x);=0A=
        z =3D y * y;=0A=
        xnum =3D a[4]*z;=0A=
        xden =3D z;=0A=
        for (var i =3D 0; i< 3; i++) {=0A=
            xnum =3D (xnum + a[i]) * z;=0A=
            xden =3D (xden + b[i]) * z;=0A=
        }=0A=
        result =3D 1.0 - x* (xnum + a[3])/ (xden + b[3]);=0A=
    } else if (Math.abs(x) <=3D 4.0) {=0A=
        y =3D Math.abs(x);=0A=
        xnum =3D c[8]*y;=0A=
        xden =3D y;=0A=
        for (var i =3D 0; i < 7; i++) {=0A=
            xnum =3D (xnum + c[i])* y;=0A=
            xden =3D (xden + d[i])* y;=0A=
        }=0A=
        result =3D (xnum + c[7])/(xden + d[7]);=0A=
        if (y > 0.0) {=0A=
            z =3D Math.floor(y*16)/16.0;=0A=
        } else {=0A=
            z =3D Math.ceil(y*16)/16.0;=0A=
        }=0A=
        del =3D (y-z)*(y+z);=0A=
        result =3D Math.exp(-z*z) * Math.exp(-del)* result;=0A=
    } else {=0A=
        y =3D Math.abs(x);=0A=
        z =3D 1.0 / (y*y);=0A=
        xnum =3D p[5]*z;=0A=
        xden =3D z;=0A=
        for (var i =3D 0; i < 4; i++) {=0A=
            xnum =3D (xnum + p[i])* z;=0A=
            xden =3D (xden + q[i])* z;=0A=
        }=0A=
        result =3D z * (xnum + p[4]) / (xden + q[4]);=0A=
        result =3D (1.0/Math.sqrt(Math.PI) -  result)/y;=0A=
        if (y > 0.0) {=0A=
            z =3D Math.floor(y*16)/16.0;=0A=
        } else {=0A=
            z =3D Math.ceil(y*16)/16.0;=0A=
        }=0A=
        del =3D (y-z)*(y+z);=0A=
        result =3D Math.exp(-z*z) * Math.exp(-del) * result;=0A=
    }=0A=
    if (x < -xbreak) {=0A=
        result =3D 2.0 - result;=0A=
    }=0A=
    return(result);=0A=
}=0A=
=0A=
function normInv(p) {=0A=
    if ( p =3D=3D 0.0 ) {=0A=
        return(Math.NEGATIVE_INFINITY);=0A=
    } else if ( p >=3D 1.0 ) {=0A=
        return(Math.POSITIVE_INFINITY);=0A=
    } else {=0A=
        return(Math.sqrt(2.0) * erfInv(2*p - 1));=0A=
    }=0A=
}=0A=
=0A=
function erfInv(y) {=0A=
    var a =3D [ 0.886226899, -1.645349621, 0.914624893, -0.140543331];=0A=
    var b =3D [-2.118377725, 1.442710462, -0.329097515, 0.012229801];=0A=
    var c =3D [-1.970840454, -1.624906493, 3.429567803, 1.641345311];=0A=
    var d =3D [ 3.543889200, 1.637067800];=0A=
    var y0 =3D 0.7;=0A=
    var x =3D 0;=0A=
    var z =3D 0;=0A=
    if (Math.abs(y) <=3D y0) {=0A=
        z =3D y*y;=0A=
        x =3D y * (((a[3]*z+a[2])*z+a[1])*z+a[0])/=0A=
         ((((b[3]*z+b[2])*z+b[1])*z+b[0])*z+1.0);=0A=
    } else if (y > y0 && y < 1.0) {=0A=
        z =3D Math.sqrt(-Math.log((1-y)/2));=0A=
        x =3D (((c[3]*z+c[2])*z+c[1])*z+c[0]) / ((d[1]*z+d[0])*z+1);=0A=
    } else if (y < -y0 && y > -1) {=0A=
        z =3D Math.sqrt(-Math.log((1+y)/2));=0A=
        x =3D -(((c[3]*z+c[2])*z+c[1])*z+c[0])/ ((d[1]*z+d[0])*z+1);=0A=
    }=0A=
    x =3D x - (1.0 - erfc(x) - y) / (2/Math.sqrt(Math.PI) * =
Math.exp(-x*x));=0A=
    x =3D x - (1.0 - erfc(x) - y) / (2/Math.sqrt(Math.PI) * =
Math.exp(-x*x));=0A=
=0A=
    return(x);=0A=
} // ends erfInv=0A=
=0A=
function betaCdf( x,  a,  b) {=0A=
   if (a <=3D 0 || b <=3D 0) {=0A=
      return(Math.NaN);=0A=
   } else if (x >=3D 1) {=0A=
      return(1.0);=0A=
   } else if ( x > 0.0) {=0A=
      return(Math.min(incBeta(x ,a ,b),1.0));=0A=
   } else {=0A=
      return(0.0);=0A=
   }=0A=
}=0A=
=0A=
function betaPdf( x,  a,  b) {=0A=
    if (a <=3D 0 || b <=3D 0 || x < 0 || x > 1) {=0A=
        return(Math.NaN);=0A=
    } else if ((x =3D=3D 0 && a < 1) || (x =3D=3D 2 && b < 1)) {=0A=
        return(Math.POSITIVE_INFINITY);=0A=
    } else if (!(a <=3D 0 || b <=3D 0 || x <=3D 0 || x >=3D 1)) {=0A=
        return(Math.exp((a - 1)*Math.log(x) + (b-1)*Math.log(1 - x) - =
lnBeta(a,b)));=0A=
    } else {=0A=
        return(0.0);=0A=
    }=0A=
}=0A=
=0A=
function lnBeta( x, y) {=0A=
    return(lnGamma(x) + lnGamma(y) - lnGamma(x+y));=0A=
}=0A=
=0A=
function betaInv( p,  a,  b) {=0A=
    if (p < 0 || p > 1 || a <=3D 0 || b <=3D 0) {=0A=
        return(Math.NaN);=0A=
    } else if ( p =3D=3D 0 ) {=0A=
        return(Math.NEGATIVE_INFINITY);=0A=
    } else if ( p =3D=3D 1) {=0A=
        return(Math.POSITIVE_INFINITY);=0A=
    } else {=0A=
        var maxIt =3D 100;=0A=
        var it =3D 0;=0A=
        var tol =3D Math.sqrt(eps);=0A=
        var work =3D 1.0;=0A=
        var next;=0A=
        var x;=0A=
        if (a =3D=3D 0.0 ) {=0A=
            x =3D Math.sqrt(eps);=0A=
        } else if ( b =3D=3D 0.0) {=0A=
            x =3D 1 - Math.sqrt(eps);=0A=
        } else {=0A=
            x =3D a/(a+b);=0A=
        }=0A=
        while (Math.abs(work) > tol*Math.abs(x) && Math.abs(work) > tol =
&& it < maxIt) {=0A=
           it++;=0A=
           work =3D (betaCdf(x,a,b) - p)/betaPdf(x,a,b);=0A=
           next =3D  x - work;=0A=
           while (next < 0 || next > 1) {=0A=
               work =3D work/2;=0A=
               next =3D x - work;=0A=
           }=0A=
           x =3D next;=0A=
         }=0A=
         return(x);=0A=
     }=0A=
}=0A=
=0A=
function lnGamma(x) {=0A=
/*  natural ln(gamma(x)) without computing gamma(x)=0A=
    P.B. Stark, stark@stat.berkeley.edu=0A=
=0A=
      JavaScript subroutine is based on a MATLAB program by C. Moler,=0A=
      in turn based on a FORTRAN program by W. J. Cody,=0A=
      Argonne National Laboratory, NETLIB/SPECFUN, June 16, 1988.=0A=
=0A=
      References:=0A=
=0A=
      1) W. J. Cody and K. E. Hillstrom, 'Chebyshev Approximations for=0A=
         the Natural Logarithm of the Gamma Function,' Math. Comp. 21,=0A=
         1967, pp. 198-203.=0A=
=0A=
      2) K. E. Hillstrom, ANL/AMD Program ANLC366S, DGAMMA/DLGAMA, May,=0A=
         1969.=0A=
=0A=
      3) Hart, Et. Al., Computer Approximations, Wiley and sons, New=0A=
         York, 1968.=0A=
*/=0A=
=0A=
     var d1 =3D -5.772156649015328605195174e-1;=0A=
     var p1 =3D [4.945235359296727046734888e0, =
2.018112620856775083915565e2,=0A=
           2.290838373831346393026739e3, 1.131967205903380828685045e4,=0A=
           2.855724635671635335736389e4, 3.848496228443793359990269e4,=0A=
           2.637748787624195437963534e4, 7.225813979700288197698961e3];=0A=
     var q1 =3D [6.748212550303777196073036e1, =
1.113332393857199323513008e3,=0A=
           7.738757056935398733233834e3, 2.763987074403340708898585e4,=0A=
           5.499310206226157329794414e4, 6.161122180066002127833352e4,=0A=
           3.635127591501940507276287e4, 8.785536302431013170870835e3];=0A=
     var d2 =3D 4.227843350984671393993777e-1;=0A=
     var p2 =3D [4.974607845568932035012064e0, =
5.424138599891070494101986e2,=0A=
           1.550693864978364947665077e4, 1.847932904445632425417223e5,=0A=
           1.088204769468828767498470e6, 3.338152967987029735917223e6,=0A=
           5.106661678927352456275255e6, 3.074109054850539556250927e6];=0A=
     var q2 =3D [1.830328399370592604055942e2, =
7.765049321445005871323047e3,=0A=
           1.331903827966074194402448e5, 1.136705821321969608938755e6,=0A=
           5.267964117437946917577538e6, 1.346701454311101692290052e7,=0A=
           1.782736530353274213975932e7, 9.533095591844353613395747e6];=0A=
     var d4 =3D 1.791759469228055000094023e0;=0A=
     var p4 =3D [1.474502166059939948905062e4, =
2.426813369486704502836312e6,=0A=
           1.214755574045093227939592e8, 2.663432449630976949898078e9,=0A=
           2.940378956634553899906876e10, 1.702665737765398868392998e11,=0A=
           4.926125793377430887588120e11, 5.606251856223951465078242e11];=0A=
     var q4 =3D [2.690530175870899333379843e3, =
6.393885654300092398984238e5,=0A=
           4.135599930241388052042842e7, 1.120872109616147941376570e9,=0A=
           1.488613728678813811542398e10, 1.016803586272438228077304e11,=0A=
           3.417476345507377132798597e11, 4.463158187419713286462081e11];=0A=
     var c =3D [-1.910444077728e-03, 8.4171387781295e-04,=0A=
          -5.952379913043012e-04, 7.93650793500350248e-04,=0A=
          -2.777777777777681622553e-03, 8.333333333333333331554247e-02,=0A=
           5.7083835261e-03];=0A=
=0A=
     var lng =3D Math.NaN;=0A=
     var mach =3D 1.e-12;=0A=
     var den =3D 1.0;=0A=
     var num =3D 0;=0A=
     var xm1, xm2, xm4;=0A=
=0A=
   if (x < 0) {=0A=
       return(lng);=0A=
   } else if (x <=3D mach) {=0A=
       return(-Math.log(x));=0A=
   } else if (x <=3D 0.5) {=0A=
      for (var i =3D 0; i < 8; i++) {=0A=
            num =3D num * x + p1[i];=0A=
            den =3D den * x + q1[i];=0A=
      }=0A=
      lng =3D -Math.log(x) + (x * (d1 + x * (num/den)));=0A=
   } else if (x <=3D 0.6796875) {=0A=
      xm1 =3D x - 1.0;=0A=
      for (var i =3D 0; i < 8; i++) {=0A=
         num =3D num * xm1 + p2[i];=0A=
         den =3D den * xm1 + q2[i];=0A=
      }=0A=
      lng =3D -Math.log(x) + xm1 * (d2 + xm1*(num/den));=0A=
   } else if (x <=3D 1.5) {=0A=
      xm1 =3D x - 1.0;=0A=
      for (var i =3D 0; i < 8; i++) {=0A=
         num =3D num*xm1 + p1[i];=0A=
         den =3D den*xm1 + q1[i];=0A=
      }=0A=
      lng =3D xm1 * (d1 + xm1*(num/den));=0A=
   } else if (x <=3D 4.0) {=0A=
      xm2 =3D x - 2.0;=0A=
      for (var i =3D 0; i<8; i++) {=0A=
         num =3D num*xm2 + p2[i];=0A=
         den =3D den*xm2 + q2[i];=0A=
      }=0A=
      lng =3D xm2 * (d2 + xm2 * (num/den));=0A=
   } else if (x <=3D 12) {=0A=
      xm4 =3D x - 4.0;=0A=
      den =3D -1.0;=0A=
      for (var i =3D 0; i < 8; i++)  {=0A=
         num =3D num * xm4 + p4[i];=0A=
         den =3D den * xm4 + q4[i];=0A=
      }=0A=
      lng =3D d4 + xm4 * (num/den);=0A=
   } else {=0A=
      var r =3D c[6];=0A=
      var xsq =3D x * x;=0A=
      for (var i =3D 0; i < 6; i++) {=0A=
         r =3D r / xsq + c[i];=0A=
      }=0A=
      r =3D r / x;=0A=
      var lnx =3D Math.log(x);=0A=
      var spi =3D 0.9189385332046727417803297;=0A=
      lng =3D r + spi - 0.5*lnx + x*(lnx-1);=0A=
    }=0A=
    return(lng);=0A=
} // ends lnGamma=0A=
=0A=
=0A=
function normPdf( mu,  sigma, x) {=0A=
     return(Math.exp(-(x-mu)*(x-mu)/(2*sigma*sigma))/=0A=
            (Math.sqrt(2*Math.PI)*sigma));=0A=
} // ends normPdf=0A=
=0A=
=0A=
function tCdf(df, x) { // cdf of Student's t distribution with df =
degrees of freedom=0A=
    var ans;=0A=
    if (df < 1) {=0A=
        ans =3D Math.NaN;=0A=
    } else if (x =3D=3D 0.0) {=0A=
        ans =3D 0.5;=0A=
    } else if (df =3D=3D 1) {=0A=
        ans =3D .5 + Math.atan(x)/Math.PI;=0A=
    } else if (x > 0) {=0A=
        ans =3D 1 - (incBeta(df/(df+x*x), df/2.0, 0.5))/2;=0A=
    } else if (x < 0) {=0A=
        ans =3D incBeta(df/(df+x*x), df/2.0, 0.5)/2;=0A=
    }=0A=
    return(ans);=0A=
}=0A=
=0A=
function tInv(p, df ) { // inverse Student-t distribution with=0A=
                                              // df degrees of freedom=0A=
    var z;=0A=
    if (df < 0 || p < 0) {=0A=
        return(Math.NaN);=0A=
    } else if (p =3D=3D 0) {=0A=
        return(Math.NEGATIVE_INFINITY);=0A=
    } else if (p =3D=3D 1) {=0A=
        return(Math.POSITIVE_INFINITY);=0A=
    } else if (df =3D=3D 1) {=0A=
        return(Math.tan(Math.PI*(p-0.5)));=0A=
    } else if ( p >=3D 0.5) {=0A=
        z =3D betaInv(2.0*(1-p),df/2.0,0.5);=0A=
        return(Math.sqrt(df/z - df));=0A=
    } else {=0A=
        z =3D betaInv(2.0*p,df/2.0,0.5);=0A=
        return(-Math.sqrt(df/z - df));=0A=
    }=0A=
}=0A=
=0A=
function incBeta(x, a, b) { // incomplete beta function=0A=
       // I_x(z,w) =3D 1/beta(z,w) * integral from 0 to x of t^(z-1) * =
(1-t)^(w-1) dt=0A=
       // Ref: Abramowitz & Stegun, Handbook of Mathemtical Functions, =
sec. 26.5.=0A=
    var res;=0A=
    if (x < 0 || x > 1) {=0A=
        res =3D Math.NaN;=0A=
    } else {=0A=
        res =3D 0;=0A=
        var bt =3D Math.exp(lnGamma(a+b) - lnGamma(a) - lnGamma(b) +=0A=
                    a*Math.log(x) + b*Math.log(1-x));=0A=
        if (x < (a+1)/(a+b+2)) {=0A=
            res =3D bt * betaGuts(x, a, b) / a;=0A=
        } else {=0A=
            res =3D 1 - bt*betaGuts(1-x, b, a) / b;=0A=
        }=0A=
    }=0A=
    return(res);=0A=
}=0A=
=0A=
function betaGuts( x, a, b) { // guts of the incomplete beta function=0A=
    var ap1 =3D a + 1;=0A=
    var am1 =3D a - 1;=0A=
    var apb =3D a + b;=0A=
    var am =3D 1;=0A=
    var bm =3D am;=0A=
    var y =3D am;=0A=
    var bz =3D 1 - apb*x/ap1;=0A=
    var d =3D 0;=0A=
    var app =3D d;=0A=
    var ap =3D d;=0A=
    var bpp =3D d;=0A=
    var bp =3D d;=0A=
    var yold =3D d;=0A=
    var m =3D 1;=0A=
    var t;=0A=
    while (y-yold > 4*eps*Math.abs(y)) {=0A=
       t =3D 2 * m;=0A=
       d =3D m * (b - m) * x / ((am1 + t) * (a + t));=0A=
       ap =3D y + d * am;=0A=
       bp =3D bz + d * bm;=0A=
       d =3D -(a + m) * (apb + m) * x / ((a + t) * (ap1 + t));=0A=
       app =3D ap + d * y;=0A=
       bpp =3D bp + d * bz;=0A=
       yold =3D y;=0A=
       am =3D ap / bpp;=0A=
       bm =3D bp / bpp;=0A=
       y =3D app / bpp;=0A=
       if (m =3D=3D 1) bz =3D 1;=0A=
       m++;=0A=
    }=0A=
    return(y);=0A=
}=0A=
=0A=
function chi2Cdf( x, df ) {=0A=
    return(gammaCdf(x,df/2,2));=0A=
}=0A=
=0A=
function chi2Inv( p, df ) { // kluge for chi-square quantile function.=0A=
    var guess =3D Math.NaN;=0A=
    if (p =3D=3D 0.0) {=0A=
        guess =3D 0.0;=0A=
    } else if ( p =3D=3D 1.0 ) {=0A=
        guess =3D Math.POSITIVE_INFINITY;=0A=
    } else if ( p < 0.0 ) {=0A=
        guess =3D Math.NaN;=0A=
    } else {=0A=
        var tolAbs =3D 1.0e-8;=0A=
        var tolRel =3D 1.0e-3;=0A=
        guess =3D Math.max(0.0, df + Math.sqrt(2*df)*normInv(p)); // =
guess from normal approx    =0A=
        var currP =3D chi2Cdf( guess, df);=0A=
        var loP =3D currP;=0A=
        var hiP =3D currP;=0A=
        var guessLo =3D guess;=0A=
        var guessHi =3D guess;=0A=
        while (loP > p) { // step down=0A=
            guessLo =3D 0.8*guessLo;=0A=
            loP =3D chi2Cdf( guessLo, df);=0A=
        }=0A=
        while (hiP < p) { // step up=0A=
            guessHi =3D 1.2*guessHi;=0A=
            hiP =3D chi2Cdf( guessHi, df);=0A=
        }=0A=
        guess =3D (guessLo + guessHi)/2.0;=0A=
        currP =3D chi2Cdf( guess, df);=0A=
        while ( (Math.abs(currP - p) > tolAbs) || (Math.abs(currP - p)/p =
> tolRel) ) { // bisect=0A=
            if ( currP < p ) {=0A=
                guessLo =3D guess;=0A=
            } else {=0A=
                guessHi =3D guess;=0A=
            }  =0A=
            guess =3D (guessLo + guessHi)/2.0;=0A=
            currP =3D chi2Cdf(guess, df);=0A=
        }=0A=
    }=0A=
    return(guess);=0A=
}=0A=
        =0A=
function gammaCdf( x,  a,  b) { // gamma distribution CDF.=0A=
    var p =3D Math.NaN;=0A=
    if (a <=3D 0 || b <=3D 0) {=0A=
    } else if (x <=3D 0) {=0A=
        p =3D 0.0;=0A=
    } else {=0A=
        p =3D Math.min(incGamma(x/b, a), 1.0);=0A=
    }=0A=
    return(p);=0A=
}=0A=
=0A=
function incGamma( x,  a) {=0A=
    var inc =3D 0;=0A=
    var gam =3D lnGamma(a+rmin);=0A=
    if (x =3D=3D 0) {=0A=
        inc =3D 0;=0A=
    } else if (a =3D=3D 0) {=0A=
        inc =3D 1;=0A=
    } else if (x < a+1) {=0A=
        var ap =3D a;=0A=
        var sum =3D 1.0/ap;=0A=
        var del =3D sum;=0A=
        while (Math.abs(del) >=3D 10*eps*Math.abs(sum)) {=0A=
            del *=3D x/(++ap);=0A=
            sum +=3D del;=0A=
        }=0A=
        inc =3D sum * Math.exp(-x + a*Math.log(x) - gam);=0A=
    } else if (x >=3D a+1) {=0A=
       var a0 =3D 1;=0A=
       var a1 =3D x;=0A=
       var b0 =3D 0;=0A=
       var b1 =3D 1;=0A=
       var fac =3D 1;=0A=
       var n =3D 1;=0A=
       var g =3D 1;=0A=
       var gold =3D 0;=0A=
       var ana;=0A=
       var anf;=0A=
       while (Math.abs(g-gold) >=3D 10*eps*Math.abs(g)) {=0A=
            gold =3D g;=0A=
            ana =3D n - a;=0A=
            a0 =3D (a1 + a0 *ana) * fac;=0A=
            b0 =3D (b1 + b0 *ana) * fac;=0A=
            anf =3D n*fac;=0A=
            a1 =3D x * a0 + anf * a1;=0A=
            b1 =3D x * b0 + anf * b1;=0A=
            fac =3D 1.0 / a1;=0A=
            g =3D b1 * fac;=0A=
            n++;=0A=
       }=0A=
       inc =3D 1 - Math.exp(-x + a*Math.log(x) - gam) * g;=0A=
    }=0A=
    return(inc);=0A=
}=0A=
=0A=
function poissonPmf( lambda, k) {=0A=
    var p =3D 0.0;=0A=
    if (k >=3D 0) {=0A=
        p =3D Math.exp(-lambda)*Math.pow(lambda,k)/factorial(k);=0A=
    }=0A=
    return(p);=0A=
}=0A=
=0A=
function poissonCdf( lambda, k) {=0A=
    var p =3D 0;=0A=
    var b =3D 0;=0A=
    var m =3D 0;=0A=
    while (m <=3D k) {=0A=
        b +=3D Math.pow(lambda, m++)/factorial(k);=0A=
    }=0A=
    p +=3D Math.exp(-lambda)*b;=0A=
    return(p);=0A=
}=0A=
=0A=
function poissonTail(lambda, k) {=0A=
    return(1.0-poissonCdf(lambda, k-1));=0A=
}=0A=
=0A=
=0A=
function factorial(n) { // computes n!=0A=
    var fac=3D1;=0A=
    for (var i=3Dn; i > 1; i--) {fac *=3D i;}=0A=
    return(fac);=0A=
}=0A=
=0A=
function binomialCoef(n,k) { // computes n choose k=0A=
    if (n < k || n < 0) {=0A=
        return(0.0);=0A=
    } else if ( k =3D=3D 0 || n =3D=3D 0 || n =3D=3D k) {=0A=
        return(1.0);=0A=
    } else {=0A=
        var minnk =3D Math.min(k, n-k);=0A=
        var coef =3D 1;=0A=
        for (var j =3D 0; j < minnk; j++) {=0A=
            coef *=3D (n-j)/(minnk-j);=0A=
        }=0A=
        return(coef);=0A=
    }=0A=
}=0A=
=0A=
function binomialPmf(n, p, k) {  // binomial pmf at k.=0A=
    var pmf =3D binomialCoef(n,k)*Math.pow(p,k)*Math.pow((1-p),(n-k));=0A=
    return(pmf);=0A=
}=0A=
=0A=
function binomialCdf(n, p, k) {  // binomial CDF:  Pr(X <=3D k), X~B(n,p)=0A=
    if (k < 0) {=0A=
        return(0.0);=0A=
    } else if (k >=3D n) {=0A=
        return(1.0);=0A=
    } else {=0A=
        var cdf =3D 0.0;=0A=
        for (var i =3D 0; i <=3D k; i++) {=0A=
            cdf +=3D binomialPmf(n, p, i);=0A=
        }=0A=
        return(cdf);=0A=
    }=0A=
}=0A=
=0A=
function binomialTail(n,p,k) { // binomial tail probability Pr(X >=3D =
k), X~B(n,p)=0A=
    if (k < 0) {=0A=
        return(1.0);=0A=
    } else if (k >=3D n) {=0A=
        return(0.0);=0A=
    } else {=0A=
        var tailP =3D 0.0;=0A=
        for (var i =3D k; i <=3D n; i++) {=0A=
            tailP +=3D binomialPmf(n, p, i);=0A=
        }=0A=
        return(tailP);=0A=
    }=0A=
}=0A=
=0A=
function binomialInv(n, p, pt) { // binomial percentile function=0A=
    var t =3D 0;=0A=
    if (pt < 0 || pt > 1) {=0A=
        t =3D NaN;=0A=
    } else if (pt =3D=3D 0.0) {=0A=
        t =3D 0;=0A=
    } else if (pt =3D=3D 1.0) {=0A=
        t =3D n;=0A=
    } else {=0A=
        var t =3D 0;=0A=
        var pc =3D 0.0;=0A=
        while ( pc < pt ) {=0A=
            pc +=3D binomialPmf(n, p, t++);=0A=
        }=0A=
        t -=3D 1;=0A=
    }=0A=
    return(t);=0A=
}=0A=
=0A=
function multinomialCoef(list, n) { // multinomial coefficient.=0A=
// WARNING:  not very stable algorithm; avoid for large n.=0A=
    var val =3D 0; =0A=
    var lmn =3D vMinMax(list);=0A=
    if (typeof(n) =3D=3D 'undefined' || n =3D=3D null) {=0A=
        n =3D vSum(list);=0A=
    }=0A=
    if (lmn[0] < 0.0) {=0A=
        alert('Error #1 in irGrade.multinomialCoef: a number of outcomes =
is negative!');=0A=
    } else if (n =3D=3D vSum(list)) {=0A=
        val =3D factorial(n);=0A=
        for (var i=3D0; i < list.length; i++) {=0A=
            val /=3D factorial(list[i]);=0A=
        }=0A=
    }=0A=
    return(val);        =0A=
}=0A=
=0A=
function multinomialPmf(olist, plist, n) { // multinomial pmf; not =
stable algorithm=0A=
    var val =3D 0.0;=0A=
    var pmn =3D vMinMax(plist);=0A=
    var omn =3D vMinMax(olist);=0A=
    if (typeof(n) =3D=3D 'undefined' || n =3D=3D null) {=0A=
        n =3D vSum(olist);=0A=
    }=0A=
    if (olist.length !=3D plist.length) {=0A=
        alert('Error #1 in irGrade.multinomialPmf: length of outcome and =
probability vectors ' +=0A=
               'do not match!');=0A=
    } else if (pmn[0] < 0.0) {=0A=
        alert('Error #2 in irGrade.multinomialPmf: a probability is =
negative!');=0A=
    } else if (omn[0] < 0.0) {=0A=
        alert('Error #3 in irGrade.multinomialPmf: a number of outcomes =
is negative!');=0A=
    } else if (n =3D=3D vSum(olist)) {=0A=
        var pl =3D vMult(1.0/vSum(plist), plist);  // just in case=0A=
        val =3D factorial(n);=0A=
        for (var i=3D0; i< olist.length; i++) {=0A=
            val *=3D Math.pow(pl[i], olist[i])/factorial(olist[i]);=0A=
        }=0A=
    }=0A=
    return(val);=0A=
}=0A=
            =0A=
=0A=
function geoPmf( p,  k) {=0A=
  // chance it takes k trials to the first success in iid Bernoulli(p) =
trials=0A=
  // EX =3D 1/p; SD(X) =3D sqrt(1-p)/p=0A=
    if (k < 1 || p =3D=3D 0.0) {=0A=
        return(0.0);=0A=
    } else {=0A=
        return(Math.pow((1-p),k-1)*p);=0A=
    }=0A=
}=0A=
=0A=
function geoCdf( p, k) {=0A=
  // chance it takes k or fewer trials to the first success in iid =
Bernoulli(p) trials=0A=
    if (k < 1 || p =3D=3D 0.0) {=0A=
        return(0.0);=0A=
    } else {=0A=
        return(1-Math.pow( 1-p, k));=0A=
    }=0A=
}=0A=
=0A=
function geoTail( p,  k) {=0A=
  // chance of k or more trials to the first success in iid Bernoulli(p) =
trials=0A=
    return(1 - geoCdf(p, k-1));=0A=
}=0A=
=0A=
function geoInv(p, pt) { // geometric percentile function=0A=
    var t =3D 0;=0A=
    if (pt < 0 || pt > 1) {=0A=
        t =3D Math.NaN;=0A=
    } else if (pt =3D=3D 0.0) {=0A=
        t =3D 0;=0A=
    } else if (pt =3D=3D 1.0) {=0A=
        t =3D Math.POSITIVE_INFINITY;=0A=
    } else {=0A=
        var t =3D 0;=0A=
        var pc =3D 0.0;=0A=
        while ( pc < pt ) {=0A=
            pc +=3D geoPmf(p, t++);=0A=
        }=0A=
    }=0A=
    return(t);=0A=
}=0A=
=0A=
function hyperGeoPmf( N,  M,  n,  m) {=0A=
  // chance of drawing m of M objects in a sample of size n from=0A=
  // N objects in all.  p =3D (M C m)*(N-M C n-m)/(N C n)=0A=
  // EX =3D n*M/N; SD(X)=3D sqrt((N-n)/(N-1))*sqrt(np(1-p));=0A=
    var p;=0A=
    if ( n < m || N < M || M < m  || m < 0 || N < 0) {=0A=
        return(0.0);=0A=
    } else {=0A=
        p =3D binomialCoef(M,m)*binomialCoef(N-M,n-m)/binomialCoef(N,n);=0A=
        return(p);=0A=
    }=0A=
}=0A=
=0A=
function hyperGeoCdf( N,  M,  n,  m) {=0A=
  // chance of drawing m or fewer of M objects in a sample of size n from=0A=
  // N objects in all=0A=
    var p=3D0.0;=0A=
    var mMax =3D Math.min(m,M);=0A=
    mMax =3D Math.min(mMax,n);=0A=
    for (var i =3D 0; i <=3D mMax; i++) {=0A=
        p +=3D hyperGeoPmf(N, M, n, i);=0A=
    }=0A=
    return(p);=0A=
}=0A=
=0A=
function hyperGeoTail( N,  M,  n,  m) {=0A=
  // chance of drawing m or more of M objects in a sample of size n from=0A=
  // N objects in all=0A=
    var p=3D0.0;=0A=
    for (var i =3D m; i <=3D M; i++) {=0A=
        p +=3D hyperGeoPmf(N, M, n, i);=0A=
    }=0A=
    return(p);=0A=
}=0A=
=0A=
function negBinomialPmf( p,  s,  t) {=0A=
  // chance that the sth success in iid Bernoulli trials is on the tth =
trial=0A=
  // EX =3D s/p; SD(X) =3D sqrt(s(1-p))/p=0A=
    if (s > t || s < 0) {=0A=
        return(0.0);=0A=
    }=0A=
    var prob =3D p*binomialPmf(t-1,p,s-1);=0A=
    return(prob);=0A=
}=0A=
=0A=
function negBinomialCdf( p,  s,  t) {=0A=
  // chance the sth success in iid Bernoulli trials is on or before the =
tth trial=0A=
    var prob =3D 0.0;=0A=
    for (var i =3D s; i <=3D t; i++) {=0A=
        prob +=3D negBinomialPmf(p, s, i);=0A=
    }=0A=
    return(prob);=0A=
}=0A=
=0A=
function pDieRolls(rolls,spots) { // chance that the sum of 'rolls' =
rolls of a die =3D 'spots'=0A=
    if (rolls > 4) {=0A=
        alert("Error #1 in irGrade.pDiceRolls: too many rolls " + rolls =
+ ". ");=0A=
        return(Math.NaN);=0A=
    } else {  // BRUTE FORCE!=0A=
        var found =3D 0;=0A=
        if (spots < rolls || spots > 6*rolls) {return(0.0);}=0A=
        var possible =3D Math.pow(6,rolls);=0A=
        if (rolls =3D=3D 1) {=0A=
            return(1/possible);=0A=
        } else if (rolls =3D=3D 2) {=0A=
            for (var i=3D1; i <=3D6; i++ ) {=0A=
                for (var j=3D1; j <=3D 6; j++ ) {=0A=
                    if (i+j =3D=3D spots ) {found++;}=0A=
                }=0A=
            }=0A=
        } else if (rolls =3D=3D 3 ) {=0A=
            for (var i=3D1; i <=3D6; i++ ) {=0A=
                for (var j=3D1; j<=3D6; j++ ) {=0A=
                    for (var k=3D1; k<=3D6; k++ ) {=0A=
                        if (i+j+k =3D=3D spots ) {found++;}=0A=
                    }=0A=
                }=0A=
            }=0A=
        } else if (rolls =3D=3D 4 ) {=0A=
            for (var i=3D1; i <=3D6; i++ ) {=0A=
                for (var j=3D1; j<=3D6; j++ ) {=0A=
                    for (var k=3D1; k<=3D6; k++ ) {=0A=
                        for (var m=3D1; m <=3D6; m++ ) {=0A=
                            if (i+j+k+m =3D=3D spots ) {found++;}=0A=
                        }=0A=
                    }=0A=
                }=0A=
            }=0A=
        }=0A=
        return(found/possible);=0A=
    }=0A=
    return(false);=0A=
}=0A=
=0A=
function permutations(n,k) { // number of permutations of k of n things=0A=
    if (n < k || n < 0) {=0A=
        return(0);=0A=
    } else if ( k=3D=3D0 || n =3D=3D 0) {=0A=
        return(1);=0A=
    } else {=0A=
        var coef=3D1;=0A=
        for (var j=3D0; j < k; j++) coef *=3D (n-j);=0A=
    }=0A=
    return(coef);=0A=
}=0A=
=0A=
=0A=
function sgn(x) {  // signum function=0A=
    if (x >=3D 0) {=0A=
        return(1);=0A=
    } else if (x < 0) {=0A=
        return (-1);=0A=
    }=0A=
}=0A=
=0A=
function linspace(lo,hi,n) { // n linearly spaced points between lo and =
hi=0A=
    var spaced =3D new Array(n);=0A=
    var dx =3D(hi-lo)/(n-1);=0A=
    for (var i=3D0; i < n; i++) {=0A=
        spaced[i] =3D lo + i*dx;=0A=
    }=0A=
    return(spaced);=0A=
}=0A=
=0A=
function rms(list) { // rms=0A=
    var r =3D 0;=0A=
    for (var i=3D0; i < list.length; i++) r +=3D list[i]*list[i];=0A=
    r /=3D list.length;=0A=
    return(Math.sqrt(r));=0A=
}=0A=
=0A=
function vMinMax(list){ // returns min and max of list=0A=
    var mn =3D list[0];=0A=
    var mx =3D list[0];=0A=
    for (var i=3D1; i < list.length; i++) {=0A=
        if (mn > list[i]) mn =3D list[i];=0A=
        if (mx < list[i]) mx =3D list[i];=0A=
    }=0A=
    var vmnmx =3D  new Array(mn,mx);=0A=
    return(vmnmx);=0A=
}=0A=
=0A=
function vMinMaxIndices(list){ // returns min, max, index of min, index =
of max=0A=
    var mn =3D list[0];=0A=
    var indMn =3D 0;=0A=
    var mx =3D list[0];=0A=
    var indMx =3D 0;=0A=
    for (var i=3D1; i < list.length; i++) {=0A=
        if (mn > list[i]) {=0A=
            mn =3D list[i];=0A=
            indMn =3D i;=0A=
        }=0A=
        if (mx < list[i]) {=0A=
            mx =3D list[i];=0A=
            indMx =3D i;=0A=
        }=0A=
    }=0A=
    var vmnmx =3D  new Array(mn,mx,indMn,indMx);=0A=
    return(vmnmx);=0A=
}=0A=
=0A=
function vMinMaxAbs(list) {=0A=
// returns min and max of absolute values of a list's elements=0A=
    var mn =3D Math.abs(list[0]);=0A=
    var mx =3D Math.abs(list[0]);=0A=
    var val;=0A=
    for (var i=3D1; i < list.length; i++) {=0A=
        val =3D Math.abs(list[i]);=0A=
            if (mn > val) mn =3D val;=0A=
            if (mx < val) mx =3D val;=0A=
    }=0A=
    var vmnmx =3D  new Array(mn,mx);=0A=
    return(vmnmx);=0A=
}=0A=
=0A=
function randBoolean(p){ // random boolean value, prob p that it is true=0A=
    if (typeof(p) =3D=3D 'undefined' || p =3D=3D null) {=0A=
        p =3D 0.5;=0A=
    }=0A=
    if (rand.next() <=3D p) {=0A=
        return(false);=0A=
    } else {=0A=
        return(true);=0A=
    }=0A=
}=0A=
=0A=
function sortUnique(list,order) { // sort a list, remove duplicate =
entries=0A=
    var temp =3D list;=0A=
    if (typeof(order) !=3D 'undefined' && order !=3D null) {=0A=
        temp.sort(order);=0A=
    } else {=0A=
        temp.sort();=0A=
    }=0A=
    var temp2 =3D new Array(temp.length);=0A=
    temp2[0] =3D temp[0];=0A=
    var ix =3D 0;=0A=
    for (var i=3D1; i < temp.length; i++) {=0A=
        if (temp[i] !=3D temp2[ix] ) {=0A=
            temp2[++ix] =3D temp[i];=0A=
        }=0A=
    }=0A=
    return(temp2);=0A=
}=0A=
=0A=
function randPermutation(list,index) { // returns a random permutation =
of list=0A=
    var randIndex =3D =
listOfDistinctRandInts(list.length,0,list.length-1);=0A=
    var thePermutation =3D new Array(list.length);=0A=
    for (var i=3D0; i < list.length; i++) {=0A=
        thePermutation[i] =3D list[randIndex[i]];=0A=
    }=0A=
    if (typeof(index) !=3D 'undefined' && index =3D=3D 'forward') { // =
original indices=0A=
        var p =3D new Array(2);=0A=
        p[0] =3D thePermutation;=0A=
        p[1] =3D randIndex;=0A=
        thePermutation =3D p;=0A=
    } else if (typeof(index) !=3D 'undefined' && index =3D=3D 'inverse') =
{ // inverse permutation=0A=
        var p =3D new Array(2);=0A=
        p[0] =3D thePermutation;=0A=
        p[1] =3D new Array(list.length);=0A=
        for (var i=3D0; i < list.length; i++) {=0A=
            p[1][randIndex[i]] =3D i;=0A=
        }=0A=
        thePermutation =3D p;=0A=
    }=0A=
    return(thePermutation);=0A=
}=0A=
=0A=
function fakeBivariateData(nPoints, funArray, heteroFac, snr, loEnd, =
hiEnd) {=0A=
   // returns a 2-d array of synthetic data generated from a polynomial,=0A=
   // according to the contents of funArray.=0A=
   // if funArray[0] =3D=3D "polynomial", uses the other elements of =
funArray as=0A=
   // the coefficients of a polynomial.=0A=
   // funArray[1] + funArray[2]*X + funArray[3]*X^2 + ...=0A=
   // 1/3 of the points have noise level heteroFac times larger than the =
rest.=0A=
   // Normalizes the errors  to signal/noise ratio snr  in 2-norm=0A=
    var data =3D new Array(2);=0A=
    data[0] =3D new Array(nPoints);=0A=
    data[1] =3D new Array(nPoints);=0A=
    var x;=0A=
    var fVal;=0A=
    var xPow;=0A=
    if (funArray[0] =3D=3D "polynomial") {=0A=
        if (typeof(loEnd) =3D=3D 'undefined' || loEnd =3D=3D null) {   =
// lower limit of X variable=0A=
            loEnd =3D -10;=0A=
        }=0A=
        if (typeof(hiEnd) =3D=3D 'undefined' || hiEnd =3D=3D null) {   =
// upper limit of X variable=0A=
            hiEnd =3D 10;=0A=
        }=0A=
        var dX =3D (hiEnd - loEnd)/(nPoints - 1);=0A=
        for (var i=3D0; i < nPoints; i++) {=0A=
            x =3D loEnd + i*dX;=0A=
            data[0][i] =3D x;=0A=
            fVal =3D 0.0;=0A=
            xPow =3D 1.0;=0A=
            for (var j=3D1;  j < funArray.length; j++) {=0A=
                fVal +=3D  xPow*funArray[j];=0A=
                xPow *=3D x;=0A=
            }=0A=
            data[1][i] =3D fVal;=0A=
        }=0A=
    } else {=0A=
        alert('Error #1 in irGrade.fakeBivariateData()!\n' +=0A=
            'Unsupported function type: ' + funArray[0].toString());=0A=
        return(null);=0A=
    }=0A=
// now add noise.=0A=
    var sigNorm =3D twoNorm(data[1]);=0A=
    var noise =3D new Array(nPoints);=0A=
    for (var i=3D0; i < nPoints; i++) {=0A=
        noise[i] =3D rNorm();=0A=
    }=0A=
// pick a random set to perturb for heteroscedastic noise=0A=
    var segLen =3D Math.floor(nPoints/3);=0A=
    var startPt =3D Math.floor(2*nPoints/3*rand.next());=0A=
    for (var i=3DstartPt; i < startPt+segLen; i++) {=0A=
        noise[i] =3D noise[i]*heteroFac;=0A=
    }=0A=
    var noiseNorm =3D twoNorm(noise);=0A=
    for (var i=3D0; i < nPoints; i++) {=0A=
        data[1][i] +=3D noise[i]*sigNorm/noiseNorm/snr;=0A=
    }=0A=
    return(data)=0A=
}=0A=
=0A=
function nextRand() {  // generates next random number in a sequence=0A=
    var up   =3D this.seed / this.Q;=0A=
    var lo   =3D this.seed % this.Q;=0A=
    var trial =3D this.A * lo - this.R * up;=0A=
    if (trial > 0) {=0A=
        this.seed =3D trial;=0A=
    } else {=0A=
        this.seed =3D trial + this.M;=0A=
    }=0A=
    return (this.seed * this.oneOverM);=0A=
}=0A=
=0A=
function rng(s) {=0A=
       if ( typeof(s)=3D=3D'undefined' || s =3D=3D null ){=0A=
           var d =3D new Date();=0A=
           this.seed =3D 2345678901=0A=
             + (d.getSeconds() * 0xFFFFFF)=0A=
             + (d.getMinutes() * 0xFFFF);=0A=
       } else {=0A=
           this.seed =3D s;=0A=
       }=0A=
       this.A =3D 48271;=0A=
       this.M =3D 2147483647;=0A=
       this.Q =3D this.M / this.A;=0A=
       this.R =3D this.M % this.A;=0A=
       this.oneOverM =3D 1.0 / this.M;=0A=
       this.next =3D nextRand;=0A=
       this.getSeed =3D getRandSeed;=0A=
       return(this);=0A=
}=0A=
=0A=
function getRandSeed() { // get seed of random number generator=0A=
    return(this.seed);=0A=
}=0A=
=0A=
function crypt(s,t) {=0A=
    var slen =3D s.length;=0A=
    var tlen =3D t.length;=0A=
    var rad =3D 16;=0A=
    var r =3D 0;=0A=
    var i;=0A=
    var j =3D -1;=0A=
    var result =3D '';=0A=
    if (s.substr(0,2) =3D=3D "0x") {=0A=
        for (i=3D2; i < slen; i+=3D2) {=0A=
            if (++j >=3D tlen) {j =3D 0;}=0A=
            r =3D parseInt(s.substr(i,2),rad) ^ t.charCodeAt(j);=0A=
            result +=3D String.fromCharCode(r);=0A=
        }=0A=
    } else {=0A=
        result +=3D'0x';=0A=
        for ( i=3D0; i < slen; i++) {=0A=
           if (++j >=3D tlen) {j =3D 0;}=0A=
           r =3D s.charCodeAt(i) ^ t.charCodeAt(j);=0A=
           result +=3D (r < rad ? "0" : "") + r.toString(rad);=0A=
        }=0A=
    }=0A=
    return(result);=0A=
}=0A=

------=_NextPart_000_0000_01C283FA.710A0560--

