From: Taylor R Campbell Date: Mon, 8 Jul 2019 00:57:25 +0000 (+0000) Subject: Plot the new math functions and their condition numbers. X-Git-Tag: mit-scheme-pucked-10.1.12~7^2~18 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=e45856cff387760b88ec63428ed17ec742f8e5c9;p=mit-scheme.git Plot the new math functions and their condition numbers. Plots are done purely in PostScript, so no additional tools required on top of the existing PostScript/PDF stack we essentially already depended on. Plots are cubic spline interpolations computed by a little automatic differentiation library in PostScript. Fix some mistakes in the prose characterizations of the condition numbers that I had written. --- diff --git a/doc/make-common.in b/doc/make-common.in index bcf6ef1fe..bcf004cc2 100644 --- a/doc/make-common.in +++ b/doc/make-common.in @@ -75,31 +75,50 @@ DVI_TARGET = $(TARGET_ROOT).dvi PDF_TARGET = $(TARGET_ROOT).pdf PS_TARGET = $(TARGET_ROOT).ps +GS = gs +PS2PDF = ps2pdf +PS2PNG = $(GS) -dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m + TEX_OPTIONS = --quiet $(EXTRA_TEX_OPTIONS) +FIGURES_PNG = $(FIGURES_EPS:.eps=.png) +FIGURES_PDF = $(FIGURES_EPS:.eps=.pdf) + all: $(INFO_TARGET) $(TARGETS) -$(INFO_TARGET): $(SOURCES) +$(INFO_TARGET): $(SOURCES) $(FIGURES_PNG) rm -f $(INFO_TARGET)* makeinfo --output=$(INFO_TARGET) $(TEXINFO_ROOT).texinfo -$(HTML_TARGET)/index.html: $(SOURCES) +$(HTML_TARGET)/index.html: $(SOURCES) $(FIGURES_PNG) rm -rf $(HTML_TARGET) makeinfo --html $(TEXINFO_ROOT).texinfo -$(PDF_TARGET): $(SOURCES) +$(PDF_TARGET): $(SOURCES) $(FIGURES_PDF) texi2dvi --pdf $(TEX_OPTIONS) --output=$@ $(TEXINFO_ROOT).texinfo -$(PS_TARGET): $(SOURCES) +$(PS_TARGET): $(SOURCES) $(FIGURES_EPS) -rm -f $(DVI_TARGET) texi2dvi $(TEX_OPTIONS) --output=$(DVI_TARGET) $(TEXINFO_ROOT).texinfo dvips -q -o $@ $(DVI_TARGET) rm -f $(DVI_TARGET) +.SUFFIXES: .eps +.SUFFIXES: .pdf +.SUFFIXES: .png + +.eps.pdf: + $(PS2PDF) -dEPSCrop -sOutputFile=$@.tmp $< && mv -f $@.tmp $@ + +.eps.png: + $(PS2PNG) -dEPSCrop -sOutputFile=$@.tmp $< && mv -f $@.tmp $@ + mostlyclean: clean: mostlyclean rm -f $(INFO_TARGET)* $(PDF_TARGET) $(PS_TARGET) + rm -f $(FIGURES_PDF) + rm -f $(FIGURES_PNG) rm -rf $(HTML_TARGET) rm -rf $(TEXINFO_ROOT).aux $(TEXINFO_ROOT).log $(TEXINFO_ROOT).toc rm -rf $(TEXINFO_ROOT).pg $(TEXINFO_ROOT).tp diff --git a/doc/ref-manual/Makefile.in b/doc/ref-manual/Makefile.in index 40e5a89c6..fa0996c84 100644 --- a/doc/ref-manual/Makefile.in +++ b/doc/ref-manual/Makefile.in @@ -54,4 +54,27 @@ SOURCES = \ vectors.texi \ win32-packaging.texi +FIGURES_EPS = \ + fig/cn-expm1.eps \ + fig/cn-log1mexp.eps \ + fig/cn-log1p.eps \ + fig/cn-log1pexp.eps \ + fig/cn-logistic.eps \ + fig/cn-logistichalf.eps \ + fig/cn-logit.eps \ + fig/cn-logitexp.eps \ + fig/cn-logithalf.eps \ + fig/cn-loglogistic.eps \ + fig/expm1.eps \ + fig/log1mexp.eps \ + fig/log1p.eps \ + fig/log1pexp.eps \ + fig/logistic.eps \ + fig/logistichalf.eps \ + fig/logit.eps \ + fig/logitexp.eps \ + fig/logithalf.eps \ + fig/loglogistic.eps \ + # end of FIGURES_EPS + include $(top_srcdir)/make-common diff --git a/doc/ref-manual/fig/cn-expm1.eps b/doc/ref-manual/fig/cn-expm1.eps new file mode 100644 index 000000000..e64e5e775 --- /dev/null +++ b/doc/ref-manual/fig/cn-expm1.eps @@ -0,0 +1,459 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -1.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 20 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 2 1 0 tick 2 1 yticklabel + 0 1 1 0 tick + 0 -1 1 0 tick +grestore + +% Plot another one: expm1 condition number. +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax { % Tx => T(f(x)) + dup Texpm1 % Tx T(e^x-1) + dup Tq 0.0 eq { + Texp + } { + exch dup % T(e^x-1) Tx Tx + Texp Tmul % T(e^x-1) T(x*e^x) + exch Tdiv % T(x*e^x/(e^x-1)) + } ifelse + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-log1mexp.eps b/doc/ref-manual/fig/cn-log1mexp.eps new file mode 100644 index 000000000..2fdd6bce1 --- /dev/null +++ b/doc/ref-manual/fig/cn-log1mexp.eps @@ -0,0 +1,497 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -2.2 def /axmax 0.5 def /aymin -2.8 def /aymax 0.5 def + +% Interpolation parameters. +/nspline 75 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 1 1 0 tick + 0 -1 1 0 tick -1 1 yticklabel + 0 -2 1 0 tick -2 1 yticklabel +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + 5 dict begin + /Tf { + dup Texp % Tx T(e^x) + dup Tneg Tln1p % Tx T(e^x) T(log(1-e^x)) + 2 index Texpm1 Tneg % Tx T(e^x) T(log(1-e^x)) T(1-e^x) + Tmul % Tx T(e^x) T((1-e^x)*log(1-e^x)) + Tdiv Tmul Tneg % T((-x*e^x)/((1-e^x)*log(1-e^x))) + } def + /fxmax -0.0001 def + /fxmin axmin def + /n nspline def + /fxwidth fxmax fxmin sub def + newpath + nspline axmin -0.0001 {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n axmin -0.0001 {Tf} cubicsplinterpostep curveto } for + % Fabricate a final point at the origin with positive + % derivative. (Too lazy to compute the limit...) + 0.0 0.0 T % Tx0 Ty0 Tx3 + 0.0 1.0 T % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol + 5 index Tq 5 index Tq + curveto + cubicsplinterpostop + stroke + end +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-log1p.eps b/doc/ref-manual/fig/cn-log1p.eps new file mode 100644 index 000000000..cf21a1260 --- /dev/null +++ b/doc/ref-manual/fig/cn-log1p.eps @@ -0,0 +1,451 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -1.2 def /axmax 2.2 def /aymin -1.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 20 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll sub % tx y ys -(ury+lly)/2 llx-urx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + -1 aymin a2bb moveto + -1 aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick + + % y ticks + 0 2 1 0 tick 2 1 yticklabel + 0 1 1 0 tick + 0 -1 1 0 tick +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline -0.9 axmax { + dup dup % Tx Tx Tx + 1.0 Tconst Tadd % Tx Tx T(1+x) + Tdiv % Tx T(x/(1+x)) + exch Tln1p % T(x/(1+x)) T(log(1+x)) + Tdiv % T(x/[(1+x)*log(1+x)]) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-log1pexp.eps b/doc/ref-manual/fig/cn-log1pexp.eps new file mode 100644 index 000000000..06b4e7b05 --- /dev/null +++ b/doc/ref-manual/fig/cn-log1pexp.eps @@ -0,0 +1,460 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -1.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 20 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke + newpath + axmin 1 a2bb moveto + axmax 1 a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont % encoding => encoding + { + dup 45 /minus put % replace hyphen by minus + } reencodefont + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -1 0 tick + 0 -1 -1 0 tick -1 -1 yticklabel +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + nspline axmin axmax { % Tx => T(f(x)) + dup Texp % Tx T(e^x) + dup Tln1p % Tx T(e^x) T(log(1+e^x)) + 1 index 1.0 Tconst Tadd % Tx T(e^x) T(log(1+e^x)) T(1+e^x) + Tmul % Tx T(e^x) T((1+e^x)*log(1+e^x)) + Tdiv Tmul % T((x*e^x)/((1+e^x)*log(1+e^x))) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-logistic.eps b/doc/ref-manual/fig/cn-logistic.eps new file mode 100644 index 000000000..0f5a30ef2 --- /dev/null +++ b/doc/ref-manual/fig/cn-logistic.eps @@ -0,0 +1,457 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -2.5 def /aymax 1.5 def + +% Interpolation parameters. +/nspline 8 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 1 -1 0 tick 1 -1 yticklabel + 0 0.5 -0.5 0 tick + 0 -0.5 -0.5 0 tick + 0 -1 -1 0 tick + 0 -1.5 -0.5 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax { % Tx => T(f(x)) + dup Tneg Texp % Tx T(e^-x) + dup 1.0 Tconst Tadd % Tx T(e^-x) T(1 + e^-x) + Tdiv % Tx T(e^-x/(1 + e^-x)) + Tmul % T(x*e^-x/(1 + e^-x)) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-logistichalf.eps b/doc/ref-manual/fig/cn-logistichalf.eps new file mode 100644 index 000000000..9a8fc476c --- /dev/null +++ b/doc/ref-manual/fig/cn-logistichalf.eps @@ -0,0 +1,448 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -4.5 def /axmax 4.5 def /aymin -0.5 def /aymax 1.2 def + +% Interpolation parameters. +/nspline 8 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin 1 a2bb moveto + axmax 1 a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 4 0 0 -1 tick 4 -1 xticklabel + 3 0 0 -1 tick + 2 0 0 -1 tick 2 -1 xticklabel + 1 0 0 -1 tick + -1 0 0 -1 tick + -2 0 0 -1 tick -2 -1 xticklabel + -3 0 0 -1 tick + -4 0 0 -1 tick -4 -1 xticklabel + + % y ticks + 0 1 -1 0 tick 1 -1 yticklabel + 0 0.75 -0.5 0 tick + 0 0.5 -0.5 0 tick + 0 0.25 -0.5 0 tick +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax { % Tx => T(f(x)) + dup Tneg Texp % Tx T(e^-x) + dup dup Tmul % Tx T(e^-x) T(e^-2x) + 1.0 Tconst exch Tsub % Tx T(e^-x) T(1-e^-2x) + Tdiv % Tx T(e^-x/(1-e^-2x)) + 2.0 Tconst Tmul Tmul % T(2x*e^-x/(1-e^-2x)) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-logit.eps b/doc/ref-manual/fig/cn-logit.eps new file mode 100644 index 000000000..3061a2f64 --- /dev/null +++ b/doc/ref-manual/fig/cn-logit.eps @@ -0,0 +1,568 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -0.2 def /axmax 1.2 def /aymin -3.2 def /aymax 6.2 def + +% Interpolation parameters. +/nspline 75 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +/newton % n x0 Tf => x +{ + 0 1 5 -1 roll % x0 Tf start step n + { + pop % x0 Tf + 1 index Tvar % x0 Tf Tx0 + 1 index % x0 Tf Tx0 Tf + exec % x0 Tf Ty0 + Tqv % x0 Tf y0 dy0 + dup 0.0 eq { pop pop exit } if + div % x0 Tf y0/dy0 + 2 index exch % x0 Tf x0 y0/dy0 + sub % x0 Tf x1 + dup 0.0 ne { + dup 3 index sub % x0 Tf x1 x1-x0 + 1 index div abs % x0 Tf x1 |(x1-x0)/x1| + eps le { pop exit } if + } if + exch % x0 x1 Tf + 3 -1 roll % x1 Tf x0 + pop % x1 Tf + } for + pop % x +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +/f +{ + dup Tlogit exch % T(log(p/(1-p))) Tp + 1.0 Tconst exch Tsub % T(log(p/(1-p))) T(1-p) + 1.0 Tconst exch Tdiv % T(log(p/(1-p))) T(1/(1-p)) + exch Tdiv % T((1/(1-p))/(log(p/(1-p)))) +} def + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + 0.5 aymin a2bb moveto + 0.5 aymax a2bb lineto + stroke + newpath + 1 aymin a2bb moveto + 1 aymax a2bb lineto + stroke + + % Find the minimum of the dip. + 10 0.75 { % numerator of f' + dup dup % Tp Tp Tp + 1.0 Tconst exch Tsub % Tp Tp T(1-p) + 1.0 Tconst exch Tdiv % Tp Tp T(1/(1-p)) + Tmul % Tp T(p/(1-p)) + Tln % Tp T(log(p/(1-p))) + Tmul % T(p*log(p/(1-p))) + 1.0 Tconst Tsub % T(p*log(p/(1-p))-1) + } newton + Tvar f Tq + newpath + axmin 1 index a2bb moveto + axmax 1 index a2bb lineto + stroke + pop +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 1 0 0 -1 tick 1 -1 xticklabel + 0.875 0 0 -0.25 tick + 0.75 0 0 -0.25 tick + 0.625 0 0 -0.25 tick + 0.5 0 0 -0.5 tick 0.5 -1 xticklabel + 0.375 0 0 -0.25 tick + 0.25 0 0 -0.25 tick + 0.125 0 0 -0.25 tick + + % y ticks + 0 5 -0.5 0 tick + 0 4 -1 0 tick 4 -1 yticklabel + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline 0.00001 0.499 {f} cubicsplinterpolate + nspline 0.501 0.999 {f} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-logitexp.eps b/doc/ref-manual/fig/cn-logitexp.eps new file mode 100644 index 000000000..a60a52535 --- /dev/null +++ b/doc/ref-manual/fig/cn-logitexp.eps @@ -0,0 +1,557 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -3.2 def /axmax 0.5 def /aymin -4.5 def /aymax 4.5 def + +% Interpolation parameters. +/nspline 70 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin 1 a2bb moveto + axmax 1 a2bb lineto + stroke + newpath + 0.5 ln aymin a2bb moveto + 0.5 ln aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + -2.25 0 0 -0.5 tick + -2.5 0 0 -0.5 tick + -2.75 0 0 -0.5 tick + -3 0 0 -1 tick -3 -1 xticklabel + + % y ticks + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 0.5 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 0.5 yticklabel + 0 -3 -0.5 0 tick +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin -0.694 { + dup Texpm1 Tneg % Tx T(1-e^x) + 1 index Texp Tlogit % Tx T(1-e^x) T(log(e^x/(1-e^x))) + Tmul Tdiv % T(x/((1-e^x)*log((e^x/(1-e^x))))) + } cubicsplinterpolate + nspline -0.693 -.0001 { + dup Texpm1 Tneg % Tx T(1-e^x) + 1 index Texp Tlogit % Tx T(1-e^x) T(log(e^x/(1-e^x))) + Tmul Tdiv % T(x/((1-e^x)*log((e^x/(1-e^x))))) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-logithalf.eps b/doc/ref-manual/fig/cn-logithalf.eps new file mode 100644 index 000000000..45c6cfa7d --- /dev/null +++ b/doc/ref-manual/fig/cn-logithalf.eps @@ -0,0 +1,514 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -0.75 def /axmax 0.75 def /aymin -3.2 def /aymax 6.2 def + +% Interpolation parameters. +/nspline 90 def % must be even here to avoid zero +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + -0.5 aymin a2bb moveto + -0.5 aymax a2bb lineto + stroke + newpath + 0.5 aymin a2bb moveto + 0.5 aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.5 0 0 -1 tick 0.5 -1 xticklabel + 0.375 0 0 -0.25 tick + 0.25 0 0 -0.5 tick + 0.125 0 0 -0.25 tick + -0.125 0 0 -0.25 tick + -0.25 0 0 -0.5 tick + -0.375 0 0 -0.25 tick + -0.5 0 0 -1 tick -0.5 -1 xticklabel + + % y ticks + 0 5 -0.5 0 tick + 0 4 -1 0 tick 4 -1 yticklabel + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline -.499 .499 { + dup dup % Tx Tx Tx + dup Tmul % Tx Tx T(x^2) + 4.0 Tconst Tmul % Tx Tx T(4x^2) + 1.0 Tconst exch Tsub % Tx Tx T(1-4x^2) + Tdiv % Tx T(x/(1-4x^2)) + exch Tlogithalf % T(x/(1-4x^2)) T(log((1/2+x)/(1/2-x))) + Tdiv + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/cn-loglogistic.eps b/doc/ref-manual/fig/cn-loglogistic.eps new file mode 100644 index 000000000..6fb83712a --- /dev/null +++ b/doc/ref-manual/fig/cn-loglogistic.eps @@ -0,0 +1,520 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -3.5 def /aymax 1.5 def + +% Interpolation parameters. +/nspline 40 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin 1 a2bb moveto + axmax 1 a2bb lineto + stroke + newpath + axmin 0 axmin sub a2bb moveto + axmax 0 axmax sub a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 1 -1 0 tick 1 1 yticklabel + 0 -1 -1 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel + 0 -3 -1 0 tick +grestore + +gsave + 1 0 0 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax { + dup Tneg Texp % Tx T(e^-x) + dup 1.0 Tconst Tadd % Tx T(e^-x) T(1+e^-x) + 1 index Tln1p % Tx T(e^-x) T(1+e^-x) T(log(1+e^-x)) + Tmul % Tx T(e^-x) T((1+e^-x)*log(1+e^-x)) + Tdiv % Tx T(e^-x/((1+e^-x)*log(1+e^-x))) + Tmul % T(x*e^-x/((1+e^-x)*log(1+e^-x))) + Tneg % T(-x*e^-x/((1+e^-x)*log(1+e^-x))) + } cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/expm1.eps b/doc/ref-manual/fig/expm1.eps new file mode 100644 index 000000000..5659358de --- /dev/null +++ b/doc/ref-manual/fig/expm1.eps @@ -0,0 +1,548 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -1.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 20 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin -1 a2bb moveto + axmax -1 a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 2 1 0 tick 2 1 yticklabel + 0 1 1 0 tick + 0 -1 1 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax {Texpm1} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/log1mexp.eps b/doc/ref-manual/fig/log1mexp.eps new file mode 100644 index 000000000..78fdc5979 --- /dev/null +++ b/doc/ref-manual/fig/log1mexp.eps @@ -0,0 +1,530 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -2.2 def /axmax 0.5 def /aymin -2.8 def /aymax 0.5 def + +% Interpolation parameters. +/nspline 70 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 1 1 0 tick + 0 -1 1 0 tick -1 1 yticklabel + 0 -2 1 0 tick -2 1 yticklabel +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin -.001 {Texp Tneg Tln1p} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/log1p.eps b/doc/ref-manual/fig/log1p.eps new file mode 100644 index 000000000..b958b2976 --- /dev/null +++ b/doc/ref-manual/fig/log1p.eps @@ -0,0 +1,546 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -1.2 def /axmax 2.2 def /aymin -3.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 70 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + -1 aymin a2bb moveto + -1 aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + + % y ticks + 0 2 -1 0 tick + 0 1 -1 0 tick 1 -1 yticklabel + 0 -1 -1 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel + 0 -3 -1 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline -0.99 axmax {Tln1p} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/log1pexp.eps b/doc/ref-manual/fig/log1pexp.eps new file mode 100644 index 000000000..1bde1cb5f --- /dev/null +++ b/doc/ref-manual/fig/log1pexp.eps @@ -0,0 +1,450 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -1.8 def /aymax 2.8 def + +% Interpolation parameters. +/nspline 20 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont % encoding => encoding + { + dup 45 /minus put % replace hyphen by minus + } reencodefont + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -1 0 tick + 0 -1 -1 0 tick -1 -1 yticklabel +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + nspline axmin axmax {Texp Tln1p} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/logistic.eps b/doc/ref-manual/fig/logistic.eps new file mode 100644 index 000000000..9ef061249 --- /dev/null +++ b/doc/ref-manual/fig/logistic.eps @@ -0,0 +1,457 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -0.5 def /aymax 1.2 def + +% Interpolation parameters. +/nspline 20 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogistic % Tx => T(1/(1+e^{-x})) +{ + 0.0 Tconst exch Tsub Texp % T(e^{-x}) + 1.0 Tconst Tadd % T(1+e^{-x}) + 1.0 Tconst exch Tdiv % T(1/(1+e^{-x})) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin 1 a2bb moveto + axmax 1 a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 1 -1 0 tick 1 -1 yticklabel + 0 0.75 -0.5 0 tick + 0 0.5 -0.5 0 tick + 0 0.25 -0.5 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax {Tlogistic} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/logistichalf.eps b/doc/ref-manual/fig/logistichalf.eps new file mode 100644 index 000000000..47e03114f --- /dev/null +++ b/doc/ref-manual/fig/logistichalf.eps @@ -0,0 +1,457 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto +llx ury lineto +urx ury lineto +urx lly lineto +closepath +clip + +% Axes. +/axmin -4.5 def /axmax 4.5 def /aymin -0.75 def /aymax 0.75 def + +% Interpolation parameters. +/nspline 8 def +/linearsplinterpoint { linpoint } def % i n => s_{i,n} +/cubicsplinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + 2.718281828 exch exp 1 sub +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogistic % Tx => T(1/(1+e^{-x})) +{ + 0.0 Tconst exch Tsub Texp % T(e^{-x}) + 1.0 Tconst Tadd % T(1+e^{-x}) + 1.0 Tconst exch Tdiv % T(1/(1+e^{-x})) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +/linearsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0 1 n {/i exch def + i n linearsplinterpoint Tconst + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb Tq exch Tq exch + i 0 eq { moveto } { lineto } ifelse + } for + stroke + end +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 6 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + 0.0 0 n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 + 1 index Tq % Tx0 Ty0 x0 + 1 index Tq % Tx0 Ty0 x0 y0 + moveto % Tx0 Ty0 + 0 1 n 1 sub {/i exch def % Tx0 Ty0 + % Construct a cubic curve segment: + % c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, + % Note that + % c(0) = p0, c'(0) = 3 p1 - 3 p0, + % c(1) = p1, c'(1) = 3 p3 - 3 p2, + % so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and + % p1 = p0 + c'(0)/3, + % p2 = p3 - c'(1)/3. + % + % Compute Tx3 and Ty3. + 1.0 i n cubicsplinter + fxwidth Tconst Tmul fxmin Tconst Tadd + dup Tf Ta2bb % Tx0 Ty0 Tx3 Ty3 + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 + % Draw the curve. + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 + 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 + curveto % Tx3 Ty3 + } for + pop pop % --- + stroke + end +} def + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/cubicsplinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + cubicsplinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + cubicsplinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin 0.5 a2bb moveto + axmax 0.5 a2bb lineto + stroke + newpath + axmin -0.5 a2bb moveto + axmax -0.5 a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 4 0 0 -1 tick 4 -1 xticklabel + 3 0 0 -1 tick + 2 0 0 -1 tick 2 -1 xticklabel + 1 0 0 -1 tick + -1 0 0 1 tick + -2 0 0 1 tick -2 1 xticklabel + -3 0 0 1 tick + -4 0 0 1 tick -4 1 xticklabel + + % y ticks + 0 0.5 -1 0 tick 0.5 -1 yticklabel + 0 0.25 -0.5 0 tick + 0 -0.25 -0.5 0 tick + 0 -0.5 -1 0 tick -0.5 -1 yticklabel +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax {Tlogistic 0.5 Tconst Tsub} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/logit.eps b/doc/ref-manual/fig/logit.eps new file mode 100644 index 000000000..cdcd2f953 --- /dev/null +++ b/doc/ref-manual/fig/logit.eps @@ -0,0 +1,537 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -0.2 def /axmax 1.2 def /aymin -4.2 def /aymax 4.2 def + +% Interpolation parameters. +/nspline 75 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +/newton % n x0 Tf => x +{ + 0 1 5 -1 roll % x0 Tf start step n + { + pop % x0 Tf + 1 index Tvar % x0 Tf Tx0 + 1 index % x0 Tf Tx0 Tf + exec % x0 Tf Ty0 + Tqv % x0 Tf y0 dy0 + dup 0.0 eq { pop pop exit } if + div % x0 Tf y0/dy0 + 2 index exch % x0 Tf x0 y0/dy0 + sub % x0 Tf x1 + dup 0.0 ne { + dup 3 index sub % x0 Tf x1 x1-x0 + 1 index div abs % x0 Tf x1 |(x1-x0)/x1| + eps le { pop exit } if + } if + exch % x0 x1 Tf + 3 -1 roll % x1 Tf x0 + pop % x1 Tf + } for + pop % x +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 3 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 3 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + 1 aymin a2bb moveto + 1 aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 1 0 0 -1 tick 1 -1 xticklabel + 0.875 0 0 -0.25 tick + 0.75 0 0 -0.25 tick + 0.625 0 0 -0.25 tick + 0.5 0 0 -0.5 tick 0.5 -1 xticklabel + 0.375 0 0 -0.25 tick + 0.25 0 0 -0.25 tick + 0.125 0 0 -0.25 tick + + % y ticks + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel + 0 -3 -0.5 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline 0.00001 0.999 {Tlogit} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/logitexp.eps b/doc/ref-manual/fig/logitexp.eps new file mode 100644 index 000000000..feadeab86 --- /dev/null +++ b/doc/ref-manual/fig/logitexp.eps @@ -0,0 +1,544 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -3.2 def /axmax 0.5 def /aymin -4.5 def /aymax 4.5 def + +% Interpolation parameters. +/nspline 40 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logistic % x => 1/(1+e^{-x}) +{ + 0 exch sub 2.718281828 exch exp 1 add 1 exch div +} def + +/logit % p => log(p/(1-p)) +{ + dup -1.0 logistic lt % p (plogistic(1)) + or { + dup 1.0 exch sub % p 1-p + div ln % log(p/(1-p)) + } { + dup 2.0 mul % p 2p + 1.0 exch sub % p 1-2p + exch div % (1-2p)/p + ln1p % log1p((1-2p)/p) + 0.0 exch sub % -log1p((1-2p)/p) + } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogit % Tp => T(log(p/(1-p))) +{ + dup Tq -1.0 logistic lt % Tp (plogistic(1)) + or { + dup 1.0 Tconst exch Tsub % Tp T(1-p) + Tdiv Tln % T(log(p/(1-p))) + } { + dup 2.0 Tconst Tmul % Tp T2p + 1.0 Tconst exch Tsub % Tp T(1-2p) + exch Tdiv % T((1-2p)/p) + Tln1p % T(log1p((1-2p)/p)) + 0.0 Tconst exch Tsub % T(-log1p((1-2p)/p)) + } ifelse +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + -2.25 0 0 -0.5 tick + -2.5 0 0 -0.5 tick + -2.75 0 0 -0.5 tick + -3 0 0 -1 tick -3 -1 xticklabel + + % y ticks + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 0.5 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 0.5 yticklabel + 0 -3 -0.5 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin -.001 {Texp Tlogit} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/logithalf.eps b/doc/ref-manual/fig/logithalf.eps new file mode 100644 index 000000000..48778cca8 --- /dev/null +++ b/doc/ref-manual/fig/logithalf.eps @@ -0,0 +1,506 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -0.75 def /axmax 0.75 def /aymin -3.2 def /aymax 3.2 def + +% Interpolation parameters. +/nspline 90 def % must be even here to avoid zero +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp { + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptotes. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + -0.5 aymin a2bb moveto + -0.5 aymax a2bb lineto + stroke + newpath + 0.5 aymin a2bb moveto + 0.5 aymax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 0.5 0 0 -1 tick 0.5 -1 xticklabel + 0.375 0 0 -0.25 tick + 0.25 0 0 -0.5 tick + 0.125 0 0 -0.25 tick + -0.125 0 0 -0.25 tick + -0.25 0 0 -0.5 tick + -0.375 0 0 -0.25 tick + -0.5 0 0 -1 tick -0.5 -1 xticklabel + + % y ticks + 0 5 -0.5 0 tick + 0 4 -1 0 tick 4 -1 yticklabel + 0 3 -0.5 0 tick + 0 2 -1 0 tick 2 -1 yticklabel + 0 1 -0.5 0 tick + 0 -1 -0.5 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline -.499 .499 {Tlogithalf} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/fig/loglogistic.eps b/doc/ref-manual/fig/loglogistic.eps new file mode 100644 index 000000000..4e0b611a4 --- /dev/null +++ b/doc/ref-manual/fig/loglogistic.eps @@ -0,0 +1,514 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 180 60 +%%BeginProlog + +% Bounding box parameters. +/llx 0 def /lly 0 def /urx 180 def /ury 60 def +/bbwidth urx llx sub def /bbheight ury lly sub def +newpath +llx lly moveto llx ury lineto urx ury lineto urx lly lineto closepath +clip + +% Axes. +/axmin -2.2 def /axmax 2.2 def /aymin -3.5 def /aymax 0.5 def + +% Interpolation parameters. +/nspline 40 def +/splinterpoint { chebypoint } def % i n => s_{i,n} + +% Derived axis parameters. +/awidth axmax axmin sub def +/aheight aymax aymin sub def + +% 1pt margin on either side for arrow heads. +/a2bbx bbwidth 2 sub awidth div def +/a2bby bbheight 2 sub aheight div def + +/a2bb % xa ya => xbb ybb +{ + exch a2bbx mul % ya xbb + exch a2bby mul % xbb ybb +} def + +/Ta2bb % Txa Tya => Txbb Tybb +{ + exch a2bbx Tconst Tmul % Tyf Tx2bb + exch a2bby Tconst Tmul % Txbb Tybb +} def + +% Math utilities. + +/eps 1.0 { dup 2 div dup 1.0 add 1.0 eq { pop exit } if exch pop } loop def +/sqrteps eps sqrt def +/cbrteps eps 1 3 div exp def + +/ln1p % x => log(1+x) +{ + dup 1.0 add % x 1+x + dup 1.0 eq { pop } { + dup ln % x 1+x log(1+x) + 3 -1 roll % 1+x log(1+x) x + mul % 1+x x*log(1+x) + exch % x*log(1+x) 1+x + 1.0 sub % x*log(1+x) (1+x)-1 + div % x*log(1+x)/[(1+x)-1] + } ifelse +} def + +/expm1 +{ + dup abs cbrteps gt { + % e^x - 1 + 2.718281828 exch exp 1 sub + } { dup abs sqrteps gt { + % x + x^2/2 + x^3/3 + dup dup dup dup % x x x x + mul mul 6 div % x x x^3/6 + exch dup mul 2 div % x x^3/6 x^2/2 + add add % x+x^2/2+x^3/6 + } { dup abs eps gt { + % x + x^2/2 + dup dup mul 2 div add + } { + % nothing + } ifelse } ifelse } ifelse +} def + +/logithalf % p => log((1/2+p)/(1/2-p)) +{ + dup abs 0.5 1.0 3.718281828 div sub le { + dup 2 mul % p 2p + exch 0.5 exch sub % 2p 1/2-p + div ln1p % log(1+2p/(1/2-p)) + } { + dup 0.5 add % p 1/2+p + exch 0.5 exch sub % 1/2+p 1/2-p + div ln % log((1/2+p)/(1/2-p)) + } ifelse +} def + +% Automatic differentiation. + +/T { 2 array astore } def % x dx => [x dx] +/Tq { 0 get } def % Tx => x (`position') +/Tv { 1 get } def % Tx => dx (`velocity') +/Tqv { dup 0 get exch 1 get } def % [x dx] => x dx +/Tvar { 1.0 T } def % x => [x 1] +/Tconst { 0.0 T } def % x => [x 0] + +/Tadd % Tx Ty => T(x+y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + exch % y dy dx x + 4 -1 roll add % dy dx x+y + 3 1 roll add % x+y dx+dy + T % T(x+y) +} def + +/Tmul % Tx Ty => T(x*y) +{ + Tqv % Tx y dy + 3 -1 roll % y dy Tx + Tqv % y dy x dx + 3 -1 roll % y x dx dy + 2 index mul % y x dx x*dy + exch % y x x*dy dx + 3 index mul % y x x*dy y*dx + add % y x y*dx+x*dy + 3 1 roll mul % y*dx+x*dy x*y + exch % x*y y*dx+x*dy + T % T(x*y) +} def + +/Tneg % Tx => T(-x) +{ + Tqv % x dx + 0 exch sub % x -dx + exch % -dx x + 0 exch sub % -dx -x + exch % -x -dx + T % T(-x) +} def + +/Trecip % Tx => T(1/x) +{ + Tqv exch % x dx + 1 exch div % dx 1/x + dup dup % dx 1/x 1/x 1/x + 4 1 roll % 1/x dx 1/x 1/x + 0 exch sub % 1/x dx 1/x -1/x + mul mul % 1/x -dx/x^2 + T % T(1/x) +} def + +/Tsub { Tneg Tadd } def % Tx Ty => T(x-y) +/Tdiv { Trecip Tmul } def % Tx Ty => T(x/y) + +/Tln % Tx => T(log x) +{ + Tqv % x dx + exch dup ln % dx x log(x) + 3 1 roll % log(x) dx x + div % log(x) dx/x + T % T(log x) +} def + +/Tln1p % Tx => T(log(1+x)) +{ + Tqv % x dx + exch dup % dx x x + ln1p % dx x log(1+x) + 3 1 roll % log(1+x) dx x + 1 add % log(1+x) dx 1+x + div % log(1+x) dx/(1+x) + T % T(log(1+x)) +} def + +/Texp % Tx => T(e^x) +{ + Tqv % x dx + exch 2.718281828 exch exp exch % e^x dx + 1 index mul % e^x e^x*dx + T % T(e^x) +} def + +/Texpm1 % Tx => T(e^x-1) +{ + Tqv % x dx + exch dup expm1 % dx x e^x-1 + 3 1 roll % e^x-1 dx x + 2.718281828 exch exp % e^x-1 dx e^x + mul % e^x-1 e^x*dx + T % T(e^x-1) +} def + +/Tsin % Tx => T(sin(x)) +{ + Tqv % x dx + exch dup % dx x x + sin exch cos % dx sin(x) cos(x) + 3 -1 roll % sin(x) cos(x) dx + 0.017453292519943295 mul + mul % sin(x) cos(x)*dx + T % T(sin(x)) +} def + +/Tcos % Tx => T(cos(x)) +{ + Tqv % x dx + exch dup % dx x x + cos exch sin % dx cos(x) sin(x) + 3 -1 roll % cos(x) sin(x) dx + 0.017453292519943295 mul + mul 1 exch sub % cos(x) -sin(x)*dx + T % T(cos(x)) +} def + +/Tlogithalf % Tp => T(log((1/2+p)/(1/2-p))) +{ + dup Tq abs 0.5 1.0 3.718281828 div sub le { + dup 2.0 Tconst Tmul % Tp T(2p) + exch 0.5 Tconst exch Tsub % T(2p) T(1/2-p) + Tdiv Tln1p % T(log(1+2p/(1/2-p))) + } { + dup 0.5 Tconst Tadd % T(p) T(1/2+p) + exch 0.5 Tconst exch Tsub % T(1/2+p) T(1/2-p) + Tdiv Tln % T(log((1/2+p)/(1/2-p))) + } ifelse +} def + +/Tlerp % Tt fxmin fxmax => Tx +{ + 1 index sub Tconst % Tt fxmin T(fxmax-fxmin) + 3 -1 roll Tmul % fxmin T((fxmax-fxmin)*t) + exch Tconst Tadd % T(fxmin+(fxmax-fxmin)*t) +} def + +/Tlogistic % Tx => T(1/(1+e^{-x})) +{ + 0.0 Tconst exch Tsub Texp % T(e^{-x}) + 1.0 Tconst Tadd % T(1+e^{-x}) + 1.0 Tconst exch Tdiv % T(1/(1+e^{-x})) +} def + +% Interpolation points. + +/linpoint { div } def % i n => s_{n,i} + +/chebypoint % i n => s_{n,i} +{ + exch % n i + dup 0 eq { + pop pop 0.0 + } { + 2 copy eq { + pop pop 1.0 + } { + 2 mul 1 sub % n 2i-1 + exch 2 mul % 2i-1 2n + div % (2i-1)/(2i) + 180 mul cos % cos(pi*(2i-1)/(2n)) + 1 exch sub % 1-cos(pi*(2i-1)/(2n)) + 2 div % [1-cos(pi*(2i-1)/(2n))]/2 + } ifelse + } ifelse +} def + +% Spline interpolation. + +% Compute the tangent vector of a piecewise linear interpolation +% between two consecutive spline interpolation nodes: +% +% c_i(t) := xmin + (xmax - xmin)*(x_i + (x_{i+1} - x_i)*t) +% c_i(1) = c_{i-1}(0) +% +/splinter % t i n => T(c_i(t)) +{ + 2 copy % t i n i n + splinterpoint % t i n x0 + 3 1 roll % t x0 i n + exch 1 add exch % t x0 i+1 n + splinterpoint % t x0 x1 + 1 index sub Tconst % t x0 T(x1-x0) + 3 -1 roll Tvar % x0 T(x1-x0) Tt + Tmul % x0 T((x1-x0)*t) + exch Tconst % T((x1-x0)*t) Tx0 + Tadd % T(x0+(x1-x0)*t) +} def + +% Evaluate the tangent vector f(fxmin + (fxmax - fxmin)*c_i(t)). +/splinterpoval % fxmin fxmax Tf t i n => x0 y0 +{ + splinter % fxmin fxmax Tf Tc + 4 2 roll % Tf Tc fxmin fxmax + Tlerp % Tf Tx0a + dup 3 -1 roll % Tx0a Tx0a Tf + exec % Tx0a Ty0a + Ta2bb % Tx0 Ty0 +} def + +% Compute control points of a cubic spline matching the starting and +% ending tangent vectors. Pops the starting vectors, keeps the ending. +% +% c(t) = (1-t)^3 p0 + 3 t (1-t)^2 p1 + 3 t^2 (1-t) p2 + t^3 p3, +% +% Note that +% +% c(0) = p0, c'(0) = 3 p1 - 3 p0, +% c(1) = p1, c'(1) = 3 p3 - 3 p2, +% +% so p0 = c(0) = (x0, y0), p3 = c(1) = (x1, y1), and +% +% p1 = p0 + c'(0)/3, +% p2 = p3 - c'(1)/3. +% +/cubicsplinterpocontrol % Tx0 Ty0 Tx3 Ty3 => Tx3 Ty3 x1 y1 x2 y2 +{ + 4 2 roll % Tx3 Ty3 Tx0 Ty0 + % Compute x1 = x1 + dx1/3. + exch Tqv % Tx3 Ty3 Ty0 x0 dx0 + 3 div add % Tx3 Ty3 Ty0 x1 + % Compute y1 = y0 + dy0/3. + exch Tqv % Tx3 Ty3 x1 y0 dy0 + 3 div add % Tx3 Ty3 x1 y1 + % Compute x2 = x3 - dx3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x3 dx3 + 3 div sub % Tx3 Ty3 x1 y1 x2 + % Compute y2 = y3 - dy3/3. + 3 index Tqv % Tx3 Ty3 x1 y1 x2 y3 dy3 + 3 div sub % Tx3 Ty3 x1 y1 x2 y2 +} def + +/cubicsplinterpostart % n fxmin fxmax Tf => Tx0 Ty0 x0 y0 +{ + 0.0 0 % n fxmin fxmax Tf t i + 6 -1 roll % fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 + 1 index Tq 1 index Tq % Tx0 Ty0 x0 y0 +} def + +/cubicsplinterpostep % Tx0 Ty0 i n fxmin fxmax Tf + % => Tx3 Ty3 x1 y1 x2 y2 x3 y3 +{ + 1.0 % Tx0 Ty0 i n fxmin fxmax Tf t + 6 -2 roll % Tx0 Ty0 fxmin fxmax Tf t i n + splinterpoval % Tx0 Ty0 Tx3 Ty3 + cubicsplinterpocontrol % Tx3 Ty3 x1 y1 x2 y2 + 5 index Tq 5 index Tq % Tx3 Ty3 x1 y1 x2 y2 x3 y3 +} def + +/cubicsplinterpostop % Tx3 Ty3 => --- +{ + pop pop +} def + +/cubicsplinterpolate % n fxmin fxmax Tf => --- +{ + 5 dict begin + /Tf exch def + /fxmax exch def + /fxmin exch def + /n exch def + /fxwidth fxmax fxmin sub def + newpath + n fxmin fxmax {Tf} cubicsplinterpostart moveto % Tx0 Ty0 + 0 1 n 1 sub { n fxmin fxmax {Tf} cubicsplinterpostep curveto } for + cubicsplinterpostop + stroke + end +} def + +% Graphics. + +/arrowhead % x y angle => --- +{ + gsave + 1 setlinecap + newpath + 3 1 roll % angle x y + moveto rotate + -2 2 rmoveto 2 -2 rlineto -2 -2 rlineto + stroke + grestore +} def + +/ticku 5 def % tick size in pt + +/tick % xa ya tx ty => --- +{ + exch ticku mul % xa ya ty dxbb + exch ticku mul % xa ya dxbb dybb + 4 2 roll a2bb % dxbb dybb xbb ybb + gsave newpath moveto rlineto stroke grestore +} def + +/ticklabel % v xa ya dxbb dybb => --- +{ + 4 2 roll a2bb % v dxbb dybb xbb ybb + newpath moveto rlineto show +} def + +/xticklabel % x ty => --- +{ + exch dup % ty x x + 4 string cvs % ty x xs + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % ty x xs llx lly urx ury + grestore + 3 -1 roll sub % ty x xs llx urx ury-lly + 3 1 roll exch add % ty x xs ury-lly urx+llx + 2 div % ty x xs ury-lly (urx+llx)/2 + 0 exch sub % ty x xs ury-lly -(urx+llx)/2 + exch % ty x xs -(urx+llx)/2 ury-lly + ticku 2 mul add % ty x xs -w/2 h + 5 -1 roll mul % x xs -w/2 h*ty + 4 -1 roll % xs -w/2 h*ty x + 0 % xs -w/2 h*ty x y + 4 2 roll % xs x y -w/2 h*ty + ticklabel +} def + +/yticklabel % y tx => --- +{ + exch dup % tx y y + 4 string cvs % tx y ys + gsave + newpath 0 0 moveto + dup true charpath + pathbbox % tx y ys llx lly urx ury + grestore + 3 -1 roll add 2 div % tx y ys llx urx (ury+lly)/2 + 0 exch sub % tx y ys llx urx -(ury+lly)/2 + 3 1 roll exch sub % tx y ys -(ury+lly)/2 urx-llx + 4 index 0 lt { + ticku 2 mul add + } { + pop ticku 2 mul + } ifelse % tx y ys -h/2 w + 5 -1 roll mul % y ys -h/2 w*tx + exch % y ys w*tx -h/2 + 4 -1 roll % ys w*tx -h/2 y + 0 % ys w*tx -h/2 y x + exch % ys w*tx -h/2 x y + 4 2 roll % ys x y w*tx -h/2 + ticklabel +} def + +/reencodefont % name font proc => font' +{ + exch dup length dict copy % name proc font' + dup /Encoding get % name proc font' encoding + dup length array copy % name proc font' encoding' + 3 -1 roll exec % name font' encoding' + 1 index exch % name font' encoding' font' + /Encoding exch put % name font' + definefont +} def + +%%EndProlog + +% Center coordinates with 1pt margin for arrow heads. +0 axmin sub 0 aymin sub a2bb 1 add exch 1 add exch translate + +% Draw reference asymptote. +gsave + 0.5 setgray + 0.25 setlinewidth + [2 3] 0 setdash + newpath + axmin axmin a2bb moveto + axmax axmax a2bb lineto + stroke +grestore + +% Draw axes. +gsave + 0.125 setlinewidth + /Times-Roman-Numeric + /Times-Roman findfont + { dup 45 /minus put } reencodefont % replace hyphen by minus + 10 scalefont setfont + + newpath axmin 0 a2bb moveto axmax 0 a2bb lineto stroke + axmax 0 a2bb 0 arrowhead + axmin 0 a2bb 180 arrowhead + newpath 0 aymin a2bb moveto 0 aymax a2bb lineto stroke + 0 aymax a2bb 90 arrowhead + 0 aymin a2bb -90 arrowhead + + % x ticks + 2 0 0 -1 tick 2 -1 xticklabel + 1.75 0 0 -0.5 tick + 1.5 0 0 -0.5 tick + 1.25 0 0 -0.5 tick + 1 0 0 -1 tick 1 -1 xticklabel + 0.75 0 0 -0.5 tick + 0.5 0 0 -0.5 tick + 0.25 0 0 -0.5 tick + -0.25 0 0 -0.5 tick + -0.5 0 0 -0.5 tick + -0.75 0 0 -0.5 tick + -1 0 0 -1 tick -1 -1 xticklabel + -1.25 0 0 -0.5 tick + -1.5 0 0 -0.5 tick + -1.75 0 0 -0.5 tick + -2 0 0 -1 tick -2 -1 xticklabel + + % y ticks + 0 -1 -1 0 tick + 0 -2 -1 0 tick -2 -1 yticklabel + 0 -3 -1 0 tick +grestore + +gsave + 0 0 1 setrgbcolor + 0.5 setlinewidth + 1 setlinecap + nspline axmin axmax {Tlogistic Tln} cubicsplinterpolate +grestore + +showpage diff --git a/doc/ref-manual/numbers.texi b/doc/ref-manual/numbers.texi index f8bf05232..ab13a002d 100644 --- a/doc/ref-manual/numbers.texi +++ b/doc/ref-manual/numbers.texi @@ -800,29 +800,32 @@ possible these procedures produce a real result from a real argument. @end deffn -@deffn procedure expm1 z -@deffnx procedure log1p z +@deffn procedure log1p z +@deffnx procedure expm1 z Equivalent to: @iftex @tex -$$\mathop{\rm expm1} z = \exp (z) - 1,$$ -$$\mathop{\rm log1p} z = \log (1 + z).$$ +\eqimage{fig/log1p}{$$\mathop{\rm log1p} z = \log (1 + z).$$} +\eqimage{fig/expm1}{$$\mathop{\rm expm1} z = \exp (z) - 1,$$} @end tex @end iftex @ifnottex @example @group -expm1 z = exp(z) - 1, log1p z = log(1 + z). +expm1 z = exp(z) - 1, @end group @end example +@image{fig/log1p} +@image{fig/expm1} + @end ifnottex However, for real numbers close to zero, these provide better -approximations than @code{(- (exp @var{z}) 1)} or @code{(log (+ 1 -@var{z}))}: +approximations than @code{(log (+ 1 @var{z}))} or @code{(- (exp +@var{z}) 1)}: @itemize @bullet @item @@ -838,7 +841,8 @@ condition number of log1p near @math{0} is near @math{1}: @iftex @tex -$$x f'(x)/f(x) = {x/(1 + x) \over \log(1 + x)}.$$ +\eqimage{fig/cn-log1p} + {$$x f'(x)/f(x) = {x/(1 + x) \over \log(1 + x)}.$$} @end tex @end iftex @ifnottex @@ -847,6 +851,8 @@ $$x f'(x)/f(x) = {x/(1 + x) \over \log(1 + x)}.$$ x f'(x)/f(x) = [x/(1 + x)]/log(1 + x). @end example +@image{fig/cn-log1p} + @end ifnottex (Conversely, the condition number of log near @math{0} approaches @math{0}, while the condition number of log1p near @math{-1} is @@ -862,7 +868,8 @@ near @math{1}: @iftex @tex -$$x f'(x)/f(x) = {x e^x \over e^x - 1}.$$ +\eqimage{fig/cn-expm1} + {$$x f'(x)/f(x) = {x e^x \over e^x - 1}.$$} @end tex @end iftex @ifnottex @@ -871,6 +878,7 @@ $$x f'(x)/f(x) = {x e^x \over e^x - 1}.$$ x f'(x)/f(x) = x e^x/(e^x - 1). @end example +@image{fig/cn-expm1} @end ifnottex @end itemize @@ -883,8 +891,8 @@ system's math library, usually below 1ulp. Equivalent to: @iftex @tex -$$\mathop{\rm log1mexp} x = \log (1 - e^x),$$ -$$\mathop{\rm log1pexp} x = \log (1 + e^x).$$ +\eqimage{fig/log1mexp}{$$\mathop{\rm log1mexp} x = \log (1 - e^x),$$} +\eqimage{fig/log1pexp}{$$\mathop{\rm log1pexp} x = \log (1 + e^x).$$} @end tex @end iftex @ifnottex @@ -896,8 +904,10 @@ log1pexp x = log (1 + e^x). @end group @end example -@end ifnottex +@image{fig/log1mexp} +@image{fig/log1pexp} +@end ifnottex Like log1p and expm1, these avoid numerical pathologies with the intermediate quantities @math{1 - e^x} and @math{1 + e^x} and inputs to log near @math{1}. @@ -918,6 +928,50 @@ only by the sign of the input and the output. This implementation gives forward relative error bounded by ten times the forward relative error bound of the system math library's log and exp, which is usually below 1ulp. + +Beware that although the forward relative error of the MIT/GNU Scheme +@emph{implementations} of these functions is bounded, these +@emph{functions} are ill-conditioned for large negative inputs: +@iftex +@tex +\nobreak\par\nobreak% +$$x f'(x)/f(x) = {\pm x e^x \over (1 \pm e^x) \log(1 \pm e^x)} + \approx x, \quad\hbox{for $x \ll 0$.}$$ +\nobreak\par\nobreak\leavevmode% +\begingroup% + % Load up the two figures into \box0 and \box1. + \setbox0=\hbox{\image{fig/cn-log1pexp}}% + \setbox1=\hbox{\image{fig/cn-log1mexp}}% + % Compute the width we have to work with here in \dimen0. + \dimen0=\hsize% + \advance\dimen0 by -\leftskip% + \advance\dimen0 by -\hangindent% + \advance\dimen0 by -\rightskip% + % Create an hbox of that width for the two figures with horizontal + % space before, between, and after. + \hbox to \dimen0{% + \hfill% + \vbox{\dimen0=\wd0 \box0 % Save width and dispense with box. + \hbox to\dimen0{\hfill Condition number of log1pexp\hfill}}% + \hfill% + \vbox{\dimen1=\wd1 \box1 % Save width and dispense with box. + \hbox to\dimen1{\hfill Condition number of log1mexp\hfill}}% + \hfill% + }% +\endgroup +@end tex +@end iftex +@ifnottex + +@example +x f'(x)/f(x) = (+/- x exp(x))/((1 +/- e^x) log(1 +/- e^x)), + --> x, for x << 0. +@end example + +@image{fig/cn-log1mexp} +@image{fig/cn-log1pexp} + +@end ifnottex @end deffn @deffn procedure logistic x @@ -926,8 +980,10 @@ Logistic and logit functions. Equivalent to: @iftex @tex -$$\mathop{\rm logistic} x = {e^x \over 1 + e^x} = {1 \over 1 + e^{-x}} = \mathop{\rm logit}\nolimits^{-1} x,$$ -$$\mathop{\rm logit} p = \log {p \over 1 - p} = \mathop{\rm logistic}\nolimits^{-1} p.$$ +\eqimage{fig/logistic} + {$$\mathop{\rm logistic} x = {e^x \over 1 + e^x} = {1 \over 1 + e^{-x}},$$} +\eqimage{fig/logit} + {$$\mathop{\rm logit} p = \log {p \over 1 - p} = \log {1 \over {1\over p} - 1}.$$} @end tex @end iftex @ifnottex @@ -949,10 +1005,11 @@ maps back from log-odds to probabilities. @itemize @bullet @item The logistic function is defined on the entire real line, but is -ill-conditioned for large @var{x}, with condition number +ill-conditioned for large negative @var{x}, with condition number @iftex @tex -$$x f'(x)/f(x) = {x e^{-x} \over 1 + e^{-x}}.$$ +\eqimage{fig/cn-logistic} + {$$x f'(x)/f(x) = {x e^{-x} \over 1 + e^{-x}}.$$} @end tex @end iftex @ifnottex @@ -961,6 +1018,8 @@ $$x f'(x)/f(x) = {x e^{-x} \over 1 + e^{-x}}.$$ x f'(x)/f(x) = x exp(-x)/[1 + exp(-x)]. @end example +@image{fig/cn-logistic} + @end ifnottex The identity @iftex @@ -989,7 +1048,8 @@ The logit function is defined on the closed unit interval @math{[0, condition number @iftex @tex -$$x f'(x)/f(x) = {1/(1 - p) \over \log (p/(1 - p))}.$$ +\eqimage{fig/cn-logit} + {$$x f'(x)/f(x) = {1/(1 - p) \over \log (p/(1 - p))}.$$} @end tex @end iftex @ifnottex @@ -998,6 +1058,8 @@ $$x f'(x)/f(x) = {1/(1 - p) \over \log (p/(1 - p))}.$$ x f'(x)/f(x) = 1/[(1 - p) log(p/(1 - p))]. @end example +@image{fig/cn-logit} + @end ifnottex The identity @iftex @@ -1027,8 +1089,10 @@ library's log, which is usually below 1ulp. Equivalent to: @iftex @tex -$$\mathop{\hbox{\rm logistic-1/2}} x = \mathop{\rm logistic}(x) - 1/2,$$ -$$\mathop{\hbox{\rm logit1/2+}} p = \mathop{\rm logit}(1/2 + p).$$ +\eqimage{fig/logistichalf} + {$$\mathop{\hbox{\rm logistic-1/2}} x = \mathop{\rm logistic}(x) - 1/2,$$} +\eqimage{fig/logithalf} + {$$\mathop{\hbox{\rm logit1/2+}} p = \mathop{\rm logit}(1/2 + p).$$} @end tex @end iftex @ifnottex @@ -1040,20 +1104,23 @@ logit1/2+ p = logit(1/2 + p). @end group @end example +@image{fig/logistichalf} +@image{fig/logithalf} + @end ifnottex Like @code{logistic} and @code{logit}, these functions are inverses of one another; unlike @code{logistic} and @code{logit}, their domains and codomains are both centered at zero. - @itemize @bullet @item The logistic-1/2 function is well-conditioned on the entire real line, with maximum condition number @math{1} at @math{0}: @iftex @tex -$$x f'(x)/f(x) = {2x e^{-x} \over 1 - e^{-2x}}.$$ +\eqimage{fig/cn-logistichalf} + {$$x f'(x)/f(x) = {2x e^{-x} \over 1 - e^{-2x}}.$$} @end tex @end iftex @ifnottex @@ -1062,6 +1129,8 @@ $$x f'(x)/f(x) = {2x e^{-x} \over 1 - e^{-2x}}.$$ x f'(x)/f(x) = 2 x e^-x / (1 - (e^-x)^2). @end example +@image{fig/cn-logistichalf} + @end ifnottex This implementation gives forward relative error bounded by 5 times the forward relative error bound of the system math library's exp, @@ -1072,7 +1141,8 @@ The logit1/2+ function is defined on @math{[-1/2, +1/2]}, and is ill-conditioned near @math{-1/2} and @math{+1/2}: @iftex @tex -$$x f'(x)/f(x) = {x / (1 - 4 x^2) \over \mathop{\rm logit}(1/2 + x)}.$$ +\eqimage{fig/cn-logithalf} + {$$x f'(x)/f(x) = {x / (1 - 4 x^2) \over \mathop{\rm logit}(1/2 + x)}.$$} @end tex @end iftex @ifnottex @@ -1081,6 +1151,8 @@ $$x f'(x)/f(x) = {x / (1 - 4 x^2) \over \mathop{\rm logit}(1/2 + x)}.$$ x f'(x)/f(x) = x/[(1 - 4 x^2) logit(1/2 + x)]. @end example +@image{fig/cn-logithalf} + @end ifnottex For points near @math{-1/2} or @math{+1/2}, it may be better to compute logit of a point near @math{0} instead. @@ -1095,8 +1167,10 @@ which is usually below 1ulp. Equivalent to: @iftex @tex -$$\mathop{\hbox{\rm log-logistic}} x = \log \mathop{\rm logistic}(x) = \log [1/(1 + e^{-x})],$$ -$$\mathop{\hbox{\rm logit-exp}} x = \mathop{\rm logit}(e^x) = \log [e^x/(1 - e^x)].$$ +\eqimage{fig/loglogistic} + {$$\eqalign{\mathop{\hbox{\rm log-logistic}} x &= \log \mathop{\rm logistic}(x) \cr&= \log [1/(1 + e^{-x})],}$$} +\eqimage{fig/logitexp} + {$$\eqalign{\mathop{\hbox{\rm logit-exp}} x &= \mathop{\rm logit}(e^x) \cr&= \log [e^x/(1 - e^x)].}$$} @end tex @end iftex @ifnottex @@ -1117,10 +1191,11 @@ one another. @item The log-logistic function maps log-odds on the extended real line to log-probability on the nonpositive half of the extended real line, and -is ill-conditioned for positive @var{x}: +is ill-conditioned for large positive @var{x}: @iftex @tex -$$x f'(x)/f(x) = {-x e^{-x} \over (1 + e^{-x}) \log (1 + e^{-x})}.$$ +\eqimage{fig/cn-loglogistic} + {$$x f'(x)/f(x) = {-x e^{-x}/(1 + e^{-x}) \over \log (1 + e^{-x})}.$$} @end tex @end iftex @ifnottex @@ -1129,15 +1204,18 @@ $$x f'(x)/f(x) = {-x e^{-x} \over (1 + e^{-x}) \log (1 + e^{-x})}.$$ x f'(x)/f(x) = (-x exp(-x))/[(1 + exp(-x)) log(1 + exp(-x))] @end example +@image{fig/cn-loglogistic} + @end ifnottex @item The logit-exp function maps log-probability on the nonpositive half of the extended real line to log-odds on the extended real line, and is -ill-conditioned near zero: +ill-conditioned near @math{\log(1/2)}: @iftex @tex -$$x f'(x)/f(x) = {x \over (1 - e^x) \log [e^x/(1 - e^x)]}.$$ +\eqimage{fig/cn-logitexp} + {$$x f'(x)/f(x) = {x/(1 - e^x) \over \log [e^x/(1 - e^x)]}.$$} @end tex @end iftex @ifnottex @@ -1146,6 +1224,8 @@ $$x f'(x)/f(x) = {x \over (1 - e^x) \log [e^x/(1 - e^x)]}.$$ x f'(x)/f(x) = x/[(1 - exp(x)) log(exp(x)/(1 - exp(x)))] @end example +@image{fig/cn-logitexp} + @end ifnottex @end itemize diff --git a/doc/ref-manual/scheme.texinfo b/doc/ref-manual/scheme.texinfo index 80cd248e8..361e85a9c 100644 --- a/doc/ref-manual/scheme.texinfo +++ b/doc/ref-manual/scheme.texinfo @@ -62,8 +62,52 @@ Documentation License.'' @contents @tex -\global\urefurlonlylinktrue -\global\def\urlcolor{0 0 1} % blue +\ifx\urefurlonlylinktrue\undefined\else + \global\urefurlonlylinktrue + \global\def\urlcolor{0 0 1} % blue +\fi + +% \eqimage{foo}{$$f_{a,b}(x) = \int_0^1 e^{-2\pi i t} \,dt.$$} +% +% Displays foo.eps to the right of the equation. +% +\global\long\def\eqimage#1#2{% + \par\leavevmode% + % Load up the image into box 0. + \setbox0=\hbox{\image{#1}}% + % Calculate the width available to us for the pair as \dimen0. + \dimen0=\hsize% + \advance\dimen0 by -\leftskip% + \advance\dimen0 by -\hangindent% + \advance\dimen0 by -\rightskip% + % Calculate the width available for the display alone as \dimen1. + \dimen1=\dimen0 \advance\dimen1 by -\wd0 + % Set the display into box 1. + \setbox1=\vbox{ + % Narrow ourselves to \dimen1-2em. + \hsize\dimen1 \advance\hsize by -2em + % Avoid interline skips for displays. + \abovedisplayskip=0pt + \belowdisplayskip=0pt + \abovedisplayshortskip=0pt + \belowdisplayshortskip=0pt + % Set the display. + #2 + }% + % Calculate the higher of the two for the height of our vboxes as + % \dimen2. + \ifdim\ht0>\ht1 \dimen2=\ht0 \else \dimen2=\ht1 \fi + % Set the display (\box1) and figure (\box0) into an hbox as wide as + % we can (\dimen0) and as high the higher of the two (\dimen2), with + % fill between them and on either side, and vertically centred. + \hbox to \dimen0{% + \hfill% + \vbox to \dimen2{\vss\box1\vss}% + \hfill% + \vbox to \dimen2{\vss\box0\vss}% + \hfill% + }% +} @end tex @ifnottex