% Copyright 2007 by Mark Wibrow
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.
%
% This file provides basic macros for converting between bases.
%
% Version 0.0 08/03/2007

% \pgfmathbasetodec
%
% Convert a representation of an integer from 
% the spcified base to base 10.
%
% #1 - a macro to store the result.
% #2 - the representation of a number (i.e. not a register)
% #3 - the current base.
%
% e.g.
%
% \pgfmathbasetodec\mynumber{10111}{2}
%
% \mynumber <- 23
%
\def\pgfmathbasetodec#1#2#3{%
	\pgfmath@checknumber{#2}%
	\pgfmath@checkbase{#3}%
	\def\pgfmath@base{#3}%
	\def\pgfmath@macro{#1}%
	\c@pgfmath@counta1\relax%
	\def\pgfmath@reversed{}%
	\expandafter\pgfmathbasetodec@#2\pgfmathbasetodec}
	
\def\pgfmathbasetodec@#1{%
	\ifx\pgfmathbasetodec#1%
		\c@pgfmath@countb0%
		\divide\c@pgfmath@counta by\pgfmath@base\relax%
		\expandafter\pgfmathbasetodec@@%
	\else%
		\edef\pgfmath@reversed{\pgfmath@reversed#1}%
		\expandafter\multiply\expandafter\c@pgfmath@counta\pgfmath@base\relax%
		\expandafter\pgfmathbasetodec@%
	\fi}

\def\pgfmathbasetodec@@{\expandafter\pgfmathbasetodec@@@\pgfmath@reversed\pgfmathbasetodec}
	
\def\pgfmathbasetodec@@@#1{%
	\ifx\pgfmathbasetodec#1\relax%
		\expandafter\edef\pgfmath@macro{\the\c@pgfmath@countb}%
		\let\pgfmath@next\pgfmathbasetodec@@@@%
	\else%
		\chardef\pgfmath@charnum`#1\relax%
		\c@pgfmath@countc\pgfmath@charnum%
		\ifnum\c@pgfmath@countc>96\relax%
			\advance\c@pgfmath@countc-87\relax%
		\else
			\ifnum\c@pgfmath@countc>64\relax%
				\advance\c@pgfmath@countc-55\relax%
			\else
				\advance\c@pgfmath@countc-48\relax%
		\fi\fi%
		\ifnum\c@pgfmath@countc<\pgfmath@base\relax%
			\multiply\c@pgfmath@countc\c@pgfmath@counta\relax%
			\advance\c@pgfmath@countb\c@pgfmath@countc%
			\divide\c@pgfmath@counta by\pgfmath@base\relax%
			\let\pgfmath@next\pgfmathbasetodec@@@%
		\else
			\pgfmath@error{Digit `#1' invalid for base \pgfmath@base}%
			\let\pgfmath@next\relax%
		\fi%	
	\fi%
	\pgfmath@next}
\def\pgfmathbasetodec@@@@{%
	\expandafter\pgfmath@ensurenumberlength\expandafter{\pgfmath@macro}%
}

% \pgfmathdectobase
%
% Convert a representation of an integer from 
% base 10 to the spcified base. Letters for bases
% greater than 10 are in lowercase.
%
% #1 - a macro to store the result.
% #2 - a number in base 10 (in a macro, not a register)
% #3 - the required base.
%
% e.g.
%
% \pgfmathdectobase\mynumber{127}{16}
%
% \mynumber <- 7f
%
\def\pgfmathdectobase#1#2#3{%
	\pgfmath@checknumber{#2}%
	\pgfmath@checkbase{#3}%
	\c@pgfmath@counta#2\relax%
	\def#1{}%
	\pgfmathloop
		\ifnum\c@pgfmath@counta>0\relax%
			\c@pgfmath@countb\c@pgfmath@counta%
			\divide\c@pgfmath@countb#3\relax%
			\multiply\c@pgfmath@countb-#3\relax%
			\advance\c@pgfmath@countb\c@pgfmath@counta%
			\edef#1{\csname pgfmath@lowercase digit@\the\c@pgfmath@countb\endcsname#1}%
			\divide\c@pgfmath@counta#3\relax%
	\repeatpgfmathloop%
	\pgfmath@ensurenumberlength{#1}}

% \pgfmathdectoBase
%
% Convert a representation of an integer from 
% base 10 to the spcified base. Letters for bases
% greater than 10 are in uppercase.
%
% #1 - a macro to store the result.
% #2 - a number in base 10 (in a macro, not a register)
% #3 - the required base.
%
% e.g.
%
% \pgfmathdectoBase\mynumber{127}{16}
%
% \mynumber <- 7F
%	
\def\pgfmathdectoBase#1#2#3{%
	\pgfmath@checkbase{#3}%
	\pgfmath@checknumber{#2}%
	\c@pgfmath@counta#2\relax%
	\def#1{}%
	\pgfmathloop
		\ifnum\c@pgfmath@counta>0\relax%
			\c@pgfmath@countb\c@pgfmath@counta%
			\divide\c@pgfmath@countb#3\relax%
			\multiply\c@pgfmath@countb-#3\relax%
			\advance\c@pgfmath@countb\c@pgfmath@counta%
			\edef#1{\csname pgfmath@uppercase digit@\the\c@pgfmath@countb\endcsname#1}%
			\divide\c@pgfmath@counta#3\relax%
	\repeatpgfmathloop%
	\pgfmath@ensurenumberlength{#1}}

\def\pgfmath@createdigits{%
	\def\pgfmath@digitstyle{lowercase digit}%
	\c@pgfmath@counta0\relax%
	\pgfmath@createdigits@0123456789abcdefghijklmnopqrstuvwxyz\pgfmath@createdigits%
	\def\pgfmath@digitstyle{uppercase digit}%
	\c@pgfmath@counta0\relax%
	\pgfmath@createdigits@0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\pgfmath@createdigits}

\def\pgfmath@createdigits@#1{%
	\ifx\pgfmath@createdigits#1\relax%
	\else%
		\expandafter\pgfmath@def\expandafter{\pgfmath@digitstyle}{\the\c@pgfmath@counta}{#1}%
		\advance\c@pgfmath@counta1\relax%
		\expandafter\pgfmath@createdigits@%
	\fi}
\pgfmath@createdigits

% \pgfmathbasetobase
%
% Convert a representation of an integer from 
% between the specified bases. Letters for target
% bases greater than 10 are in lppercase.
%
% #1 - a macro to store the result.
% #2 - a number (in a macro, not a register)
% #3 - the source base.
% #4 - the target base.
%
% e.g.
%
% \pgfmathbasetobase\mynumber{4321}{5}{9}
%
% \mynumber <- 721
%	
\def\pgfmathbasetobase#1#2#3#4{%
	\pgfmathbasetodec{\pgfmath@temp}{#2}{#3}%
	\pgfmathdectobase{#1}{\pgfmath@temp}{#4}
}

% \pgfmathbasetobase
%
% Convert a representation of an integer from 
% between the specified bases. Letters for target
% bases greater than 10 are in lppercase.
%
% #1 - a macro to store the result.
% #2 - a number (in a macro, not a register)
% #3 - the source base.
% #4 - the target base.
%
% e.g.
%
% \pgfmathbasetobase\mynumber{1234}{5}{12}
%
% \mynumber <- 142
%	
\def\pgfmathbasetoBase#1#2#3#4{%
	\pgfmathbasetodec{\pgfmath@temp}{#2}{#3}%
	\pgfmathdectoBase{#1}{\pgfmath@temp}{#4}
}

\def\pgfmath@checkbase#1{%
	\ifnum#1<2\relax%
		\pgfmath@error{Cannot process numbers in base `#1'.}%
	\else%
		\ifnum#1>36\relax%
			\pgfmath@error{Cannot process numbers in base `#1'.}%
	\fi\fi}
	
\def\pgfmath@checknumber#1{%
	\expandafter\pgfmath@checknumber@#1\pgfmath@}
\def\pgfmath@checknumber@#1#2\pgfmath@{%
	\ifx#1-%
		\pgfmath@error{Cannot process negative numbers.}%
	\fi}


% \pgfmath@ensurenumberlength
%
% Internal macro for making a representation of a number have
% a specific length, byt prefixing zeros to the number.
%
% #1 - a macro contatining a representation of an integer.
% #2 - the number of digits to ensure.
%
% e.g.
%
% \foo <- 7FF
%
% \pgfmathsetnumberlength{8}%
% \pgfmath@ensurenumberlength\foo
%
% \foo <- 000007FF
%
\def\pgfmath@ensurenumberlength#1{%
	\def\pgfmath@tempa{#1}%
	\expandafter\c@pgfmath@counta\pgfmath@basenumberlength\relax%
	\expandafter\pgfmath@ensurenumberlength@#1\pgfmath@ensurenumberlength}
\def\pgfmath@ensurenumberlength@#1{%
	\ifx\pgfmath@ensurenumberlength#1\relax%
		\expandafter\pgfmath@ensurenumberlength@@%
	\else%
		\advance\c@pgfmath@counta-1\relax%
		\expandafter\pgfmath@ensurenumberlength@
	\fi}

\def\pgfmath@ensurenumberlength@@{%
	\edef\pgfmath@tempb{\pgfmath@tempa}%
	\pgfmath@ensurenumberlength@@@}
\def\pgfmath@ensurenumberlength@@@{%
	\ifnum\c@pgfmath@counta>0\relax%
		\advance\c@pgfmath@counta-1\relax%
		\edef\pgfmath@tempb{0\pgfmath@tempb}%
		\expandafter\pgfmath@ensurenumberlength@@@%
	\fi%
	\expandafter\edef\pgfmath@tempa{\pgfmath@tempb}}
	
\def\pgfmathsetbasenumberlength#1{\def\pgfmath@basenumberlength{#1}}
\pgfmathsetbasenumberlength{1}%