Plotting Weierstrass function

The pst-func package knows \psWeierstrass(x0,x1)[a]{a or b}. It uses the function from http://mathworld.wolfram.com/WeierstrassFunction.html or, if the optional argument is given, the original one, seen here http://en.wikipedia.org/wiki/Weierstrass_function:

\documentclass[pstricks,border=10pt]{standalone}
\usepackage{pst-func}   
\begin{document}

\psset{yunit=10,xunit=5}
\begin{pspicture}(-0.1,-0.5)(2.1,0.5)
\psaxes[Dx=0.2,Dy=0.1,ticksize=-4pt 0,labelFontSize=\scriptstyle]{->}(0,0)(0,-0.5)(2.1,0.5)
\psWeierstrass[linecolor=red](0,2){2}
\psWeierstrass[linecolor=green](0,2){3}
\psWeierstrass[linecolor=blue](0,2){4}
\end{pspicture}

\end{document}

Run the example with xelatex or latex->dvips->ps2pdf. You need the latest version of pst-funx.tex from http://texnik.dante.de/tex/generic/pst-func/ or tomorrows update of TeX Live/MiKTeX.

output

and the same with the original Weierstraß definition and a variable interation number:

\documentclass{article}
\usepackage{ifxetex} 
\ifxetex\usepackage{fontspec}\else\usepackage[utf8]{inputenc}\fi
\usepackage{pst-func}   
\begin{document}

The original Weierstraß function
\[ f(x)= \sum_{n=0}^\infty a^n \cos(b^n \pi x) \]

\psset{unit=2cm,linewidth=0.5pt,plotpoints=5000}
\begin{pspicture}(-2.1,-2.1)(2.1,2.1)
\psaxes[Dx=0.5,Dy=0.5,ticksize=-2pt 0,labelFontSize=\scriptstyle]{->}(0,0)(-2,-2)(2,2)
\psWeierstrass[linecolor=red](-2,2)[0.5]{3}
\psWeierstrass[linecolor=blue!70](-2,2)[0.5]{10}
\end{pspicture}

\end{document}

enter image description here

And now a LuaTeX version with pgf which also has a varibale number of iterations:

\documentclass[tikz,border=0.125cm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{luacode}
\begin{luacode}
function weierstrass(x0, x1, n, a, b, epsilon)
 local dx = (x1-x0)/n 
 local x = x0
 local out=assert(io.open("tmp.data","w"))
 local y,k,dy
 while (x <= x1) do
   y = 0
   k = 0
   repeat
      dy = math.pow(a,k) * math.cos(math.pow(b,k)*math.pi*x)
      y = y + dy
      k = k + 1
   until (math.abs(dy) < epsilon)
   out:write(x, " ", y, "\string\n") 
   x = x + dx
 end
 out:close()
end
\end{luacode}

\begin{document}

\begin{tikzpicture}
\directlua{weierstrass(-2,2,5000,0.3,5,1.e-12)}%
\begin{axis}[axis lines=middle,domain=-2:2]
\addplot [thick, black, line join=round] table {tmp.data};
\end{axis}
\end{tikzpicture}

\end{document}

Here's a pgfmath function definition of the original Weierstrass function: weierstrass(x,a,b,i). i is the number of iterations to be used for approximating the function.

\documentclass{article}
\usepackage{pgfplots}

\makeatletter
\pgfmathdeclarefunction{weierstrass}{4}{%
    \pgfmathfloattofixed@{#4}%
    \afterassignment\pgfmath@x%
    \expandafter\c@pgfmath@counta\pgfmathresult pt\relax%
    \pgfmathfloatcreate{1}{0.0}{0}%
    \let\pgfmathfloat@loc@TMPr=\pgfmathresult
    \pgfmathfloatpi@%
    \let\pgfmathfloat@loc@TMPp=\pgfmathresult%
    \edef\pgfmathfloat@loc@TMPx{#1}%
    \edef\pgfmathfloat@loc@TMPa{#2}%
    \edef\pgfmathfloat@loc@TMPb{#3}%
    \pgfmathloop
        \ifnum\c@pgfmath@counta>-1\relax%
            \pgfmathfloatparsenumber{\the\c@pgfmath@counta}%
            \let\pgfmathfloat@loc@TMPn=\pgfmathresult%
            \pgfmathpow{\pgfmathfloat@loc@TMPa}{\pgfmathfloat@loc@TMPn}%
            \let\pgfmathfloat@loc@TMPe=\pgfmathresult%
            \pgfmathpow{\pgfmathfloat@loc@TMPb}{\pgfmathfloat@loc@TMPn}%
            \pgfmathmultiply{\pgfmathresult}{\pgfmathfloat@loc@TMPp}%
            \pgfmathmultiply{\pgfmathresult}{\pgfmathfloat@loc@TMPx}%
            \pgfmathdeg{\pgfmathresult}%
            \pgfmathcos{\pgfmathresult}%
            \pgfmathmultiply{\pgfmathresult}{\pgfmathfloat@loc@TMPe}%
            \pgfmathadd{\pgfmathresult}{\pgfmathfloat@loc@TMPr}%
            \let\pgfmathfloat@loc@TMPr=\pgfmathresult
            \advance\c@pgfmath@counta by-1\relax%
    \repeatpgfmathloop%
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[axis lines=middle, axis equal image, enlarge y limits=true]
\addplot [thick, black, samples=301, line join=round, domain=-2:2] {weierstrass(x,0.5,3,10)};
\end{axis}
\end{tikzpicture}
\end{document}

And here's the version from MathWorld that's implemented in PSTricks:

\documentclass{article}
\usepackage{pgfplots}

\makeatletter
\pgfmathdeclarefunction{weierstrass}{3}{%
    \pgfmathfloattofixed@{#3}%
    \afterassignment\pgfmath@x%
    \expandafter\c@pgfmath@counta\pgfmathresult pt\relax%
    \pgfmathfloatcreate{1}{0.0}{0}%
    \let\pgfmathfloat@loc@TMPa=\pgfmathresult
    \pgfmathfloatpi@%
    \let\pgfmathfloat@loc@TMPd=\pgfmathresult%
    \edef\pgfmathfloat@loc@TMPb{#1}%
    \edef\pgfmathfloat@loc@TMPc{#2}%
    \pgfmathloop
        \ifnum\c@pgfmath@counta>0\relax%
            \pgfmathfloatparsenumber{\the\c@pgfmath@counta}%
            \pgfmathpow{\pgfmathresult}{\pgfmathfloat@loc@TMPc}%
            \pgfmathfloatmultiply@{\pgfmathresult}{\pgfmathfloat@loc@TMPd}%
            \let\pgfmathfloat@loc@TMPe=\pgfmathresult%
            \pgfmathmultiply{\pgfmathresult}{\pgfmathfloat@loc@TMPb}%
            \pgfmathdeg{\pgfmathresult}%
            \pgfmathsin{\pgfmathresult}%
            \pgfmathdivide{\pgfmathresult}{\pgfmathfloat@loc@TMPe}%
            \pgfmathadd{\pgfmathresult}{\pgfmathfloat@loc@TMPa}%
            \let\pgfmathfloat@loc@TMPa=\pgfmathresult
            \advance\c@pgfmath@counta by-1\relax%
    \repeatpgfmathloop%
}
\makeatother

\begin{document}
\begin{tikzpicture}
\begin{axis}[axis lines=middle,
    xmin=0, xmax=2,
    ymin=-0.5, ymax=0.5,
    axis equal image
]
\addplot [red, samples=300, domain=0:2] {weierstrass(x,2,15)};
\addplot [green, samples=300, domain=0:2] {weierstrass(x,3,15)};
\addplot [blue, samples=300, domain=0:2] {weierstrass(x,4,15)};
\end{axis}
\end{tikzpicture}

\end{document}

Jake's method using lualatex with pgfplots. Some nonsense seems to be required to convert to and from the internal representation of numbers used by pgfplots which makes this annoying inefficient.

\documentclass[tikz,border=0.125cm]{standalone}
\usepackage{pgfplots}
\directlua{%
  function weierstrass(x, a, b, N)
    local y, n
    y = 0
    for n = 0,N do
      y = y + math.pow(a,n) * math.cos(math.pow(b, n)*math.pi*x)
    end
    return y
  end
}

\pgfmathdeclarefunction{weierstrass}{4}{%
  \begingroup%
    \pgfkeys{/pgf/number format/.cd,assume math mode,verbatim}%
    \pgfmathprintnumberto{#1}{\x}\pgfmathprintnumberto{#2}{\a}%
    \pgfmathprintnumberto{#3}{\b}\pgfmathprintnumberto{#4}{\N}%
    \edef\pgfmathresult{\directlua{tex.print("" .. weierstrass(\x,\a,\b,\N))}}%
   \expandafter\endgroup\expandafter%
    \pgfmathfloatparsenumber\expandafter{\pgfmathresult}%
}
\begin{document}

\begin{tikzpicture}
\begin{axis}[axis lines=middle, axis equal image, enlarge y limits=true]
\addplot [thick, black, samples=301, line join=round, domain=-2:2] 
  {weierstrass(x,0.5,3,100)};
\end{axis}
\end{tikzpicture}

\end{document}

enter image description here

Tags:

Plot

Tikz Pgf