%%
%% This is file `kvmap.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% kvmap.dtx  (with options: `pkg,cfg')
%% Copyright (C) 2018 Ben Frank
%% 
%% It may be distributed and/or modified under the conditions of
%% the LaTeX Project Public License (LPPL), either version 1.3c of
%% this license or (at your option) any later version.  The latest
%% version of this license is in the file:
%% 
%%    http://www.latex-project.org/lppl.txt
%% 
\RequirePackage{expl3}
\ProvidesExplPackage{kvmap}{2018/09/20}{0.3.1}{Drawing karnaugh maps with LaTeX}
\RequirePackage{xparse}
\RequirePackage{tikz}
\RequirePackage{environ}
\cs_generate_variant:Nn \seq_set_split:Nnn   { Nno, Nnx }
\cs_generate_variant:Nn \int_mod:nn          { VV       }
\cs_generate_variant:Nn \int_div_truncate:nn { VV       }

\cs_new:Npn \__kvmap_graycode_xor_bits:nn #1#2
  {
    \int_compare:nTF { #1 = #2 }
      { 0 } { 1 }
  }
\cs_new:Npn \__kvmap_graycode_xor:w #1#2\q_stop#3#4\q_stop
  {
    \__kvmap_graycode_xor_bits:nn { #1 } { #3 }
    \tl_if_empty:nF { #2 }
      {
        \__kvmap_graycode_xor:w #2\q_stop#4\q_stop
      }
  }
\cs_new:Npn \__kvmap_graycode_xor:nn #1#2
  {
    \__kvmap_graycode_xor:w #1\q_stop#2\q_stop
  }
\cs_generate_variant:Nn \__kvmap_graycode_xor:nn { xx }

\cs_new:Npn \kvmap_graycode_at:nn #1#2
{
    \__kvmap_graycode_xor:xx
      { \tl_tail:f { \int_to_bin:n { #1 - 1 + #2 } } }
      { \tl_tail:f { \int_to_bin:n { \fp_eval:n { floor((#1-1)/2) + #2 } } } }
}
\cs_generate_variant:Nn \kvmap_graycode_at:nn { nV }

\bool_new:N \l__kvmap_matrix_isintikz_bool
\int_new:N \l__kvmap_matrix_height_int
\int_new:N \l__kvmap_matrix_width_int
\cs_new:Nn \__kvmap_outputgraycode:
  {
    \int_step_inline:nnnn { 1 } { 1 } { \l__kvmap_matrix_width_int }
      {
\node ~ at ~ (\fp_eval:n { 0.5 + (##1-1) }, .3)
{ \kvmap_graycode_at:nV { ##1 } \l__kvmap_matrix_width_int };
      }
    \int_step_inline:nnnn { 1 } { 1 } { \l__kvmap_matrix_height_int }
      {
\node[anchor = east] ~ at ~ (0, \fp_eval:n { -0.5 - (##1-1) })
{ \kvmap_graycode_at:nV { ##1 } \l__kvmap_matrix_height_int };
      }
  }

\tikzset{kvnode/.style = { inner ~ sep = 8pt }}
\cs_new:Npn \__kvmap_outputmatrix:n #1
{
\int_zero:N \l_tmpa_int
\seq_set_from_clist:Nn \l_tmpa_seq { #1 }
\seq_map_inline:Nn \l_tmpa_seq
{
\node[kvnode] ~
(\int_mod:VV \l_tmpa_int \l__kvmap_matrix_width_int
                    \int_div_truncate:VV \l_tmpa_int \l__kvmap_matrix_width_int ) ~
at ~
(.5+\int_mod:VV \l_tmpa_int \l__kvmap_matrix_width_int,
                -.5-\int_div_truncate:nn \l_tmpa_int \l__kvmap_matrix_width_int ) ~
{$##1$};
\int_incr:N \l_tmpa_int
}
}

\keys_define:nn { kvmap/bundle }
{
reducespace    .dim_set:N      = \l__kvmap_bundle_reducespace_dim,
reducespace    .initial:n      = { 0pt },
color          .tl_set:N       = \l__kvmap_bundle_color_tl,
color          .initial:n      = { black },
invert         .bool_set:N     = \l__kvmap_bundle_invert_bool,
invert         .default:n      = true,
invert         .initial:n      = false,
overlapmargins .dim_set:N      = \l__kvmap_bundle_overlapmargins_dim,
overlapmargins .initial:n      = { 0pt },
}
\tikzset{kvbundle/.style = { rounded ~ corners = 5pt }}
\int_new:N \l__kvmap_bundle_minx_int
\int_new:N \l__kvmap_bundle_miny_int
\int_new:N \l__kvmap_bundle_maxx_int
\int_new:N \l__kvmap_bundle_maxy_int
\NewDocumentCommand { \bundle } { O{} m m m m }
{
\group_begin:
\keys_set:nn { kvmap/bundle } { #1 }
\int_set:Nn \l__kvmap_bundle_minx_int { \int_min:nn { #2 } { #4 } }
\int_set:Nn \l__kvmap_bundle_miny_int { \int_min:nn { #3 } { #5 } }
\int_set:Nn \l__kvmap_bundle_maxx_int { \int_max:nn { #2 } { #4 } }
\int_set:Nn \l__kvmap_bundle_maxy_int { \int_max:nn { #3 } { #5 } }
\bool_if:NTF \l__kvmap_bundle_invert_bool
{
\bool_if:nT
{
\int_compare_p:n { \l__kvmap_matrix_height_int - 1 = \l__kvmap_bundle_maxy_int }
&& \int_compare_p:n { 0 = \l__kvmap_bundle_miny_int }
}
{
\draw[draw=\l__kvmap_bundle_color_tl,kvbundle] ~
([xshift=\l__kvmap_bundle_reducespace_dim,
yshift=\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ west) --
([xshift=\l__kvmap_bundle_reducespace_dim,
yshift=\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_miny_int . south ~ west) --
([xshift=-\l__kvmap_bundle_reducespace_dim,
yshift=\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_miny_int . south ~ east) --
([xshift=-\l__kvmap_bundle_reducespace_dim,
yshift=\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ east);
\draw[draw=\l__kvmap_bundle_color_tl,kvbundle] ~
([xshift=\l__kvmap_bundle_reducespace_dim,
yshift=-\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ west) --
([xshift=\l__kvmap_bundle_reducespace_dim,
yshift=-\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_maxy_int . north ~ west) --
([xshift=-\l__kvmap_bundle_reducespace_dim,
yshift=-\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_maxy_int . north ~ east) --
([xshift=-\l__kvmap_bundle_reducespace_dim,
yshift=-\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ east);
}
\bool_if:nT
{
\int_compare_p:n { \l__kvmap_matrix_width_int - 1 = \l__kvmap_bundle_maxx_int }
&& \int_compare_p:n { 0 = \l__kvmap_bundle_minx_int }
}
{
\draw[draw=\l__kvmap_bundle_color_tl,kvbundle] ~
([yshift=-\l__kvmap_bundle_reducespace_dim,
xshift=-\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ west) --
([yshift=-\l__kvmap_bundle_reducespace_dim,
xshift=-\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ east) --
([yshift=\l__kvmap_bundle_reducespace_dim,
xshift=-\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ east) --
([yshift=\l__kvmap_bundle_reducespace_dim,
xshift=-\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ west);
\draw[draw=\l__kvmap_bundle_color_tl,kvbundle] ~
([yshift=-\l__kvmap_bundle_reducespace_dim,
xshift=\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ east) --
([yshift=-\l__kvmap_bundle_reducespace_dim,
xshift=\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ west) --
([yshift=\l__kvmap_bundle_reducespace_dim,
xshift=\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ west) --
([yshift=\l__kvmap_bundle_reducespace_dim,
xshift=\l__kvmap_bundle_overlapmargins_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ east);
}
}
{
\draw[draw=\l__kvmap_bundle_color_tl, kvbundle] ~
([xshift=\l__kvmap_bundle_reducespace_dim,
yshift=-\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_minx_int
\int_use:N \l__kvmap_bundle_miny_int . north ~ west) ~
rectangle ~
([xshift=-\l__kvmap_bundle_reducespace_dim,
yshift=\l__kvmap_bundle_reducespace_dim]
\int_use:N \l__kvmap_bundle_maxx_int
\int_use:N \l__kvmap_bundle_maxy_int . south ~ east);
}
\group_end:
}
\cs_new:Npn \kvmap_map:nn #1#2
{
\draw ~ (0,0) ~ grid ~
(\int_use:N \l__kvmap_matrix_width_int, -\int_use:N \l__kvmap_matrix_height_int);
\__kvmap_outputmatrix:n  { #1 }
\__kvmap_outputgraycode:
\draw ~ (0,0) ~ -- ~ (-.7,.7);
\int_set:Nn \l_tmpa_int
{ \fp_eval:n { floor(ln(\l__kvmap_matrix_width_int)/ln(2)) }  }
\tl_clear:N \l_tmpa_tl
\int_step_inline:nnnn { 1 } { 1 } { \l_tmpa_int }
{
 \tl_put_right:Nn \l_tmpa_tl { \clist_item:nn { #2 } { ##1 } }
}
\node[anchor = west] ~ at ~ (-.5, .7) ~ { $\tl_use:N \l_tmpa_tl$ };
\tl_clear:N \l_tmpa_tl
\int_step_inline:nnnn { \l_tmpa_int + 1 } { 1 }
{ \l_tmpa_int + \fp_eval:n { floor(ln(\l__kvmap_matrix_height_int)/ln(2)) } }
{
 \tl_put_right:Nn \l_tmpa_tl { \clist_item:nn { #2 } { ##1 } }
}
\node[anchor = east] ~ at ~ (-.4, .2) ~ { $\tl_use:N \l_tmpa_tl$ };
}
\cs_generate_variant:Nn \kvmap_map:nn { xn }

\NewDocumentEnvironment { kvmap } { O{} }
{
\group_begin:
\keys_set:nn { kvmap } { #1 }
\int_gzero:N \l__kvmap_matrix_height_int
\int_gzero:N \l__kvmap_matrix_width_int
\begin{tikzpicture}
}
{
\end{tikzpicture}
\group_end:
}
\NewDocumentCommand { \kvlist } { m m m m }
{
\tikzifinpicture
{ \bool_set_true:N  \l__kvmap_matrix_isintikz_bool }
{ \bool_set_false:N \l__kvmap_matrix_isintikz_bool }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \begin{tikzpicture} }
\int_gset:Nn \l__kvmap_matrix_width_int  { #1 }
\int_gset:Nn \l__kvmap_matrix_height_int { #2 }
\kvmap_map:nn { #3 } { #4 }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \end{tikzpicture} }
}

\seq_new:N \l__kvmap_tmp_seq
\NewEnviron { kvmatrix } [ 1 ]
{
\seq_set_split:Nno \l_tmpa_seq { \\ } { \BODY }
\seq_remove_all:Nn \l_tmpa_seq { }
\seq_set_split:Nnx \l_tmpb_seq { & } { \seq_item:Nn \l_tmpa_seq { 1 } }
\seq_remove_all:Nn \l_tmpb_seq { }
\int_gset:Nn \l__kvmap_matrix_width_int  { \seq_count:N \l_tmpb_seq }
\int_gset:Nn \l__kvmap_matrix_height_int { \seq_count:N \l_tmpa_seq }
\seq_clear:N \l__kvmap_tmp_seq
\seq_map_inline:Nn \l_tmpa_seq
{
\seq_clear:N \l_tmpb_seq
\seq_set_split:Nnn \l_tmpb_seq { & } { ##1 }
\seq_concat:NNN \l__kvmap_tmp_seq \l__kvmap_tmp_seq \l_tmpb_seq
}
\tikzifinpicture
{ \bool_set_true:N  \l__kvmap_matrix_isintikz_bool }
{ \bool_set_false:N \l__kvmap_matrix_isintikz_bool }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \begin{tikzpicture} }
\kvmap_map:xn
{ \seq_use:Nnnn \l__kvmap_tmp_seq { , } { , } { , } }
{ #1                  }
\bool_if:NF \l__kvmap_matrix_isintikz_bool
{ \end{tikzpicture}   }
}

\NewDocumentCommand { \kvmapsetup } { m }
{
\keys_set:nn { kvmap } { #1 }
}
%% 
%%
%% End of file `kvmap.sty'.
