Show logical calculations

For my students, I'd like a macro to show logical calculations bit by bit ( AND, OR, XOR ) between two numbers in base b ( b integer from 2 to 36) .

Parameters would be number1, number2 and b; number1, number2 are written in base b; The macro translate number1 and number2 in binary, then presents the calculus as shown in pictures below:

Has anyone made this?

Xavier .

Quite fun to program. :-)

\documentclass{article}
\usepackage{xparse,booktabs}

\ExplSyntaxOn
\NewDocumentCommand{\showbitwiseand}{mm}
{
\bitwise_show:Nnnn \bitwise_and:nnn { #1 } { #2 } { AND }
}
\NewDocumentCommand{\showbitwiseor}{mm}
{
\bitwise_show:Nnnn \bitwise_or:nnn { #1 } { #2 } { OR }
}
\NewDocumentCommand{\showbitwisexor}{mm}
{
\bitwise_show:Nnnn \bitwise_xor:nnn { #1 } { #2 } { XOR }
}

\NewDocumentCommand{\bitwiseand}{mm}
{
\bitwise_compute:Nnnn \bitwise_and:nnn { #1 } { #2 } { AND }
}
\NewDocumentCommand{\bitwiseor}{mm}
{
\bitwise_compute:Nnnn \bitwise_or:nnn { #1 } { #2 } { OR }
}
\NewDocumentCommand{\bitwisexor}{mm}
{
\bitwise_compute:Nnnn \bitwise_xor:nnn { #1 } { #2 } { XOR }
}

\cs_new_protected:Nn \bitwise_show:Nnnn
{
\ensuremath
{
#1 { #2 } { #3 } { 0 }
\begin{array}{r@{}l}
\lbrack\int_to_bin:n { #2 }\rbrack & \sb{2} \\
\lbrack\int_to_bin:n { #3 }\rbrack & \sb{2} \\
\midrule
\lbrack\l__bitwise_out_tl\rbrack & \sb{2} \\
\multicolumn{2}{l}{#2 \mathbin{\mathrm{#4}} #3 = \l__bitwise_decimal_tl}
\end{array}
}
}

\cs_new_protected:Nn \bitwise_compute:Nnnn
{
#2 \mathbin{\mathrm{#4}} #3 = #1 { #2 } { #3 } { 1 }
}

\tl_new:N \l__bitwise_first_tl
\tl_new:N \l__bitwise_second_tl
\tl_new:N \l__bitwise_out_tl
\tl_new:N \l__bitwise_decimal_tl
\int_new:N \l__bitwise_log_int

\cs_new_protected:Nn \bitwise_and:nnn
{
\__bitwise_set:nn { #1 } { #2 }
\__bitwise_generic:N \__bitwise_and:n
\__bitwise_normalize:
\int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
}
\cs_new_protected:Nn \bitwise_or:nnn
{
\__bitwise_set:nn { #1 } { #2 }
\__bitwise_generic:N \__bitwise_or:n
\__bitwise_normalize:
\int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
}
\cs_new_protected:Nn \bitwise_xor:nnn
{
\__bitwise_set:nn { #1 } { #2 }
\__bitwise_generic:N \__bitwise_xor:n
\__bitwise_normalize:
\int_compare:nF { #3 = 0 } { \l__bitwise_decimal_tl }
}

\cs_new_protected:Nn \__bitwise_generic:N
{
\int_step_function:nnnN { 1 } { 1 } { \l__bitwise_log_int } #1
}

\cs_new_protected:Npn \__bitwise_normalize:
{
\tl_reverse:N \l__bitwise_out_tl
\tl_set:Nx \l__bitwise_decimal_tl { \int_from_bin:V \l__bitwise_out_tl }
\tl_set:Nx \l__bitwise_out_tl { \int_to_bin:V \l__bitwise_decimal_tl }
}
\cs_generate_variant:Nn \int_to_bin:n { V }
\cs_generate_variant:Nn \int_from_bin:n { V }

\cs_new_protected:Nn \__bitwise_and:n
{
\tl_put_right:Nx \l__bitwise_out_tl
{
\int_eval:n
{
\tl_item:Nn \l__bitwise_first_tl { #1 }
*
\tl_item:Nn \l__bitwise_second_tl { #1 }
}
}
}

\cs_new_protected:Nn \__bitwise_or:n
{
\tl_put_right:Nx \l__bitwise_out_tl
{
\int_eval:n
{
\int_min:nn { 1 }
{
\tl_item:Nn \l__bitwise_first_tl { #1 }
+
\tl_item:Nn \l__bitwise_second_tl { #1 }
}
}
}
}

\cs_new_protected:Nn \__bitwise_xor:n
{
\tl_put_right:Nx \l__bitwise_out_tl
{
\int_eval:n
{
\int_if_odd:nTF
{
\tl_item:Nn \l__bitwise_first_tl { #1 }
+
\tl_item:Nn \l__bitwise_second_tl { #1 }
}
{ 1 } { 0 }
}
}
}

\cs_new_protected:Nn \__bitwise_set:nn
{
\tl_clear:N \l__bitwise_out_tl
% make the binary representations
\tl_set:Nx \l__bitwise_first_tl { \int_to_bin:n { #1 } }
\tl_set:Nx \l__bitwise_second_tl { \int_to_bin:n { #2 } }
% reverse the token lists
\tl_reverse:N \l__bitwise_first_tl
\tl_reverse:N \l__bitwise_second_tl
% make them equal length
\int_compare:nNnTF { \tl_count:N \l__bitwise_first_tl } > { \tl_count:N \l__bitwise_second_tl }
{
\tl_put_right:Nx \l__bitwise_second_tl
{
\prg_replicate:nn { \tl_count:N \l__bitwise_first_tl - \tl_count:N \l__bitwise_second_tl } { 0 }
}
}
{
\tl_put_right:Nx \l__bitwise_first_tl
{
\prg_replicate:nn { \tl_count:N \l__bitwise_second_tl - \tl_count:N \l__bitwise_first_tl } { 0 }
}
}
\int_set:Nn \l__bitwise_log_int { \tl_count:N \l__bitwise_first_tl }
}
\ExplSyntaxOff

\begin{document}

$\showbitwiseand{93}{208} \qquad \showbitwiseor{93}{208} \qquad \showbitwisexor{93}{208}$

In line:
\begin{itemize}
\item $\bitwiseand{93}{208}$
\item $\bitwiseor{93}{208}$
\item $\bitwisexor{93}{208}$
\end{itemize}

\end{document} • Very fun! Thanks a lot! And if I want EB6 AND 48A ( with entry in base 16 )? Or if I want XYZ4 OR 48AT in base 36? Does it work? – Xavier ANSIAUX Feb 21 '18 at 16:11
• @XavierANSIAUX That's a not really difficult variation, I think. – egreg Feb 21 '18 at 16:12
• @XavierANSIAUX Not so easy, after all. – egreg Feb 21 '18 at 17:49
• I tested your macro, and it works fine! Thanks a lot! – Xavier ANSIAUX Feb 23 '18 at 21:04