//  basecvt.js
//  Written:  2009-02-05 by James Alarie <jalarie@umich.edu>
//    http://spruce.flint.umich.edu/~jalarie/
//
//  Usage:
//    CodedVersion=FromDecimal(DecimalVersion,Codes);
//    DecimalVersion=ToDecimal(CodedVersion,Codes);
//
//  The "Codes" field for both functions is a string of individual characters 
//  used in the coded version of the number.  The first should be the "zero" 
//  value, the second should represent the base, and succeeding characters 
//  represent succeeding powers of the base.
//
//  Examples:
//    BinaryVersion=FromDecimal(DecimalVersion,'01');
//    OctalVersion =FromDecimal(DecimalVersion,'01234567');
//    HexVersion   =FromDecimal(DecimalVersion,'0123456789ABCDEF');
//
//  Both functions limit their calculations to six places past the "decimal" 
//  point.

        function FromDecimal(What,Codes) {
          var Input=What, Symbols=Codes, Return='';
          var Base=Symbols.length;
          if ((Input.isNaN)
          ||  (Base < 2)) {
            Return='*** Error';
          } else {
            var Negative='no';
            var ix1, Integer, Fraction;
            if (Input < 0) {                        // input was negative
              Negative='yes';
              Input=0-Input;
            }
            Input=String(Input);
            if ((ix1=Input.indexOf('.')) > -1) {    // a fraction exists
              Integer=Input.substring(0,ix1)*1;
              Fraction=Input.substring(ix1)*1;
            } else {                                // integer only
              Integer=Input;
              Fraction='';
            }
            while (Integer > 0) {
              ix1=Integer%Base;
              Integer=Math.floor(Integer/Base);
              Code=Symbols.substring(ix1,ix1+1);
              Return=''+Code+Return;
            }
            if (Fraction) {                         // a fraction exists
              var NullChar=String(Fraction).substring(0,1);
              var NullReturn='';
              Return+='.';
              ix1=0;
              var ix2;
              while ((Fraction != 0) 
              &&     (ix1 < 6)) {
                Fraction*=Base;
                ix2=Math.floor(Fraction);
                Fraction=Fraction-ix2;
                Code=Symbols.substring(ix2,ix2+1);
                if (Code == NullChar) {
                  NullReturn+=Code;
                } else {
                  Return+=NullReturn+Code;
                  NullReturn='';
                }
                ix1++;
              }
            }
            if (Negative == 'yes') {                // input was negative
              Return='-'+Return;
            }
          }
          return Return;
        } // FromDecimal
        
        function ToDecimal(What,Codes) {
          var Input=What, Symbols=Codes, Return=0;
          var Base=Symbols.length;
          var Valid, Xeq;
          Xeq='Valid=Input.match(/^\-{0,1}['+Codes+']*\.{0,1}['+Codes+']*$/);';
          eval(Xeq);
          if ((Base < 2)
          ||  (!Valid)) {
            Return='*** Error';
          } else {
            var Negative='no';
            if (Input.substring(0,1) == '-') {      // input was negative
              Negative='yes';
              Input=Input.substring(1);
            }
            var ix1, Integer, Fraction;
            if ((ix1=Input.indexOf('.')) > -1) {    // a fraction exists
              Integer=Input.substring(0,ix1);
              Fraction=Input.substring(ix1+1);
            } else {
              Integer=Input;
              Fraction='';
            }
            var Char, Value;
            var Factor=1;
            while ((ix1=Integer.length) > 0) {
              Char=Integer.substring(ix1-1,ix1);
              Integer=Integer.substring(0,ix1-1);
              Value=Symbols.indexOf(Char);
              Return+=Value*Factor;
              Factor*=Base;
            }
            if (Fraction) {                         // a fraction exists
              Factor=Base;
              for (ix1=0; ix1<6; ix1++) {
                Char=Fraction.substring(ix1,ix1+1);
                if (Char) {
                  Value=Symbols.indexOf(Char);
                  Return+=Value/Factor;
                  Factor*=Base;
                } else {
                  ix1=999;                          // kill the loop
                }
              }
            }
            if (Negative == 'yes') {                // input was negative
              Return=0-Return;
            }
          }
          return Return;
        } // ToDecimal
