From 2aa608cd9808e84c462362be9eb92a98a1b79e4d Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 25 Jul 2014 21:05:22 +0000 Subject: dsptricks (25jul14) git-svn-id: svn://tug.org/texlive/trunk@34724 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/latex/dsptricks/dspblocks.sty | 116 +++ .../tex/latex/dsptricks/dspfunctions.sty | 258 +++++ .../texmf-dist/tex/latex/dsptricks/dsptricks.sty | 1071 ++++++++++++++++++++ 3 files changed, 1445 insertions(+) create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty (limited to 'Master/texmf-dist/tex/latex/dsptricks') diff --git a/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty b/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty new file mode 100644 index 00000000000..b7aba995a9e --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty @@ -0,0 +1,116 @@ +%% This is the package dspblocks +%% +%% (c) Paolo Prandoni +%% +%% 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: +%% `dspblocks' is a companion package to dsptricks; it contains a +%% set of macros to draw the types of block diagrams commonly +%% used in DSP theory +%% +%% v1.0, July 2014 +%% + +% required packages: +\RequirePackage{calc} +\RequirePackage{fp} +\RequirePackage{pst-xkey} +\RequirePackage{fmtcount} +\RequirePackage{ifthen} +% +\ProvidesPackage{dspblocks}[2014/07/24 package for signal processing graphics] + + +% turn off FP messages +\FPmessagesfalse + +\makeatletter + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Set up BLOCK DIAGRAM plot +% +% \begin{psdrawBDmatrix}[OPTIONS]{X_SPACING}{Y_SPACING} +% +% X_SPACING +% Y_SPACING vertical and horizontal spacing +% +% Once in Block diagram mode the following commands are available +% (they all create nodes) +% +% \BDadd adder +% \BDmul multiplier +% \BDdelay z^{-1} delay block +% \BDdelayN{N} z^{-N} delay block +% \BDfilter{text} filter box +% \BDfilterMulti{text} multiline filter box +% \BDsplit splitting point (dot) +% \BDupsmp{K} upsampler by K +% \BDdwsmp{K} downsampler by K +% + +\def\BDwidth{1.2pt} +\psset{xunit=1mm,yunit=1mm,linewidth=\BDwidth} +\def\BDadd{[mnode=circle] +}% +\def\BDsub{[mnode=circle] -}% +\def\BDmul{[mnode=circle] $\times$}% +\def\BDdelay{\psframebox[framesep=.3]{$z^{-1}$}}% +\def\BDdelayN#1{\psframebox[framesep=.3]{$z^{-#1}$}}% +\def\BDfilter#1{\psframebox[framesep=.3]{#1}}% +\def\BDfilterMulti#1{\psframebox% + {\begin{tabular}{c} #1 \end{tabular}}}% +\def\BDsplit{[mnode=dot,linewidth=1.5pt]}% +\def\BDupsmp#1{[mnode=circle] $#1 \uparrow$}% +\def\BDdwsmp#1{[mnode=circle] $#1 \downarrow$}% +\def\BDsampler{\raisebox{-14.6pt}{ + \psset{xunit=1em,yunit=1em,linewidth=1.2pt}% + \pspicture(-2.6,-1.8)(1,1.8)% + \psline(-3,0)(-1.6,0)(0.7,1.2) + \psline(0.8,0)(1,0) + \psarc[linewidth=1pt]{<-}(-1.2,0){1.4em}{-10}{55} + \endpspicture}} +\newcommand{\BDsamplerFramed}[1][1em]{ + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline(-2.8,-0.2)(-1.6,-0.2)(1.2,1.4)% + \psline(1.1,-0.2)(1.8,-0.2)% + \psarc[linewidth=1pt]{<-}(-1.6,0){2}{-10}{55}% + \endpspicture}}} +\newcommand{\BDlowpass}[1][1em]{% + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline{->}(-2.8,-1)(2.8,-1)% + \psline{->}(0,-1.8)(0,2)% + \psline[linewidth=1.5pt](-1,-1)(-1,0.8)(1,0.8)(1,-1)% + \endpspicture}}} +\newcommand{\BDsinc}[1][1em]{% + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline{->}(-2.8,-.5)(2.8,-.5)% + \psline{->}(0,-1.8)(0,2)% + \psplot[linewidth=1pt, plotpoints=500,linejoin=1]{-2.5}{2.5}{x \dspSinc{0}{0.5} 1.5 mul .5 sub}% + \endpspicture}}} + +\newenvironment{dspBlocks}[2]{% + \begin{psmatrix}[colsep=#1,rowsep=#2,emnode=R] }{% + \end{psmatrix} +} + +\newcommand{\BDConnH}[5][]{\ncline[#1]{->}{#2,#3}{#2,#4}\taput{#5}} +\newcommand{\BDConnHNext}[2]{\FPupn\n{#2 1 add 0 trunc}\ncline{->}{#1,#2}{#1,\n}} +\newcommand{\BDConnV}[5][]{\ncline[#1]{->}{#2,#3}{#4,#3}\tlput{#5}} + +\makeatother \ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty b/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty new file mode 100644 index 00000000000..ae63eccaa0d --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty @@ -0,0 +1,258 @@ +%% This is the package dspfunctions +%% +%% (c) Paolo Prandoni +%% +%% 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: +%% `dspfunctions' is a companion package to dsptricks; it contains a +%% set of postscript macros to compute the value of various DSP +%% common functions +%% +%% v1.0, July 2014 +%% + +\ProvidesPackage{dspfunctions}[2014/07/24 package for signal processing graphics] + +\def\dspToDeg{180 mul } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspRect{a}{b} rect((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRect#1#2{ #1 sub abs #2 div 0.5 gt {0} {1} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspTri{a}{b} triangle((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspTri#1#2{ #1 sub abs #2 div dup 1 gt {pop 0} {1 exch sub} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspExpDec{a}{b} b^(x-a)u[x-a] +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspExpDec#1#2{ #1 sub dup 0 lt {pop 0} {#2 exch exp} ifelse } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspQuad{a}{b} quadratic((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspQuad#1#2{ #1 sub abs #2 div dup 1 gt {pop 0} {dup mul 1 exch sub } ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Porkpie hat shape (useful for spectral prototypes +% \dspPorkpie{a}{b} phi((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspPorkpie#1#2{ #1 sub #2 div dup abs 1 gt {pop 0}% + {32.4 mul dup cos exch % + dup 3 mul cos 2 mul exch % + 12 mul cos -0.7 mul % + add add 0.31 mul 0.017 add } ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Raised cosine +% \dspRaisedCos{cutoff}{rolloff} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRaisedCos#1#2{abs % + dup dup + 1 #2 sub #1 mul lt % + {pop pop 1} % + {1 #2 add #1 mul gt % + {pop 0} {1 #2 sub #1 mul sub 2 #2 #1 mul mul div 3.14 mul RadtoDeg cos 1 add 0.5 mul} ifelse } % + ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Raised cosine, better syntax +% \dspRaisedCos{a}{b}{r} b = cutoff, r = rolloff +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRaisedCosine#1#2#3{% + #1 sub abs #2 div + dup dup + 1 #3 sub lt + {pop pop 1} + {1 #3 add gt + {pop 0} + {1 #3 sub sub 2 #3 mul div 180 mul cos 1 add 0.5 mul} + ifelse} + ifelse } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspSinc{a}{b} sinc((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSinc#1#2{ #1 sub #2 div dup 0 eq {pop 1} {dup 180 mul sin exch 3.1415 mul div} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspSincN{a}{b} (1/b)sinc((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincN#1#2{\dspSinc{#1}{#2} #2 div } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Fourier transform of a symmetric 2N+1 tap rect +% \dspSincS{a}{N} sin((x-a)(2N+1)/2)/sin((x-a)/2) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincS#1#2{ #1 sub 90 mul dup #2 2 mul 1 add mul sin exch sin dup 0 eq {pop pop #2 2 mul 1 add} {div} ifelse} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Fourier transform magnitude of a causal N tap rect +% (phase is e^{-j\frac{N-1}{2}\omega}) +% \dspSincC{a}{N} sin((x-a)(N/2))/sin((x-a)/2) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincC#1#2{ #1 sub 90 mul dup #2 mul sin exch sin dup 0 eq {pop pop #2} {div} ifelse} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspRand % Random number uniformly distributed over [-1 1] +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRand{rand 2147483647 div 0.5 sub 2 mul } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Discrete Fourier Transform of an input sequence; input is +% the integer value of the DFT coefficient. +% +% \dspDFTRE{a_0 a_1 ... a_{N-1}} (real part) +% \dspDFTIM{a_0 a_1 ... a_{N-1}} (imaginary part) +% \dspDFTMAG{a_0 a_1 ... a_{N-1}} (magnitude) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspDFT#1{% + cvi [#1] length mod % DFT is N periodic + 360 mul [#1] length div % w = (2k\pi)/N + 0 % index n + 0 % accumulator Re + 0 % accumulator Im + [#1] % data points + { % STACK: + % w n re im a_n + dup % w n re im a_n a_n + 5 index % w n re im a_n a_n w + 5 index % w n re im a_n a_n w n + mul dup % w n re im a_n a_n nw nw + sin exch cos % w n re im a_n a_n sin(nw) cos(nw) + 4 1 roll mul % w n re im cos(nw) a_n (a_n)sin(nw) + 3 1 roll mul % w n re im (a_n)sin(nw) (a_n)cos(nw) + 4 1 roll add % w n (a_n)cos(nw) re im' + 3 1 roll add exch % w n re' im' + 3 2 roll 1 add % w re' im' n' + 3 1 roll % w n re im + } forall + 4 2 roll pop pop % re im +} +\def\dspDFTRE#1{\dspDFT{#1} pop } +\def\dspDFTIM#1{\dspDFT{#1} exch pop } +\def\dspDFTMAG#1{\dspDFT{#1} dup mul exch dup mul add sqrt } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Frequency response of a (2N+1)-tap Type-I FIR computed at a given +% normalized frequency value. Frequency response is real for Type-I +% The filter is considered zero-centered, so a_0 is the center tap +% +% \dspFIRI{a_0 a_1 ... a_{N-1}} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspFIRI#1{% + \dspToDeg % input to degrees + 0 % index n + 0 % accumulator A + [#1] % coefficients a_n + { + 3 index % x + 3 index % n [*** using index INCREASES stack size... so it's 3 3 rather than 3 2] + mul cos mul % a_n cos nx + add % accumulate + exch 1 add exch % i++ + } forall + 3 1 roll pop pop + 2 mul % final value is 2A - a_0 + [#1] 0 get sub +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Magnitude response of a generic digital filter defined by the +% constant-coefficient difference equation: +% y[n] = a_0 x[n] + a_1 x[n-1] + ... + a_{N-1} x[n-N+1] +% - b_1 y[n-1] - ... - b_{M-1} y[n-M+1] +% +% The response is computed at the given normalized frequency value +% +% \dspTFM{a_0 a_1 ... a_{N-1}}{b_1 b_2 ... b_{M-1}} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspTFM#1#2{% + \dspToDeg % input to degrees + dup % save a copy for denominator + 0 % index n + 0 % accumulator Re + 0 % accumulator Im + [#1] % coefficients a_n + { % STACK (neglecting saved input at bottom): + % x n re im a_n + dup % x n re im a_n a_n + 5 index % x n re im a_n a_n x + 5 index % x n re im a_n a_n x n + mul dup % x n re im a_n a_n nx nx + sin exch cos % x n re im a_n a_n sin(nx) cos(nx) + 4 1 roll mul % x n re im cos(nx) a_n (a_n)sin(nx) + 3 1 roll mul % x n re im (a_n)sin(nx) (a_n)cos(nx) + 4 1 roll add % x n (a_n)cos(nx) re im' + 3 1 roll add exch % x n re' im' + 3 2 roll 1 add % x re' im' n' + 3 1 roll % x n re im + } forall + 4 2 roll pop pop % re im + dup mul exch dup mul add % (re^2 + im^2) + sqrt % mag of the numerator of transfer function + exch % bring up saved input copy + 0 % same loop for the b_n coefficients + 0 + 0 + [#2] + { + dup + 5 index + 5 index + mul dup + sin exch cos + 4 1 roll mul + 3 1 roll mul + 4 1 roll add + 3 1 roll add exch + 3 2 roll 1 add + 3 1 roll + } forall + 4 2 roll pop pop + dup mul exch dup mul add + sqrt + div %0 eq {pop pop 0} {div} ifelse +} + diff --git a/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty b/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty new file mode 100644 index 00000000000..5b075c043c1 --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty @@ -0,0 +1,1071 @@ +%% This is the package dsptricks +%% +%% (c) Paolo Prandoni +%% +%% 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.0, July 2014 +%% +\RequirePackage{pstricks} +\RequirePackage{pstricks-add} +\RequirePackage{pst-xkey} +\RequirePackage{calc} +\RequirePackage{fp} +\RequirePackage{ifthen} +% +\ProvidesPackage{dsptricks}[2014/07/24 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&##3& + \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& + #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 + -- cgit v1.2.3