%% This is the package dsptricks
%%
%% (c) Paolo Prandoni <paolo.prandoni _at_ epfl.ch>
%%
%% This program can be redistributed and/or modified under the terms
%% of the LaTeX Project Public License Distributed from CTAN archives
%% in directory macros/latex/base/lppl.txt.
%%
%% DESCRIPTION:
%%   `dsptricks' is a LaTeX package based on PSTricks to plot discrete- and continuous-time
%%       signals, pole-zero plots and DSP block diagrams. The package has been developed
%%       while writing the textbook "Signal Processing for Communication" by P. Prandoni
%%       and M. Vetterli, freely available at www.sp4comm.org
%%
%% v1.1, November 2023
%%
\RequirePackage{pstricks}
\RequirePackage{pstricks-add}
\RequirePackage{pst-xkey}
\RequirePackage{calc}
\RequirePackage{fp}
\RequirePackage{ifthen}
%
\ProvidesPackage{dsptricks}[2023/11/08 package for signal processing graphics]

% turn off FP messages
\FPmessagesfalse

\makeatletter

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Sizes and units:
%%
%% default values for plot size
%%
\newlength{\dspWidth}\setlength{\dspWidth}{0.7\textwidth}
\newlength{\dspHeight}\setlength{\dspHeight}{0.43\dspWidth}
\def\dspAxisColor{black}
%
%% Actual size (this is the size of the chart's frame, labels are extra)
\newlength{\dspW}
\newlength{\dspH}
%% Basic Unit is a function of plot size
\newlength{\dspBU}
%% Derived units:
\newlength{\dspLineWidth}
\newlength{\dspStemWidth}
\newlength{\dspDotSize}
\newlength{\dspTickLen}
\newlength{\dspXTickGap}
\newlength{\dspYTickGap}
\newlength{\dspTickLineWidth}
\newlength{\dspFrameLineWidth}
%% psTricks units
\newlength{\dspUnitX}
\newlength{\dspUnitY}
\newlength{\dspTmpLen}
%% booleans
\newif\ifXTicks
\newif\ifDoXTicks
\newif\ifYTicks
\newif\ifDoYTicks
\newif\ifXLabel
\newif\ifYLabel
\newif\ifXAxisExp
\newif\ifYAxisExp
\newif\ifXAxisFreq
\newif\ifXInside

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% dspPlot environment:
%%
%% \begin{dspPlot}[OPTIONS]{xMin, xMax}{yMin, yMAx}
%%
%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Keys for data plots :
%%
\define@key{dspDP}{width}{\setlength{\dspW}{#1}}
\define@key{dspDP}{height}{\setlength{\dspH}{#1}}
\define@key{dspDP}{xlabel}{\def\dspXLabel{#1}\XLabeltrue}
\define@key{dspDP}{ylabel}{\def\dspYLabel{#1}\YLabeltrue}
\define@key{dspDP}{rlabel}{\def\dspYLabelR{#1}\YLabeltrue} % right-side y-axis label
\define@key{dspDP}{sidegap}{\def\sg{#1}}
\define@choicekey*+{dspDP}{xtype}[\ll\ln]{time,freq}[time]{%
 \ifcase\ln\relax
   \XAxisFreqfalse
 \or
   \XAxisFreqtrue
 \fi}{}
\define@choicekey*+{dspDP}{xticks}[\ll\ln]{auto,none,custom}[auto]{%
 \DoXTickstrue\XTickstrue\def\incX{-1}\def\piFrac{2}
 \ifcase\ln\relax
   \relax
 \or
   \DoXTicksfalse\XTicksfalse
 \or
   \DoXTicksfalse
 \fi}{%
 \DoXTickstrue\XTickstrue
 \def\incX{#1}\def\piFrac{#1}}
\define@choicekey*+{dspDP}{yticks}[\ll\ln]{auto,none,custom}[auto]{%
 \DoYTickstrue\YTickstrue\def\incY{-1}
 \ifcase\ln\relax
   \relax
 \or
   \DoYTicksfalse\YTicksfalse
 \or
   \DoYTicksfalse
 \fi}{%
 \DoYTickstrue\YTickstrue
 \def\incY{#1}}
\newif\ifXTicksOut
\define@key{dspDP}{xout}{\XTicksOuttrue}
\define@key{dspDP}{inticks}{\XInsidetrue}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% dspPlot environment
%%
\newenvironment{dspPlot}[3][]{%
% default values
 \def\dspXlabel{}\XLabelfalse%
 \def\dspYLabel{}\def\dspYLabelR{}\YLabelfalse%
 \XAxisFreqfalse%
 \XTicksOutfalse%
 \setlength{\dspW}{\dspWidth}\setlength{\dspH}{\dspHeight}%

 \presetkeys{dspDP}{xticks=auto,yticks=auto}{}%
 \presetkeys{dspDP}{sidegap=-1}{}%
 \setkeys{dspDP}{#1}%
%%
%% set up
 \ifXAxisFreq\def\sg{0} \fi%
 \dspSetDims#2,#3,\sg\relax%
 \dspSetupAxes
%%
%% special x-axis for frequency plots
 \ifXAxisFreq\FPset\incX{1}%
   \ifXAxisExp%
     % x-axis is not on bottom; skip last values
     \FPupn\stX{\dspMinX{} \piFrac{} * 1 + 0 trunc}%
     \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 0 trunc}%
   \else%
     \FPupn\stX{\dspMinX{} \piFrac{} * 0 trunc}%
     \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 1 + 0 trunc}\relax\fi%
   %
   \ifXTicksOut% undo above if ticks explicitly out
     \FPupn\stX{\dspMinX{} \piFrac{} * 0 trunc}%
     \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 1 + 0 trunc}\relax\fi
   %
   \def\thisTickX##1{%
     \FPupn\u{\piFrac{} ##1 /}%
     \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\u,\haY)(\u,\tickEndX)}
   \def\thisTickLabelX##1##2{%
     \FPupn\u{\piFrac{} ##1 /}%
     \rput*[B]{{0}}(\u,\tickTxtX){{\simplifyPiFrac{##1}{\piFrac}}}}%
 \else
   \def\thisTickX{\dspTickX}\def\thisTickLabelX{\dspTickLabelX}\relax\fi
%%
%% start the plot
 \begin{pspicture}(\LX,\BY)(\RX,\TY)
   %\showpointstrue
   %\psframe[dimen=middle,linewidth=1pt,linecolor=red](\LX,\BY)(\RX,\TY)%
   \ifXAxisExp\psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](\dspMinX,0)(\dspMaxX,0)\fi
   \dspPlotFrame
%%
%% draw ticks selectively according to user options
   \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\thisTickX{\n}}\fi
   \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickY{\n}}\fi
}{%
%% tick labels
   \psset{xunit=\dspUnitX,yunit=\dspUnitY} %user may have changed those
   \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\thisTickLabelX{\n}{$\n$}}\fi
   \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickLabelY{\n}{$\n$}}\fi
   \dspLabels
\end{pspicture}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Custom ticks
%%
%% \dspCustomTicks[axis={x|y}]{value label ...}
%%
%% if using macros for values, enclose them in curly braces:
%% \def\a{1 }
%% \dspCustomTicks{{\a} 1}
%%
\define@choicekey*{dspCT}{axis}[\ll\ln]{x,y,ry}[x]{%
 \def\dspCA{\ln}}
\define@key{dspCT}{color}{\def\tickColor{#1}}
\newcommand{\dspCustomTicks}[2][]{%
 \presetkeys{dspCT}{axis=x,color=black}{}%
 \setkeys{dspCT}{#1}%
 \ifcase\dspCA\relax%
   \def\dspMkTk##1##2{\dspTickX{##1}{\dspTickLabelX{##1}{##2}}}%
 \or
   \def\dspMkTk##1##2{\dspTickY{##1}{\dspTickLabelY{##1}{##2}}}%
 \or
   \def\dspMkTk##1##2{{\dspTickLabelYR{##1}{##2}}}%
 \fi
 \def\dspMakeTicks##1 ##2 ##3\relax{%
   \ifx\relax##3\relax
     \dspMkTk{##1}{##2} %
   \else
    \dspMkTk{##1}{##2} \relax %
     \dspMakeTicks##3\relax%
   \fi}%
   \dspMakeTicks#2 \relax}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Draw legend
%%
%% \dspLegend(x,y){color label color label ...}
%%
\def\dspLegend(#1,#2)#3{%
 \rput[lt](#1,#2){\fbox{%
   \begin{tabular}{ll}
     \@dsplegend#3 \@empty
   \end{tabular}}}}
\def\@dsplegend#1 #2 #3{%
  {\color{#1}\rule[0.5ex]{2em}{2pt}} & #2\\ \space  % fbox here to have a visual test
  \ifx #3\@empty\else
   \expandafter\@dsplegend
  \fi
  #3}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Redraw frame around plot
%%
\newcommand{\dspPlotFrame}{
 \psframe[dimen=middle,linewidth=\dspFrameLineWidth,linecolor=black]%
   (\dspMinX,\dspMinY)(\dspMaxX,\dspMaxY)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Environment to clip plots to within the frame box. Do not leave
%%  spaces in the environment's body otherwise graph will shift
%%
\newenvironment{dspClip}{%
 \psclip{\psframe[dimen=middle,linestyle=none](\dspMinX,\dspMinY)(\dspMaxX,\dspMaxY)}}{%
 \endpsclip}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plotting discrete-time signals in the  dspPlot environment:
%%
%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Keys for plotting functions (these are set together with pstricks keys
%%  so they must use the [psset] prefix and be declared)
%%
%%   xmin=N,
%%   xmax=N       range for the plotted signal
%%
\define@key[psset]{dspData}{xmin}{\def\dspXmin{#1}}
\define@key[psset]{dspData}{xmax}{\def\dspXmax{#1}}
\pst@addfams{dspData}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot discrete-time points
%%
%% \dspTaps[OPTIONS]{x1 y1 x2 y2 ...}
%%
\newcommand{\dspTaps}[2][]{%
 \listplot[plotstyle=LineToXAxis, linestyle=solid,%
   showpoints=true, dotstyle=*, linewidth=\dspStemWidth,%
   dotsize=\dspDotSize, #1]{\expandafter\m@keList#2 \relax}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot discrete-time points starting at a given abscissa
%% Data in this case is only ordinates
%%
%% \dspTapsAt{x0}{y0 y1 y2,...}
%%
\newcommand{\dspTapsAt}[3][]{%
 % use postscript to iterate over space-separated list and create indices
 \listplot[plotstyle=LineToXAxis, linestyle=solid,%
     showpoints=true, dotstyle=*, linewidth=\dspStemWidth,%
     dotsize=\dspDotSize, #1]{%
 #2
 [#3] {    % n []
           % n a0
   1 index % n a0 n
   1 add
 } forall
 pop
}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot discrete-time signal from a data file
%%
%% \dspTapsFile[OPTIONS]{FILE}
%%
\newcommand{\dspTapsFile}[2][]{%
 \readdata{\data}{#2}%
 \listplot[plotstyle=LineToXAxis, linestyle=solid,%
           showpoints=true, dotstyle=*,%
           linewidth=\dspStemWidth, dotsize=\dspDotSize,%
           #1]{\data}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot discrete-time signal
%%
%% \dspSignal[OPTIONS]{PS code}
%%
\newcommand{\dspSignal}[2][]{%
 \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}%
 \setkeys*[psset]{dspData}{#1}%
 \FPupn\mn{{\dspXmin} 0 trunc clip }%
 \FPupn\mx{{\dspXmax} 0 trunc clip }%
 \FPupn\ntaps{\mn{} \mx{} - 1 + 0 trunc clip}%
 \psplot[plotstyle=LineToXAxis, linestyle=solid,%
         showpoints=true, dotstyle=*,%
         linewidth=\dspStemWidth, dotsize=\dspDotSize,%
         plotpoints=\ntaps, #1]%
         {\mn}{\mx}{#2}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot discrete-time signal with postscript initialization options
%%
%\dspSignalOpt[OPTIONS]{PS init code}{PS code}
%%
\newcommand{\dspSignalOpt}[3][]{%
 \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}%
 \setkeys*[psset]{dspData}{#1}%
 \FPupn\ntaps{\dspXmin{} \dspXmax{} - 1 + 0 trunc}%
 \psplot[plotstyle=LineToXAxis, linestyle=solid,%
         showpoints=true, dotstyle=*,%
         linewidth=\dspStemWidth, dotsize=\dspDotSize,%
         plotpoints=\ntaps, #1]%
         {\dspXmin}{\dspXmax}[{#2}]{#3}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plotting continuous-time signals in the  dspPlot environment:
%%
%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot smooth function
%%
%% \dspFunc[OPTIONS]{PS code}
%%
\newcommand{\dspFunc}[2][]{%
 \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}%
 \setkeys*[psset]{dspData}{#1}%
 \psplot[linewidth=\dspLineWidth, plotpoints=\dspPSPoints,%
   linejoin=1,#1]{\dspXmin}{\dspXmax}{#2}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot smooth function with postscript initialization options
%%
%% \dspFuncOpt[OPTIONS]{PS init code}{PS code}
%%
\newcommand{\dspFuncOpt}[3][]{%
 \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}%
 \setkeys*[psset]{dspData}{#1}%
 \psplot[linewidth=\dspLineWidth, plotpoints=\dspPSPoints,%
   linejoin=1,#1]{\dspXmin}{\dspXmax}[{#2}]{#3}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot smooth function from a set of points
%%
%% \dspFuncData[OPTIONS]{x1 y1 x2 y2 ...}
%%
\newcommand{\dspFuncData}[2][]{%
 \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{\expandafter\m@keList#2 \relax}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot smooth function from a set of points starting at a given point
%% Data in this case is only ordinates
%%
%% \dspFuncDataAt[OPTIONS]{x1}{y1 y2 ...}
%%
\newcommand{\dspFuncDataAt}[3][]{%
 \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{%
 #2
 [#3] {    % n []
           % n a0
   1 index % n a0 n
   1 add
 } forall
 pop
}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot smooth function from a data file
%% file must contain a list of space-separated abscissa and ordinate pairs
%%
%% \dspFuncFile[OPTIONS]{FILE}
%%
\newcommand{\dspFuncFile}[2][]{%
 \readdata{\data}{#2}%
 \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{\data}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Plot Dirac deltas
%%
%% \dspDiracs[OPTIONS]{x1 y1 x2 y2 ...}
%%
\newcommand{\dspDiracs}[2][]{%
 \def\dirac##1##2{\psline[linestyle=solid,linewidth=\dspLineWidth,#1]{->}(! ##1 0)(! ##1 ##2)}
 \doOnPairs{dirac}{#2}}




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Periodize function over the [-1, 1] interval
%
\newcommand{\dspPeriod}[1]{ #1 sub #1 2 mul div dup floor sub #1 2 mul mul #1 sub }
\newcommand{\dspPeriodize}{ \dspPeriod{1} }
\newcommand{\dspMainPeriod}[1][]{%
 \psframe[linecolor=lightgray,linewidth=0.4pt,#1](-1,\dspMinY)(1,\dspMaxY)}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Plot text
% \dspText(x,y){text}
\newcommand{\dspText}[2]{%
 \rput*[B]{0}#1{#2}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Pole-Zero Plots
%
% Specialized options:
%
%   circle=["true" | "false"]  draw unit circle
%   clabel="text"  set a label at circle unit
%   roc
%
\define@key{dspPZ}{width}{\setlength{\dspW}{#1}\setlength{\dspH}{#1}}
\define@key{dspPZ}{height}{\setlength{\dspH}{#1}}
\define@key{dspPZ}{circle}{\def\dspCircle{#1}}
\define@key{dspPZ}{clabel}{\def\dspCircleLabel{#1}}
\define@choicekey*+{dspPZ}{xticks}[\ll\ln]{auto,none}[auto]{%
 \DoXTickstrue\def\incX{-1}
 \ifcase\ln\relax
   \relax
 \or
   \DoXTicksfalse
 \fi}{%
 \DoXTickstrue
 \def\incX{#1}}
\define@choicekey*+{dspPZ}{yticks}[\ll\ln]{auto,none}[auto]{%
 \DoYTickstrue\def\incY{-1}
 \ifcase\ln\relax
   \relax
 \or
   \DoYTicksfalse
 \fi}{%
 \DoYTickstrue
 \def\incY{#1}}
\newif\ifComplexLabels
\define@choicekey*{dspPZ}{cunits}[\ll\ln]{true,false}[true]{%
 \ifcase\ln\relax
   \ComplexLabelstrue
 \or
   \ComplexLabelsfalse
 \fi}
\define@key{dspPZ}{roc}{\def\PZCROC{#1}}
\define@key{dspPZ}{antiroc}{\def\PZAROC{#1}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newenvironment{dspPZPlot}[2][]{%
 \setlength{\dspW}{\dspHeight}\setlength{\dspH}{\dspHeight}%
 \ComplexLabelstrue%
 \presetkeys{dspPZ}{xticks=auto,yticks=auto,circle=1,clabel={ },roc=-1,antiroc=-1}{}%
 \setkeys{dspPZ}{#1}%
%
 %% set up
 \dspSetDims{-#2},{#2},{-#2},{#2},0\relax%
 \dspSetupAxes%
%
 \gdef\dspTickX##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,-\tickEndX)(##1,\tickEndX)}%
 \gdef\dspTickY##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](-\tickEndY,##1)(\tickEndY,##1)}%
 \gdef\dspTickLabelY##1##2{\uput{{2\dspYTickGap}}[0]{{0}}(\tickEndY,##1){{##2}}}%
 \gdef\dspTickLabelX##1##2{\rput[B]{{0}}(##1,\tickTxtX){{##2}}}%
%
 %% start the plot
 \begin{pspicture}(\LX,\BY)(\RX,\TY)
   \FPifpos\PZCROC%
     \pscustom[fillstyle=vlines,hatchcolor=lightgray,linecolor=lightgray,linewidth=0]{%
     \psarc(0,0){\PZCROC\dspUnitX}{0}{360}%
     \psline[linecolor=\dspAxisColor](\dspMaxX,0)(\dspMaxX,\dspMinY)(\dspMinX,\dspMinY)%
       (\dspMinX,\dspMaxY)(\dspMaxX,\dspMaxY)(\dspMaxX,0)}
     \pscircle[linecolor=lightgray,dimen=middle]{\PZCROC\dspUnitX}\relax\fi
   \FPifpos\PZAROC%
     \pscircle[fillstyle=vlines,hatchcolor=lightgray,linecolor=lightgray,dimen=middle]{\PZAROC\dspUnitX}\relax\fi
%%
   \psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](\dspMinX,0)(\dspMaxX,0)%
   \psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](0,\dspMinY,0)(0,\dspMaxY)%
   \dspPlotFrame%
   \FPifgt\dspCircle{0}%
     \FPmul\r\dspCircle{\strip@pt\dspUnitX}%
     \pscircle[linewidth=\dspFrameLineWidth,dimen=middle](0,0){{\r}pt}%
     \ifx\@empty\dspCircleLabel%
       \def\dspCircleLabel{\dspCircle}\relax\fi
     \FPupn\r{0.6 \dspTSX{} mul \dspCircle{} add}%
     \rput[b]{0}(\r,\tickTxtX){\dspCircleLabel}\relax\fi
%
   % draw ticks selectively according to user options
   % but here skip zero and intersections with the circle (if any)
   \FPupn\r{\tlimX{} 1 sub 2 div clip}%
   \def\xt{%
     \multido{\n=\stX+\incX}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickX{\n}\fi}%
     \multido{\n=\incX+\incX}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickX{\n}\fi}%
     \multido{\n=\stX+\incX}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickLabelX{\n}{$\n$}\fi}%
     \multido{\n=\incX+\incX}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickLabelX{\n}{$\n$}\fi}}%
   \def\yt{%
     \multido{\n=\stY+\incY}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickY{\n}\fi}%
     \multido{\n=\incY+\incY}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickY{\n}\fi}%
     \multido{\n=\stY+\incY}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickLabelY{\n}{$\n$}\fi}%
     \multido{\n=\incY+\incY}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickLabelY{\n}{$\n$}\fi}}%
   \ifDoXTicks\xt\fi
   \ifDoYTicks\yt\fi
   \ifComplexLabels%
     \rput[mr]{0}(\dspMaxX,1em){Re~}%
     \FPupn\r{\dspMaxY{} 0.6 \dspTSY{} mul sub}%
     \rput[t]{0}(-1.2em,\r){Im~}\relax\fi
}{%
 \end{pspicture}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Keyvals for poles and zeros
%
\newif\ifPZPole
\define@choicekey*[psset]{dspPZP}{type}[\ll\ln]{zero,pole}[zero]{%
 \ifcase\ln\relax
   \PZPolefalse
 \or
   \PZPoletrue
 \fi}
\newif\ifPZLabel
\define@choicekey*+[psset]{dspPZP}{label}[\ll\ln]{auto,none}[auto]{%
 \def\PZLabel{}\relax%
 \ifcase\ln\relax
   \PZLabeltrue
 \or
   \PZLabelfalse
 \fi}{%
 \PZLabeltrue
 \def\PZLabel{#1}}
\define@key[psset]{dspPZP}{lpos}{\def\PZLP{#1}}
\pst@addfams{dspPZP}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Plot pole-zero point
%
% \dspPZPoint[OPTIONS]{RE,IM}
%
%     RE, IM    coordinates
%
%   Options:
%
%     type = ["pole" | "zero"]    circle or cross (default: pole)
%     label=["false" | TEXT ]     the point's label (default: false)
%     lpos = ANGLE            label position (default: 45)
%
\newcommand{\dspPZ}[2][]{%
 \presetkeys[psset]{dspPZP}{type=pole,label=auto}{}%
 \setkeys*[psset]{dspPZP}{#1}%
 \ifPZPole
   \psdot[dotstyle=+,dotsize=1.4ex,dotscale=1.5,dotangle=45, #1](\twoArgSplit#2) \else
   \psdot[dotstyle=*,dotsize=1.4ex,#1](\twoArgSplit#2) \fi
 \ifx\@empty\PZLabel \def\PZLabel{$(\twoArgSplit#2)$} \fi
 % tricky bug in pstricks so we can't use presetkeys for angle... Could not understand
 \ifdefined\PZLP \relax \else \def\PZLP{45} \fi
 \ifPZLabel \uput[\PZLP]{0}(\twoArgSplit#2){\PZLabel} \fi}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\define@key{dspCP}{width}{\setlength{\dspCPW}{#1}\setlength{\dspCPH}{#1}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% dspCP environment
%
% \begin{dspCP}[OPTIONS]{MAX}
%
%
\newlength{\dspCPW}\newlength{\dspCPH}
\newenvironment{dspCP}[3][]{%
%% scale dimensions so that axes have equal units
 \setlength{\dspCPW}{0.37\textwidth}\setlength{\dspCPH}{\dspCPW}
 \setlength{\dspW}{\dspCPW}\setlength{\dspH}{\dspCPH}
 \setkeys*{dspCP}{#1}%
 \dspSetDims#2,#3,0\relax%
 \FPupn\g{\dspRngY{} {\strip@pt\dspCPW} / \dspRngX{} * 0 trunc}%
 \setlength{\dspCPH}{1pt*\g}%
%%
 \begin{dspPlot}[#1,sidegap=0,inticks=true,width=\dspCPW,height=\dspCPH]{#2}{#3}%
   \ifYAxisExp\psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](0,\dspMinY)(0,\dspMaxY)\fi
}{%
%% redo ticks and axes since images may overlap a little
   \dspPlotFrame
   \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\dspTickX{\n}}\fi
   \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickY{\n}}\fi
 \end{dspPlot}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Plot Dirac deltas
%
% \dspPoints[OPTIONS]{x1 y1 x2 y2 ...}
%
\newcommand{\dspPoints}[2][]{%
 \listplot[plotstyle=dots,%
   showpoints=true, dotstyle=*,%
   dotsize=\dspDotSize, #1]{\m@keList#2 \relax}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Plot Dirac delta with value
%
% \dspDiracs[OPTIONS]{x, y}{text}
%
\newcommand{\dspPointValue}[3][]{%
 \psdot[dotstyle=*, dotsize=\dspDotSize, #1](\twoArgSplit#2)%
 \uput[45]{0}(\twoArgSplit#2){#3}}

\newcommand{\dspPointValueSC}[3][]{%
 \SpecialCoor
 \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)%
 \uput[45]{0}(\twoArgSplit#2){#3}
 \NormalCoor}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Plot image from file
\newcommand{\dspImageFile}[1]{%
 \FPupn\u{2 \dspRngX{} 1.01 * / \dspMinX{} + }\FPupn\v{2 \dspRngY{} 1.01 * / \dspMinY{} + }%
 \setlength{\dspCPW}{1.01\dspW}\setlength{\dspCPH}{1.01\dspH}%
 \rput(\u,\v){\includegraphics[width=\dspCPW,height=\dspCPH]{#1}}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Quick image plot, with frame but no additional space around it
\newcommand{\dspShowImage}[2][0.37\textwidth]{%
 \psset{xunit=#1,yunit=#1}%
 \begin{pspicture}(0,0)(0,1)%
   \includegraphics[width=#1,height=#1]{#2}%
   \psframe[dimen=middle,linewidth=1.1pt](-0.01,0)(-.99,.99)
 \end{pspicture}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%% Some geometrical primitives
%
\newif\ifPointToOrg
\define@choicekey*[psset]{dspPZP}{toorg}[\ll\ln]{true,false}[false]{%
 \ifcase\ln\relax
   \PointToOrgtrue
 \or
   \PointToOrgfalse
 \fi}

% [opts]{x,y}{label}
\newcommand{\dspCPPoint}[3][]{%
 \setkeys*[psset]{dspPZP}{#1}%
 \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)%
 \uput[45]{0}(#2){#3}%
 \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](0,0)(#2)\fi}

% [opts]{x,y in special coor}{label}
\newcommand{\dspCPPointSC}[3][]{%
 \setkeys*[psset]{dspPZP}{#1}%
 \SpecialCoor%
 \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)%
 \uput[45]{0}(#2){#3}%
 \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](! 0 0 )(#2)\fi%
 \NormalCoor}

% [opts]{x,y}{r}
\newcommand{\dspCPCircle}[3][]{%
 \pscircle[#1](#2){#3\dspUnitX}}

% [opts]{r}{a}{label}
\newcommand{\dspCPCirclePoint}[4][]{%
 \setkeys*[psset]{dspPZP}{#1}%
 \SpecialCoor%
 \def\pcorps{! #3 cos #2 mul #3 sin #2 mul}%
 \FPupn\q{#2 1.1 * 2 trunc}%
 \uput*{\q\dspUnitX}[#3]{0}(0,0){#4}%
 \psdot[dotstyle=*, dotsize=\dspDotSize, #1](\pcorps)%
 \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](! 0 0 )(\pcorps)\fi%
 \NormalCoor}

% [opts] {r}{a}{b}{label}
\newcommand{\dspCPArc}[5][]{%
 \FPupn\p{#3 #4 + 0.5 * 2 trunc}%
 \FPupn\q{#2 1.1 * 2 trunc}%
 \uput*{\q\dspUnitX}[\p]{0}(0,0){#5}%
 \psarc[linewidth=2\dspTickLineWidth, #1]{->}{#2\dspUnitX}{#3}{#4}}
\newcommand{\dspCPArcn}[5][]{%
 \FPupn\p{#3 #4 + 0.5 * 2 trunc}%
 \FPupn\q{#2 1.1 * 2 trunc}%
 \uput*{\q\dspUnitX}[\p]{0}(0,0){#5}%
 \psarcn[linewidth=2\dspTickLineWidth, #1]{->}{#2\dspUnitX}{#3}{#4}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Helpers
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This is called at each plot setup with xmin, xmax, ymin, ymax and sidegap
%%  and sets all lengths
\def\dspSetDims#1,#2,#3,#4,#5\relax{%
 \def\sideGap{#5}%
 % default sidegap: 5% of range
 \FPifneg\sideGap\FPupn\sideGap{#1 #2 - 0.05 * 0.5 + 2 trunc}\fi%
 \FPifgt\sideGap{1}\FPtrunc\sideGap\sideGap{0}\fi%
%%
%% active range for the independent variable
 \def\dspMinActX{#1}%
 \def\dspMaxActX{#2}%
%% axes range (including sidegap)
 \FPupn\dspMinX{\sideGap{} #1 - clip}%
 \FPupn\dspMaxX{\sideGap{} #2 + clip}%
 \FPupn\dspRngX{#1 #2 - \sideGap{} 2 * + clip}%
 \FPupn\dspMinY{#3 0 + clip}%
 \FPupn\dspMaxY{#4 0 + clip}%
 \FPupn\dspRngY{#3 #4 - clip}%
%%
% if y-range is across zero we'll need to draw the x-axis
 \FPmul\u\dspMinY\dspMaxY%
 \FPifneg\u\XAxisExptrue\else\XAxisExpfalse\fi%
%% same for x (but usually we never draw the y axis)
 \FPmul\u\dspMinX\dspMaxX%
 \FPifneg\u\YAxisExptrue\else\YAxisExpfalse\fi%
%%
%% pstricks units: we scale the units so that coordinates are "real" coords on the axes
 \FPupn\tmp{\dspRngX{} {\strip@pt\dspW} / }
 \setlength{\dspUnitX}{\tmp pt}%
 \FPupn\tmp{\dspRngY{} {\strip@pt\dspH} / }%
 \setlength{\dspUnitY}{\tmp pt}%
%%
%% basic unit based on the size of the image: ~1pt for a 10x5 cm box
 \FPupn\g{2 {\strip@pt\dspW} {\strip@pt\dspH} * root 0.005 * 0 round 1 max}%
 \setlength{\dspBU}{1pt*\g}%
%% derived sizes: lines and fonts
 \setlength{\dspLineWidth}{1.8\dspBU}%
 \setlength{\dspDotSize}{5\dspBU}%
 \setlength{\dspStemWidth}{1.4\dspBU}%
 \fontsize{9\dspBU}{10\dspBU}\selectfont%
%  %% ticks on axes
 \setlength{\dspTickLen}{4\dspBU}%
 \setlength{\dspTickLineWidth}{0.4\dspBU}%
 \setlength{\dspXTickGap}{6\dspBU}\addtolength{\dspXTickGap}{2ex}%
 \setlength{\dspYTickGap}{2\dspBU}%
 \setlength{\dspFrameLineWidth}{2.2\dspTickLineWidth}%
%%
%% height of a line of text in psticks units
 \setlength{\dspTmpLen}{1em}%
 \FPupn\dspTSX{{\strip@pt\dspUnitX} {\strip@pt\dspTmpLen} / }%
 \FPupn\dspTSY{{\strip@pt\dspUnitY} {\strip@pt\dspTmpLen} / }%
%%
%% find the coordinates of the plot's bounding box, including labels
 \ifYLabel%
   \FPupn\LX{\dspTSX{} 4 * \dspMinX{} -}%
   \FPupn\RX{\dspTSX{} 4 * \dspMaxX{} +}%
 \else%
   \FPupn\LX{\dspTSX{} 2 * \dspMinX{} -}%
   \FPupn\RX{\dspTSX{} 2 * \dspMaxX{} +}%
 \fi
 \FPupn\TY{\dspTSY{} \dspMaxY{} +}%
 \def\outTicks{%
   \ifXTicks\FPupn\BY{\dspTSY{} 2.5 * \dspMinY{} -}\else\FPupn\BY{\dspTSY{} \dspMinY{} -}\fi%
  \ifXLabel\FPupn\BY{\dspTSY{} 1.5 * \BY{} -}\else\relax\fi }%
 \ifXAxisExp % ticks are inside
   \ifXLabel\FPupn\BY{\dspTSY{} 2.5 * \dspMinY{} -}\else\FPupn\BY{\dspTSY{} \dspMinY{} -}\fi%
 \else% ticks are outside
   \outTicks \fi%
 % did we select explicit outside ticks?
 \ifXTicksOut\outTicks \fi%
%%
%% x-axis resolution for plotting functions: ~60 values/cm
 \FPupn\dspPSPoints{{\strip@pt\dspW} 2 * 0 trunc}%
%%
 \psset{xunit=\dspUnitX, yunit=\dspUnitY}%
 \psset{linewidth=\dspLineWidth}%www
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Draw axis labels (if required) under x axis and to left and right of y axes
%%
\def\dspLabels{%
 % horizontal label
 \ifXTicksOut\XAxisExpfalse\fi%
 \ifXLabel%
   \FPupn\mid{\dspMinX{} \dspMaxX{} + 0.5 mul}%
   \ifXAxisExp%
     \FPupn\pos{\dspTSY{} 2 * \dspMinY{} -}%
   \else%
     \ifXTicks%
       \FPupn\pos{\dspTSY{} 3 * \dspMinY{} -}%
     \else%
       \FPupn\pos{\dspTSY{} 2 * \dspMinY{} -}%
     \fi%
   \fi%
   \rput[b]{0}(\mid,\pos){\dspXLabel}%
 \fi%
%
 \FPupn\mid{\dspMinY{} \dspMaxY{} + 0.5 mul}%
 \ifYTicks%
   \FPupn\pos{\dspTSX{} 3.4 * \dspMinX{} -}%
 \else%
   \FPupn\pos{\dspTSX{} 1 * \dspMinX{} -}%
 \fi%
 \rput[b]{90}(\pos,\mid){\dspYLabel}
%%
 \FPupn\pos{\dspTSX{} 3 * \dspMaxX{} +}%
 \rput[b]{-90}(\pos,\mid){\dspYLabelR}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This sets axes ticks (spacing and number) and prepares macros
%%  for plotting ticks and tick labels
\def\dspSetupAxes{%
%% tick increments; if incX/Y is zero, compute suitable value
 \FPifgt\incX{0}\FPupn\incX{\incX{} 2 trunc}%
   \else\FPupn\incX{\dspMinActX{} \dspMaxActX{} - 1 + 6 swap / 0 trunc 1 max}\relax\fi%
 \FPifgt\incY{0}\FPupn\incY{\incY{} 2 trunc}%
   \else\FPupn\incY{\dspMinY{} \dspMaxY{} - 1 + 6 swap / 0 trunc 1 max}\relax\fi%
%%
%% now find starting point and increment for ticks (and number of ticks)
%% start with y-axis:
 \ifXAxisExp% is y=0 explicit or does it coincide with the lower edge?
   \def\haY{0}%
   % make sure ticks hit zero; add small epsilons to avoid ticks at the limits
   \FPupn\stY{\incY{} \dspMinY{} / 0.001 + 0 trunc \incY{} * 2 trunc}%
   \FPupn\tlimY{\stY{} \dspMaxY{} - 0.001 - \incY{} swap / abs 1 + 0 trunc}%
 \else%
   \def\haY{\dspMinY}%
   \FPupn\tlimY{\incY{} \dspRngY{} / abs 1 + 0 trunc}%
   \FPupn\stY{\dspMinY{} 2 trunc}% \incY{} 1 \tlimY{} - * \dspRngY{} - 0.5 * \dspMinY{} + 2 trunc}%
 \fi%
 % x-ticks outside of the box anyway?
 \ifXTicksOut\def\haY{\dspMinY}\relax\fi%
 % round off to integer if possible:
 \FPupn\v{\stY{} 0 trunc \stY{} - abs \incY{} 0 trunc \incY{} - abs + clip}%
 \FPifeq\v{0}\FPtrunc\stY\stY{0}\FPtrunc\incY\incY{0}\relax\fi%
%
%% now x-axis:
 \ifYAxisExp% we almost never draw the y-axis but need to see if x-axis spans zero
   % make sure ticks hit zero; add small epsilons to avoid ticks at the limits
   \FPupn\stX{\incX{} \dspMinX{} / 0 trunc \incX{} * 2 trunc}%
   \FPupn\tlimX{\incX{} \stX{} \dspMaxX{} - / abs 1 +  0 trunc}%
 \else%
   \FPupn\tlimX{\incX{} \dspRngX{} / abs 1 + 0 trunc}%
   \FPupn\stX{\dspMinX{} 2 trunc}% \FPupn\stX{\incX{} 1 \tlimX{} - * \dspRngX{} - 0.5 * \dspMinX{} + 2 trunc}%
 \fi%
 \FPupn\v{\stX{} 0 trunc \stX{} - abs \incX{} 0 trunc \incX{} - abs +}%
 \FPifzero\v\FPtrunc\stX\stX{0}\FPtrunc\incX\incX{0}\relax\fi%
%%
%% macros for drawing x-ticks
 \ifXInside%
   \FPupn\tickEndX{{\strip@pt\dspUnitY} {\strip@pt\dspTickLen} /}%
   \FPupn\tickTxtX{{\strip@pt\dspUnitY} {\strip@pt\dspXTickGap} 0.9 * / \dspMinY{} -}% tick label pos in PS units
   \FPupn\tickXB{\tickEndX{} \dspMinY{} +}%
   \FPupn\tickXT{\tickEndX{} \dspMaxY{} -}%
   \gdef\dspTickX##1{%
     \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\dspMinY)(##1,\tickXB)%
     \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\dspMaxY)(##1,\tickXT)}%
 %  \gdef\dspTickLabelX##1##2{\uput{{2\dspYTickGap}}[180]{{0}}(\dspMinX,##1){{##2}}}%
   \gdef\dspTickLabelX##1##2{\rput*[B]{{0}}(##1,\tickTxtX){{##2}}}%
 \else%
   \FPupn\tickEndX{{\strip@pt\dspUnitY} {\strip@pt\dspTickLen} / \haY{} -}% tick len in PS units
   \FPupn\tickTxtX{{\strip@pt\dspUnitY} {\strip@pt\dspXTickGap} / \haY{} -}% tick label pos in PS units
   \gdef\dspTickX##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\haY)(##1,\tickEndX)}%
   \gdef\dspTickLabelX##1##2{\rput*[B]{{0}}(##1,\tickTxtX){{##2}}}%
 \fi%
%% macros for drawing y-ticks
 \FPupn\tickEndY{{\strip@pt\dspUnitX} {\strip@pt\dspTickLen} /}%
 \FPupn\tickXB{\tickEndY{} \dspMinX{} +}%
 \FPupn\tickXT{\tickEndY{} \dspMaxX{} -}%
 \gdef\dspTickY##1{%
   \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\dspMinX,##1)(\tickXB,##1)%
   \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\dspMaxX,##1)(\tickXT,##1)}%
 \gdef\dspTickLabelY##1##2{\uput{{2\dspYTickGap}}[180]{{0}}(\dspMinX,##1){{##2}}}%
 \gdef\dspTickLabelYR##1##2{\uput{{2\dspYTickGap}}[0]{{0}}(\dspMaxX,##1){{##2}}}%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% simplify fractions of pi
\newcount\dspNum \newcount\dspDen
\def\simplifyPiFrac#1#2{%
 \ifnum#1=0 $0$\else % zero is zero
   \dspNum=#1 \dspDen=#2 %
   \divide\dspNum by\dspDen \multiply\dspNum by\dspDen % see if frac is simply an integer
   \ifnum\dspNum=#1 \divide\dspNum by\dspDen \ifnum\dspNum=1 $\pi$\else \ifnum\dspNum=-1 $-\pi$\else $\number\dspNum\pi$\fi\fi\else%
     \dspNum=#1 %
     \ifnum\dspNum<0 \multiply\dspNum by-1 \def\s{-}\else\def\s{}\fi % normalize sign
     \divide\dspDen by\dspNum \multiply\dspDen by\dspNum % see if frac is of type 1/x
     \ifnum\dspDen=#2 \divide\dspDen by\dspNum $\s\pi / \number\dspDen$\else %
     \dspNum=#1\dspDen=#2 %
     \removeFactor{10}\removeFactor{9}\removeFactor{8}% remove some common factors
     \removeFactor{7}\removeFactor{6}\removeFactor{5}%
     \removeFactor{4}\removeFactor{3}\removeFactor{2}%
     $\number\dspNum \pi / \number\dspDen$\fi%
   \fi %
 \fi}

%% simplify a fraction (not the full Euclid, but it's ok for our purposes)
\newcount\dspTerm \newcount\dspFact
\def\removeFactor#1{\dspFact=#1 \dspTerm=\dspNum%
 \divide\dspTerm by\dspFact \multiply\dspTerm by\dspFact %
 \ifnum\dspTerm=\dspNum %
   \dspTerm=\dspDen %
   \divide\dspTerm by\dspFact \multiply\dspTerm by\dspFact %
   \ifnum\dspTerm=\dspDen %
     \divide\dspNum by\dspFact \divide\dspDen by\dspFact %
   \fi %
 \fi}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% space-separated lists must have at least two pairs of elements.
% Duplicate singletons
%
\def\m@keList#1 #2 #3\relax{%
 \ifx&#3&
   #1 #2 #1 #2
 \else
   #1 #2 #3
 \fi
}

\def\twoArgSplit#1,#2{#1, #2}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% prepend the ordinal index to each element of a space-separated list
%
\def\m@keIndexedList#1#2{%
 \count0=#1%
 \expandafter\m@kixl\trim #2 |}
\def\m@kixl#1 {%
 \ifx#1|%
   \let\next=\relax%
 \else{\number\count0} \ #1\ \advance\count0 by1\let\next=\m@kixl\fi%
\next}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% perform an action on all consecutive pairs in a space-separated list
%
\def\doOnPairs#1#2{%
 \def\action{#1}%
 \expandafter\p@rseB\trim #2 |}
\def\p@rseB#1 #2 #3{%
\csname \action\endcsname{#1}{#2}%
 \ifx#3|%
   \let\next=\@gobble%
 \else%
   \let\next=\p@rseB\fi%
 \next #3}
\def\@gobble#1{}


\def\trim#1{%
 \romannumeral-`\.\expandafter\noexpand#1%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% PsTricks overrides
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Lollipop line style, by Denis.Girou at idris.fr %%%%%%%%%%%%%%%%%%%%%%%%
%%
\let\beginplot@LineToXAxis\beginplot@line
\def\endplot@LineToXAxis{\psLineToXAxis@ii}
\let\beginqp@LineToXAxis\beginqp@line
\let\doqp@LineToXAxis\doqp@line
\let\endqp@LineToXAxis\endqp@line
\let\testqp@LineToXAxis\testqp@line
%
\def\psLineToXAxis@ii{%
\addto@pscode{\pst@cp \psline@iii \tx@LineToXAxis}%
\end@OpenObj}
%
\def\tx@LineToXAxis{LineToXAxis }
%
% Adapted from Line
\pst@def{LineToXAxis}<{%
NArray
n 0 eq not
 { n 1 eq { 0 0 /n 2 def } if
   ArrowA
   /n n 2 sub def
   CP 2 copy moveto pop 0 Lineto
   n { 2 copy moveto pop 0 Lineto } repeat
   CP
   4 2 roll
   ArrowB
   2 copy moveto pop 0
   L
   pop pop } if}>


\makeatother
\endinput