%%
%% This is file `zeckendorf.tex',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% zeckendorf.dtx  (with options: `interactive')
%% 
%% IMPORTANT NOTICE:
%% 
%% For the copyright see the source file.
%% 
%% Any modified versions of this file must be renamed
%% with new filenames distinct from zeckendorf.tex.
%% 
%% For distribution of the original source see the terms
%% for copying and modification in the file zeckendorf.dtx.
%% 
%% This generated file may be distributed as long as the
%% original source files, as listed above, are part of the
%% same distribution. (The sources need not necessarily be
%% in the same archive or directory.)
%% ---------------------------------------------------------------
%% The zeckendorf package: Zeckendorf representation of big integers
%% Copyright (C) 2025 Jean-Francois Burnol
%%
\input zeckendorfcore.tex
\let\xintfirstoftwo\xint_firstoftwo
\let\xintsecondoftwo\xint_secondoftw
\let\zeckexprmapwithin\XINT:expr:mapwithin
\def\zeckNumbraced#1{{\xintNum{#1}}}
\xintexprSafeCatcodes

\let\ZeckShouldISayOrShouldIGo\iftrue
\def\ZeckCmdQ{\let\ZeckShouldISayOrShouldIGo\iffalse}
\let\ZeckCmdX\ZeckCmdQ
\let\ZeckCmdx\ZeckCmdQ
\let\ZeckCmdq\ZeckCmdQ

\newif\ifzeckphimode
\newif\ifzeckindices
\zeckindicestrue
\newif\ifzeckfromN
\zeckfromNtrue
\newif\ifzeckmeasuretimes
\newif\ifzeckevalonly
\newif\ifzeckhex

\def\ZeckCmdP{%
    \zeckphimodetrue
    \ifzeckindices\ZeckCmdL\else\Zeck@CmdB\fi
}
\let\ZeckCmdp\ZeckCmdP
\def\ZeckCmdZ{%
    \zeckphimodefalse
    \ifzeckindices\ZeckCmdL\else\Zeck@CmdB\fi
}
\let\ZeckCmdz\ZeckCmdZ

\def\PhiTypesetXPrint #1#2{a=#1, b=#2}
\def\ZeckCmdL{%
    \zeckindicestrue
    \ifzeckphimode
      \def\ZeckFromN{\PhiExponents}%
      \def\ZeckToN##1{\PhiTypesetX{\PhiXfromExponents{##1}}}%
    \else
      \def\ZeckFromN{\ZeckIndices}%
      \def\ZeckToN{\ZeckNFromIndices}%
    \fi
}
\let\ZeckCmdl\ZeckCmdL

\def\ZeckCmdB{%
    \zeckindicesfalse
    \zeckhexfalse
    \Zeck@CmdB
}
\def\Zeck@CmdB{%
    \ifzeckphimode
      \ifzeckhex
        \def\ZeckFromN{\PhiBaseHexPhi}%
        \def\ZeckToN##1{\PhiTypesetX{\PhiXfromBaseHexPhi{##1}}}%
      \else
        \def\ZeckFromN{\PhiBasePhi}%
        \def\ZeckToN##1{\PhiTypesetX{\PhiXfromBasePhi{##1}}}%
      \fi
    \else
      \ifzeckhex
        \def\ZeckFromN{\ZeckHexWord}%
        \def\ZeckToN{\ZeckNfromHexWord}%
      \else
        \def\ZeckFromN{\ZeckWord}%
        \def\ZeckToN{\ZeckNfromWord}%
      \fi
    \fi
}
\let\ZeckCmdW\ZeckCmdB
\let\ZeckCmdb\ZeckCmdB
\let\ZeckCmdw\ZeckCmdB

\def\ZeckCmdC{%
    \zeckindicesfalse
    \zeckhextrue
    \Zeck@CmdB
}
\let\ZeckCmdc\ZeckCmdC

\def\ZeckConvert{%
    \csname Zeck\ifzeckfromN From\else To\fi N\endcsname
}
\def\ZeckCmdT{\ifzeckfromN\zeckfromNfalse\else\zeckfromNtrue\fi}
\let\ZeckCmdt\ZeckCmdT

\expandafter\def\csname ZeckCmd@\endcsname{%
  \ifdefined\xinttheseconds
      \ifzeckmeasuretimes\zeckmeasuretimesfalse
          \else          \zeckmeasuretimestrue
      \fi
  \else
      \immediate\write128{Sorry, this requires xintexpr 1.4n or later.}%
  \fi
}

\def\ZeckCmdE{\ifzeckevalonly\zeckevalonlyfalse\else\zeckevalonlytrue\fi}
\let\ZeckCmde\ZeckCmdE

\def\ZeckCmdH{\immediate\write128{\ZeckHelpPanel}}
\let\ZeckCmdh\ZeckCmdH

\ZeckCmdL

\def\ZeckCommands{Enter input or command
                  (q, z, p, l, w, b, c, t, e, @, or h for help).}
\def\ZeckPrompt{%
  \ifzeckevalonly
    <<<Eval-only (e to quit)>>>^^J%
    [IN] expression =
  \else
   \ifzeckfromN
    \ifzeckphimode
      \ifzeckindices <convert to Bergman phi-exponents>^^J%
      \else
        \ifzeckhex
                   <convert to Bergman hexphi-representation>^^J%
        \else
                   <convert to Bergman phi-representation>^^J%
        \fi
      \fi
      \ZeckCommands^^J
      [IN] a + b phi =
    \else
      \ifzeckindices <convert to Zeckendorf indices>^^J%
      \else
        \ifzeckhex
                     <convert to Zeckendorf hex-word>^^J%
        \else
                     <convert to Zeckendorf word>^^J%
        \fi
      \fi
      \ZeckCommands^^J
      [IN] N =
    \fi
   \else
    \ifzeckphimode <convert to a + b phi>^^J
      \ZeckCommands^^J
      [IN]
       \ifzeckindices phi exponents =
       \else
         \ifzeckhex
                   hexphi-representation =
         \else
                      phi-representation =
         \fi
       \fi
    \else          <convert to integer>^^J
      \ZeckCommands^^J
      [IN]
       \ifzeckindices indices =
       \else
         \ifzeckhex
                      hex word =
         \else
                      binary word =
         \fi
       \fi
    \fi
   \fi
  \fi
}
\newlinechar10
\immediate\write128{}
\immediate\write128{Welcome to Zeckendorf 0.9d (2025/11/16, JFB).}

\def\ZeckHelpPanel{Commands (lowercase also):^^J
 Q to quit. Also X.^^J
 H for this help.^^J
 Z to switch to Zeckendorf-mode (starting default).^^J
 P to switch to phi-mode.^^J
 L for indices or exponents.^^J
 W for binary words or reps. Also B.^^J
 C for hexadecimal words or reps.^^J
 T to toggle the direction of conversions.^^J
 E to toggle to and from  \string\xinteval-only mode.^^J
 @ to toggle measurement of execution times.^^J
^^J
 - binary words, phi-representations, are parsed only by \string\edef.^^J
 - all other inputs are handled by \noexpand\xinteval so for example one^^J
\space\space
   can use 2^100 or 100! or binomial(100,50).  And a list of indices^^J
\space\space
   or exponents can be for example seq(3*a+1, a=0..10).^^J
^^J
\space\space The fib() function computes Fibonacci numbers.^^J
\space\space The character $ serves as symbol for Knuth multiplication.^^J%
**** empty input is not supported!
     no linebreaks in input! ****}

\immediate\write128{\ZeckHelpPanel}

\def\zeckpar{\par}
\long\def\xintbye#1\xintbye{}
\long\def\zeckgobbleii#1#2{}
\long\def\zeckfirstoftwo#1#2{#1}
\def\zeckonlyonehelper #1#2#3%
    \zeckonlyonehelper{\xintbye#2\zeckgobbleii\xintbye0}

\xintFor*#1 in {0123456789}\do{%
   \expandafter\def\csname ZeckCmd#1\endcsname{%
      \immediate\write128{%
** Due to under-funding, a lone #1 is not accepted. Inputs must have^^J%
** two characters at least.  Think about a donation? Try 0#1.}}
}%
\xintloop
\message{\ZeckPrompt}
\read-1to\zeckbuf
\ifx\zeckbuf\zeckpar
  \immediate\write128{**** empty input is not supported, please try again.}
\else
  \edef\zeckbuf{\zeckbuf}
  \if 1\expandafter\zeckonlyonehelper\zeckbuf\xintbye\zeckonlyonehelper1%
   \ifcsname ZeckCmd\expandafter\zeckfirstoftwo\zeckbuf\relax\endcsname
     \csname ZeckCmd\expandafter\zeckfirstoftwo\zeckbuf\relax\endcsname
   \else
     \immediate\write128{%
     **** Unrecognized command letter
          \expandafter\zeckfirstoftwo\zeckbuf\relax. Try again.^^J}
   \fi
  \else
   \ifzeckmeasuretimes\xintresettimer\fi
   \if1\ifzeckevalonly0\fi\ifzeckfromN0\fi\ifzeckindices0\fi1%
      \edef\ZeckIn{{\zeckbuf}}%
   \else
      \expandafter\def\expandafter\ZeckIn\expandafter{%
      \romannumeral0\xintbareeval\zeckbuf\relax}%
      \ifzeckevalonly\else
         \expandafter\def\expandafter\ZeckIn
           \expanded
           \expandafter\zeckexprmapwithin
           \expandafter\zeckNumbraced\ZeckIn
         \ifzeckfromN\else
            \expandafter\def\expandafter\ZeckIn\expandafter{%
              \expandafter{\romannumeral0\xintlistwithsep,\ZeckIn}%
            }%
         \fi
      \fi
   \fi
   \immediate\write128{%
     [OUT] \ifzeckevalonly
       \expanded\expandafter\XINTexprprint\expandafter.\ZeckIn
     \else
       \expandafter\ZeckConvert\ZeckIn
     \fi
   }%
   \ifzeckmeasuretimes
     \edef\tmp{\xinttheseconds}%
     \immediate\write128{%
        \ifzeckevalonly Evaluation \else Conversion \fi
        took \tmp s%
     }%
   \fi
  \fi
\fi
\ZeckShouldISayOrShouldIGo
\repeat

\immediate\write128{Bye. Session was saved to log file (hard-wrapped too, alas).}
\bye
\endinput
%%
%% End of file `zeckendorf.tex'.
