var type = 0;
var limtype = 0;
var fra = new fraction(-2,1);
var frb = new fraction(1,1);
var frc = new fraction(1,1);
var frd = new fraction(1,1);
var outpstr = "";
var step = 0;

// Constructor of a simple type - fraction                                      
function fraction(n,d)                                                          
{                                                                               
    this.num = n;                                                               
    this.denom = d;                                                             
}

function fracmult(fr1,fr2)                                                      
{                                                                               
    fr1.num = fr1.num*fr2.num;                                                  
    fr1.denom = fr1.denom*fr2.denom;                                            
    reduce(fr1);                                                                
} 

// Euclid algorithm to compute GCD                                              
function gcd(a,b)                                                               
{                                                                               
    ra = Math.abs(a);                                                           
    rb = Math.abs(b);                                                           
    if ( ra<rb )                                                                
    {                                                                           
        rr = ra;  ra = rb;  rb = rr;                                            
    }                                                                           
    while ( rb!=0 )                                                             
    {                                                                           
        rr = ra % rb; ra = rb; rb = rr;                                         
    }                                                                           
    return ra;                                                                  
}

// This function reduces a given fraction                                       
function reduce(fr)                                                             
{                                                                               
    if ( fr.num==0 )                                                            
       fr.denom = 1;                                                            
    else                                                                        
    {                                                                           
      if ( fr.denom<0 )                                                         
      {                                                                         
          fr.denom = -fr.denom;                                                 
          fr.num = -fr.num;                                                     
      }                                                                         
      g = gcd(fr.num,fr.denom);                                                 
      fr.num = fr.num/g;                                                        
      fr.denom = fr.denom/g;                                                    
    }                                                                           
}

// This function outputs a fraction in LaTeX format                             
function printfraction(pm,fr)                                                   
{                                                                               
    reduce(fr);                                                                 
    if ( pm<0 )                                                                 
      fr.num = -fr.num;                                                         
    if ( pm!=0 && fr.num>0 )                                                    
      outpstr = outpstr+"+";                                                    
    if ( fr.num!=0 )                                                            
    {                                                                           
      if ( fr.denom==1 )                                                        
         outpstr = outpstr+fr.num;                                              
      else                                                                      
      {                                                                         
         if ( fr.num<0 )                                                        
            outpstr = outpstr+"-";                                              
         outpstr = outpstr+"\\frac{"+Math.abs(fr.num)+"}{"+fr.denom+"}";        
      }                                                                         
    }                                                                           
    if ( pm<0 )                                                                 
      fr.num = -fr.num;                                                         
}

// This is modified version of printfraction - used to print -x instead of -1x  
function xprintfraction(pm,fr)                                                  
{                                                                               
    if ( fr.num==fr.denom )                                                     
    {                                                                           
        if ( pm>0 )                                                             
            outpstr = outpstr+"+";                                              
         else if ( pm<0 )                                                       
            outpstr = outpstr+"-";                                              
         return;                                                                
     }                                                                          
     if ( fr.num==-fr.denom )                                                   
     {                                                                          
         if ( pm>=0 )                                                           
             outpstr = outpstr+"-";                                             
         else if ( pm<0 )                                                       
             outpstr = outpstr+"+";                                             
         return;                                                                
     }                                                                          
     printfraction(pm,fr);                                                      
}

function isone(fr)
{
    return ( fr.num==fr.denom );
}

function printexpfr(fr)
{
    if ( isone(fr) )
        return;
    reduce(fr);
    outpstr += "^{"+fr.num;
    if ( fr.denom!=1 )
        outpstr += "/"+fr.denom;
    outpstr += "}";
}
 

function printint1()
{
    outpstr += "\\int_{";
    if ( limtype==0 )
    {
        printfraction(0,frb);
        outpstr += "}^{\\infty}\\,";
    }
    else if ( limtype==1 )
    {
        outpstr += "-\\infty}^{";
        printfraction(0,frb);
        outpstr += "}\\,";
    }
} 

function printint2()
{
    outpstr += "\\int_{";
    if ( limtype==0 )
    {
        printfraction(0,frb);
        outpstr += "}^{t}\\,";
    }
    else if ( limtype==1 )
    {
        outpstr += "t}^{";
        printfraction(0,frb);
        outpstr += "}\\,";
    }
}

function printintlims()
{
    outpstr += "_{";
    if ( limtype==0 )
    {
        printfraction(0,frb);
        outpstr += "}^{t}\\,";
    }  
    else if ( limtype==1 )
    {
        outpstr += "t}^{";
        printfraction(0,frb);
        outpstr += "}\\,";
    }
}
 
function print_integral(t)
{
    if ( t==0 )
        printint1();
    else if ( t==1 )
        printint2();
    else
        outpstr += "\\int\\, ";
    if ( type==0 )
    {
        outpstr += "e^{";
        xprintfraction(0,fra);
        outpstr += "x}\\,dx";
    } else if ( type==2 )
    {
        outpstr += "\\,\\frac{1}{x^2";
        fra1 = new fraction(fra.num*fra.num,fra.denom*fra.denom);
        printfraction(1,fra1);
        outpstr += "}\\,dx";
    } else if ( type==1 )
    {
        outpstr += "\\frac{";
        if ( !isone(fra) )
            outpstr += "(";
        outpstr +="\\ln\\,x";
        if ( !isone(fra) )
            outpstr += ")";
        printexpfr(fra);
        outpstr += "}{x}\\,dx";
    } else if ( type==3 )
    {
        outpstr += "(";
        xprintfraction(0,frc);
        outpstr += "x";
        printfraction(1,frd);
        outpstr += ")";
        printexpfr(fra);
        outpstr += "\\,dx";
    }
}

function printlim()
{
    if ( limtype!=1 )
        outpstr += "\\lim_{t\\to\\infty}";
    else
        outpstr += "\\lim_{t\\to-\\infty}"; 
}    
 
       
function getrandom()                                                            
{                                                                               
    r = 0;                                                                      
    while ( r==0 )                                                              
      r = Math.round(Math.random()*18-9);                                       
    return r;                                                                   
}

function writeNewEqn()
{
    step = 0;
    type = Math.floor(Math.random()*4);
    if ( type==4 )
        type = 0;  
    if ( type!=3 )
    { 
        if ( type==0 )
            limtype = Math.round(Math.random());
        else if ( type==1 ) 
            limtype = 0;
        else if ( type==2 )
            limtype = Math.round(Math.random());
        fra.num = getrandom();
        fra.denom = 1;
        if ( type==1 && fra.num==-1 )
            fra.num = 1;
        frb.num = getrandom();
        if ( type==1 )
        {
            frb.num = Math.abs(frb.num);
            if ( frb.num==1 && fra.num<0 )
                frb.num = 2;
        }    
        frb.denom = 1;
    }
    else
    {
        frc.num = Math.abs(getrandom());
        frc.denom = 1;
        frd.num = getrandom();
        frd.denom = 1;
        frb.num = getrandom();
        frb.denom = 1;
        fra.num = getrandom();
        fra.denom = getrandom();
        reduce(fra);
        if ( frb.num<=-frd.num/frc.num )
        {
            frb.num = Math.round(-frd.num/frc.num+1);
            if ( frb.num==0 )
                frb.num = 1;
        }
        limtype = 0;
    }  
    outpstr = "";
    print_integral(0);
    document.polynomial.reloadFromTeXString('$$'+outpstr+'$$');
    document.eq1.reloadFromTeXString('$.$');                                               
    document.eq2.reloadFromTeXString('$.$');                                               
    document.eq3.reloadFromTeXString('$.$');
    document.derivative.Continue.value="Continue";                              
    document.derivative.Cont1.value="Continue";                                 
    document.derivative.Cont2.value="Continue";                                 
}

function WriteEqn1()
{
    outpstr = "";
    print_integral(0);
    outpstr += "=";
    printlim();
    print_integral(1);
    document.eq1.reloadFromTeXString("$$"+outpstr+"$$");
    document.derivative.Continue.value="Go to next step.";
}
        
function WriteEqn2()
{
    outpstr = "";
    print_integral(2);
    outpstr += "=";
    if ( type==0 )
    {
        fra1 = new fraction(fra.denom,fra.num);
        xprintfraction(0,fra1);
        outpstr += "e^{";
        xprintfraction(0,fra);
        outpstr += "x}+C";
    }
    else if ( type==1 )
    {
        fra1 = new fraction(fra.denom,fra.num+fra.denom);    
        xprintfraction(0,fra1);
        outpstr += "(\\ln\\,x)^{";
        fra1.num = fra.num+fra.denom; fra1.denom = fra.denom; 
        printfraction(0,fra1);
        outpstr += "}+C";
    } 
    else if ( type==2 )
    {
        fra1 = new fraction(fra.denom,fra.num);
        xprintfraction(0,fra1);
        outpstr += "\\tan^{-1}\\left(";
        xprintfraction(0,fra1);
        outpstr += "x\\right)+C";
    } else if ( type==3 )
    {
        if ( fra.num==-fra.denom )
        {
            fra1 = new fraction(frc.denom,frc.num);
            xprintfraction(0,fra1);
            outpstr += "\\ln\\,(";
            xprintfraction(0,frc);
            outpstr += "x";
            printfraction(1,frd);
            outpstr += ")+C";
        }
        else 
        {
            fra1 = new fraction(fra.denom*frc.denom,(fra.num+fra.denom)*frc.num);
            xprintfraction(0,fra1);
            outpstr += "(";
            xprintfraction(0,frc);
            outpstr += "x";
            printfraction(1,frd);
            outpstr += ")";
            fra1.num = fra.num+fra.denom;  fra1.denom = fra.denom;
            printexpfr(fra1);
            outpstr += "+C";
        }  
    }
    document.eq2.reloadFromTeXString("$$"+outpstr+"$$");
    document.derivative.Cont1.value="Go to next step."; 
}

function sixdigits(x)
{
    return Math.floor(x*1000000)/1000000;
}

function WriteEqn3()
{
    if ( step==0 )
    {
        outpstr = "\\begin{array}{l}{";
        print_integral(0);
        outpstr += "}=";
        printlim();
        print_integral(1);
        outpstr += "=";
        printlim();
        outpstr += "\\left[";
        if ( type==0 )
        {
            fra1 = new fraction(fra.denom,fra.num);
            xprintfraction(0,fra1);
            outpstr += "e^{";
            xprintfraction(0,fra);
            outpstr += "x}\\right]";
            printintlims();
        }
        else if ( type==1 )
        {
            fra1 = new fraction(fra.denom,fra.num+fra.denom);
            xprintfraction(0,fra1);
            outpstr += "(\\ln\\,x)^{";
            fra1.num = fra.num+fra.denom; fra1.denom = fra.denom;
            printfraction(0,fra1);
            outpstr += "}\\right]";
            printintlims();
        }
        else if ( type==2 )
        {
            fra1 = new fraction(fra.denom,fra.num);
            xprintfraction(0,fra1);
            outpstr += "\\tan^{-1}\\left(";
            xprintfraction(0,fra1);
            outpstr += "x\\right)\\right]";
            printintlims();
        }     
        else if ( type==3 )
        {
            if ( fra.num==-fra.denom )
            {
                fra1 = new fraction(frc.denom,frc.num);
                xprintfraction(0,fra1);
                outpstr += "\\ln\\,(";
                xprintfraction(0,frc);
                outpstr += "x";
                printfraction(1,frd);
                outpstr += ")\\right]";
                printintlims();
            }
            else
            {
                fra1 = new fraction(fra.denom*frc.denom,(fra.num+fra.denom)*frc.num);
                xprintfraction(0,fra1);
                outpstr += "(";
                xprintfraction(0,frc);
                outpstr += "x";
                printfraction(1,frd);
                outpstr += ")";
                fra1.num = fra.num+fra.denom;  fra1.denom = fra.denom;
                printexpfr(fra1);
                outpstr += "\\right]";
                printintlims();
            }
        }      
        step++;
        document.eq3.reloadFromTeXString("$$"+outpstr+"\\end{array}"+"$$");
        return; 
    }
    if ( step==1 )
    {
        outpstr += "\\\\=";
        printlim();
        outpstr += "\\left[";
        if ( type==0 )
        {
            fra1 = new fraction(fra.denom,fra.num);
            if ( limtype==0 )
            {
                xprintfraction(0,fra1);
                outpstr += "e^{";
                xprintfraction(0,fra);
                outpstr += "t}";
                xprintfraction(-1,fra1);
                outpstr += "e^{";
                fra1.num = fra.num*frb.num;
                fra1.denom = fra.denom*frb.denom;
                printfraction(0,fra1);
                outpstr += "}";
            } 
            else
            {
                xprintfraction(0,fra1);
                outpstr += "e^{";
                fra2 = new fraction(fra.num*frb.num,fra.denom*frb.denom);
                printfraction(0,fra2);
                outpstr += "}";
                xprintfraction(-1,fra1);
                outpstr += "e^{";
                xprintfraction(0,fra);
                outpstr += "t}";
            } 

        }
        else if ( type==1 )
        {
            fra1 = new fraction(fra.denom,fra.num+fra.denom);
            fra2 = new fraction(fra1.denom,fra1.num);
            xprintfraction(0,fra1);
            outpstr += "(\\ln\\,t)^{";
            printfraction(0,fra2);
            outpstr += "}";
            xprintfraction(-1,fra1);
            outpstr += "(\\ln\\,";
            printfraction(0,frb);
            outpstr += ")^{";
            printfraction(0,fra2);
            outpstr += "}";
        }   
        else if ( type==2 )
        {
            fra1 = new fraction(fra.denom,fra.num);
            fra2 = new fraction(frb.num*fra.denom,frb.denom*fra.num); 
            xprintfraction(0,fra1);
            outpstr += "\\tan^{-1}\\left(";  
            if ( limtype!=1 )
            {
                xprintfraction(0,fra1);
                outpstr += "t";
            }
            else
                printfraction(0,fra2);
            outpstr += "\\right)";
            xprintfraction(-1,fra1);
            outpstr += "\\tan^{-1}\\left(";
            if ( limtype==0 )
                printfraction(0,fra2);
            else if ( limtype==1 )
            {
                xprintfraction(0,fra1);
                outpstr += "t";
            }
            else
            {
                fra1.num = -fra1.num;
                xprintfraction(0,fra1);
                fra1.num = -fra1.num;
                outpstr += "t";
            }
            outpstr += "\\right)";
        }     
        else if ( type==3 )
        {
            if ( fra.num==-fra.denom )
            {
                fra1 = new fraction(frc.denom,frc.num);
                xprintfraction(0,fra1);
                outpstr += "\\ln\\,(";
                xprintfraction(0,frc);
                outpstr += "t";
                printfraction(1,frd);
                outpstr += ")";
                xprintfraction(-1,fra1);
                outpstr += "\\ln\\,";
                fra1.num = frc.num*frb.num+frd.num;
                fra1.denom = 1;
                printfraction(0,fra1);
            }
            else
            {
                fra1 = new fraction(fra.denom*frc.denom,(fra.num+fra.denom)*frc.num);
                fra2 = new fraction(fra.num+fra.denom,fra.denom);
                xprintfraction(0,fra1);
                outpstr += "(";
                xprintfraction(0,frc);
                outpstr += "t";
                printfraction(1,frd);
                outpstr += ")";
                printexpfr(fra2);
                xprintfraction(-1,fra1);
                outpstr += "(";
                fra1.num = frc.num*frb.num+frd.num;
                fra1.denom = 1;
                printfraction(0,fra1);
                outpstr += ")";
                printexpfr(fra2);
            }
        }    
        outpstr += "\\right]";
        step++;
        document.eq3.reloadFromTeXString("$$"+outpstr+"\\end{array}"+"$$");
        return; 
    }       
    if ( step==2 )
    {
        outpstr += "\\\\={";
        reduce(fra);
        if ( type==0 )
        {
            if ( (limtype==0 && fra.num<0) || (limtype==1 && fra.num>0) )
            {
                fra1 = new fraction(fra.denom,fra.num);
                if ( limtype==0 )
                    fra1.num = -fra1.num;
                xprintfraction(0,fra1);
                outpstr += "e^{";
                fra1.num = fra.num*frb.num;
                fra1.denom = fra.denom*frb.denom;
                printfraction(0,fra1);
                outpstr += "}";
            }
            else
                outpstr += "\\infty";
        }
        else if ( type==1 )
        {
            if ( fra.num<-1 )
            {
                fra1 = new fraction(fra.denom,fra.num+fra.denom);
                fra1.num = -fra1.num;
                xprintfraction(0,fra1);
                outpstr += "(\\ln\\,";
                printfraction(0,frb);
                outpstr += ")^{";
                fra1.num = fra.num+fra.denom; fra1.denom = fra.denom;
                printfraction(0,fra1);
                outpstr += "}";
                if ( frb.num==frb.denom )
                    outpstr += "=0"; 
            }
            else
                outpstr += "\\infty";
        }    
        else if ( type==2 )
        {
            fra1 = new fraction(fra.denom,fra.num);
            reduce(fra1);
            fra2 = new fraction(Math.abs(fra1.num),2*fra1.denom);
            fra3 = new fraction(frb.num*fra.denom,frb.denom*fra.num); 
            if ( limtype==0 )
            {
                 xprintfraction(0,fra2);
                 outpstr += "\\pi";
                 xprintfraction(-1,fra1);
                 outpstr += "\\tan^{-1}\\left(";
                 printfraction(0,fra3);
                 outpstr += "\\right)";
                 if ( fra3.num == fra3.denom )
                 {
                     outpstr += "=";
                     fra3.num = 4*fra.num-2*Math.abs(fra.num);
                     fra3.denom = 8*fra.num*Math.abs(fra.num);
                     xprintfraction(0,fra3);
                     outpstr += "\\pi";
                 } 
                 else if ( fra3.num == -fra3.denom )
                 {
                     outpstr += "=";
                     fra3.num = 4*fra.num+2*Math.abs(fra.num);
                     fra3.denom = 8*fra.num*Math.abs(fra.num);
                     xprintfraction(0,fra3);
                     outpstr += "\\pi";
                 }
           
            }
            else if ( limtype==1 )
            {
                xprintfraction(0,fra1);
                outpstr += "\\tan^{-1}\\left(";
                printfraction(0,fra3);
                outpstr += "\\right)";
                xprintfraction(1,fra2);
                outpstr += "\\pi";
                if ( fra3.num == fra3.denom )
                {
                    outpstr += "=";
                    fra3.num = 2*Math.abs(fra.num)+4*fra.num;
                    fra3.denom = 8*fra.num*Math.abs(fra.num);
                    xprintfraction(0,fra3);
                    outpstr += "\\pi";
                }
                else if ( fra3.num == -fra3.denom )
                {
                    outpstr += "=";
                    fra3.num = -2*Math.abs(fra.num)+4*fra.num;
                    fra3.denom = 8*fra.num*Math.abs(fra.num);
                    xprintfraction(0,fra3);
                    outpstr += "\\pi";
                }
            }  
        } 
        else if ( type==3 )
        {
            if ( fra.num==-fra.denom )
                outpstr += "\\infty";
            else
            {
                reduce(fra);
                if ( fra.num+fra.denom>0 )
                    outpstr += "\\infty";
                else
                {
                    fra1 = new fraction(-fra.denom*frc.denom,(fra.num+fra.denom)*frc.num);
                    xprintfraction(0,fra1);
                    outpstr += "(";
                    fra2 = new fraction(frc.num*frb.num+frd.num,1);
                    printfraction(0,fra2);
                    outpstr += ")";
                    fra3 = new fraction(fra.num+fra.denom,fra.denom);
                    printexpfr(fra3);
                    xx = Math.exp((fra3.num/fra3.denom)*Math.log(fra2.num));
                    yy = 1.0/xx;
                    if ( xx==Math.floor(xx) || yy==Math.floor(yy) )
                    {
                        if ( xx==Math.floor(xx) )
                        {
                            outpstr += "=";
                            fra1.num *= Math.floor(xx);
                            printfraction(0,fra1);
                        } 
                        else 
                        {
                            outpstr += "=";
                            fra1.denom *= Math.floor(yy);
                            printfraction(0,fra1);
                        } 
                    }
                 }
            }
        }    
        outpstr += "}";  
        step++;
        document.eq3.reloadFromTeXString("$$"+outpstr+"\\end{array}"+"$$");
        document.derivative.Continue.value="Done!";
        document.derivative.Cont1.value="Done!";
        document.derivative.Cont2.value="Done!"; 
        return;         
    }
}
