updated: package xinttools
(for \xintListWithSep
) for example, needs
explicit loading: since 1.1 (2014/10/28)
, it is not loaded by xintfrac
anymore.
last edit: added a method using the fpu
library with pgfplots
, for the general \sum_n a^n*cos(b^n x)
Weierstrass function. The powers a^n
and b^n
are pre-computed as floating point numbers with xintfrac
, which also prepares the complete partial sum. I kept only 6
digits of precision as anyhow the fpu
library mantissa computations are between 4
and 7
digits of precision.
As the x
axis will be in degrees, which is what cos
and sin
use, no need here to worry about a pi
, it's all in the horizontal scale.
See bottom of answer for the result.
Taking over Charles' solution, with the difference that the powers of two are now precomputed. A partial sum expression is prepared using xint
to pass to tikz's plot
, with the fpu
library loaded.
edit: the plots now use an odd number of sample points (101
vs 100
, or 201
vs 200
); hence are better looking at x=0
. (only second image replaced, the one with n=20
).
Note: I don't know how tikz's fpu
interfaces with the plot
command, and I have noticed that with a too long partial sum (say n=30
) an error arises:Dimension too large
(but admittedly it does not make sense to handle that many terms which will be completely negligible). Thus, it seems some computations at least are not handled by the floating point library, presumably at least the additions? if everything was handled by the fpu
there would not be a Dimension too large
error, right?
Besides, I use only 200
samples for n=20
, else it is too slow.
\documentclass[multi=preview]{standalone}
\usepackage{tikz}
\usetikzlibrary{fpu}
\usepackage{xint, xinttools}
\makeatletter
% general term will compute 1/2^n*cos(2^n pi x), or 1/2^n*sin(2^n pi x)
% (where 2^n is already evaluated)
% we need pi and r to use radians.
% (I don't know if loading the tikz library fpu increased the precision of pi,
% perhaps it does not)
\def\@weierstrassgeneralterm #1#2#3{(1/#3*#2(#3*#1*pi r))}
\def\@weierstrassseries #1#2#3{%
% #1 will be \x or \y etc...
% #2=cos or sin
% #3=summation will be from 0 to #3
\xintListWithSep{+}
{\xintApply {\@weierstrassgeneralterm{#1}{#2}}
{\xintApply{\xintiiPow {2}}{\xintSeq {0}{#3}}}}%
}
% \fdef is defined by xint, it expands fully the first token. Hence no need
% to protect the \x, or \y which will be passed as argument.
% (initial version used \edef, see below)
\def\SetWeierstrass #1#2{% #1=\x or \y, etc..., #2=summation from 0 to #2
\fdef\weierstrasscos {\@weierstrassseries {#1}{cos}{#2}}%
\fdef\weierstrasssin {\@weierstrassseries {#1}{sin}{#2}}%
}%
% earlier version:
%
%\def\SetWeierstrass #1#2{% #1=\x or \y, etc..., #2=summation from 0 to #2
% \edef\weierstrasscos {\@weierstrassseries {#1}{cos}{#2}}%
% \edef\weierstrasssin {\@weierstrassseries {#1}{sin}{#2}}%
%}%
% \edef in \SetWeierstrass meant we had to use \noexpand here:
%\def\@weierstrassseries #1#2#3{%
% #1 will be \x or \y etc... \noexpand as it will then end up in an \edef
% #2=cos or sin
% #3=summation will be from 0 to #3
% \xintListWithSep{+}
% {\xintApply {\@weierstrassgeneralterm{\noexpand#1}{#2}}
% {\xintApply{\xintiiPow {2}}{\xintSeq {0}{#3}}}}%
%}
\makeatother
\begin{document}
% % debugging
% \SetWeierstrass \x{10}
% \show\weierstrasscos
% \show\weierstrasssin
% \stop
\begin{preview}
\begin{tikzpicture}\SetWeierstrass \x{0}
\draw[thick, color=lightgray,step=0.25cm,solid] (-2,-1.5) grid (2,2);
\draw[->] (-2.1,0) -- (2.1,0) ;
\draw[->] (0,-1.6) -- (0,2.1) ;
\draw[color=blue, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasscos}) ;
\draw[color=red, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasssin}) ;
\end{tikzpicture}
\begin{tikzpicture}\SetWeierstrass \x{1}
\draw[thick, color=lightgray,step=0.25cm,solid] (-2,-1.5) grid (2,2);
\draw[->] (-2.1,0) -- (2.1,0) ;
\draw[->] (0,-1.6) -- (0,2.1) ;
\draw[color=blue, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasscos}) ;
\draw[color=red, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasssin}) ;
\end{tikzpicture}
\begin{tikzpicture}\SetWeierstrass \x{2}
\draw[thick, color=lightgray,step=0.25cm,solid] (-2,-1.5) grid (2,2);
\draw[->] (-2.1,0) -- (2.1,0) ;
\draw[->] (0,-1.6) -- (0,2.1) ;
\draw[color=blue, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasscos}) ;
\draw[color=red, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasssin}) ;
\end{tikzpicture}
\begin{tikzpicture}\SetWeierstrass \x{3}
\draw[thick, color=lightgray,step=0.25cm,solid] (-2,-1.5) grid (2,2);
\draw[->] (-2.1,0) -- (2.1,0) ;
\draw[->] (0,-1.6) -- (0,2.1) ;
\draw[color=blue, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasscos}) ;
\draw[color=red, thick, domain=-2:2, samples=101, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasssin}) ;
\end{tikzpicture}
\end{preview}
% odd number of sample points to get it right at the origin.
\begin{preview}
\begin{tikzpicture}[scale=2]\SetWeierstrass \x{20}
\draw[thick, color=lightgray,step=0.25cm,solid] (-2,-1.5) grid (2,2);
\draw[->] (-2.1,0) -- (2.1,0) ;
\draw[->] (0,-1.6) -- (0,2.1) ;
\draw[color=blue, thick, domain=-2:2, samples=201, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasscos}) ;
\draw[color=red, thick, domain=-2:2, samples=201, /pgf/fpu,
/pgf/fpu/output format=fixed]
plot (\x, {\weierstrasssin}) ;
\end{tikzpicture}
\end{preview}
\end{document}


\documentclass[multi=preview]{standalone}
\usepackage{tikz}
\usetikzlibrary{fpu}
\usepackage{pgfplots}
\usepackage{xintfrac, xinttools}
\makeatletter
\def\SetWeierstrass #1#2#3#4{%
% #1=typically 'x' for pgfplots expression,
% #2=sum will be from n=0 to #2
% formula will be: sum of a^n * (cos or sin) (b^n x)
% a=#3, b=#4, may be fractions, numbers in scientific notations, fixed point ...
% their powers will be computed as float with only 6 digits precision
\def\@weierX {\noexpand #1}% in case one has some \x, rather
\def\@weierA {#3}% perhaps with an \@weierstrassgeneralterm
\def\@weierB {#4}% not using floating point numbers...
\def\@weierN {#2}%
\edef\weierstrasscos {\@weierstrassseries {cos}}%
\edef\weierstrasssin {\@weierstrassseries {sin}}%
}%
\def\@weierstrassseries #1{% #1 = cos or sin
\xintListWithSep{+}
{\xintApply{\@weierstrassgeneralterm {#1}}{\xintSeq {0}{\@weierN}}}%
}
\def\@weierstrassgeneralterm #1#2% [6] means 6 digits of precision
{(\xintFloatPow [6]{\@weierA}{#2}*% #1= cos or sin
#1(\xintFloatPow [6]{\@weierB}{#2}*\@weierX))}
\makeatother
\begin{document}
% debugging
% \SetWeierstrass x{5}{1/2}{3}
% \show\weierstrasscos
% % e.g. [was with 8 digits precision]
% % (1.0000000e0*cos(1.0000000e0*x))+(5.0000000e-1*cos(3.0000000e0*x))+
% % (2.5000000e-1*cos(9.0000000e0*x))+(1.2500000e-1*cos(2.7000000e1*x))+
% % (6.2500000e-2*cos(8.1000000e1*x))+(3.1250000e-2*cos(2.4300000e2*x)).
% \show\weierstrasssin
\begin{preview}
\begin{tikzpicture}[domain=-360:360]\SetWeierstrass {x}{10}{1/2}{3}%
\begin{axis}[xmin=-360, xmax=+360, ymin=-2, ymax=+2, width=12cm,
height=12cm, scale only axis]% ENFIN!
\addplot [color=blue, samples=601] {\weierstrasscos} ;
\addplot [color=red, samples=601] {\weierstrasssin} ;
\end{axis}
\end{tikzpicture}
\end{preview}
\begin{preview}
\begin{tikzpicture}[domain=-360:360]\SetWeierstrass {x}{0}{1/2}{3}%
\begin{axis}[xmin=-360, xmax=+360, ymin=-2, ymax=+2, width=2.8cm,
height=2.8cm, scale only axis]%
\addplot [color=blue, samples=301] {\weierstrasscos} ;
\addplot [color=red, samples=301] {\weierstrasssin} ;
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}[domain=-360:360]\SetWeierstrass {x}{1}{1/2}{3}%
\begin{axis}[xmin=-360, xmax=+360, ymin=-2, ymax=+2, width=2.8cm,
height=2.8cm, scale only axis]%
\addplot [color=blue, samples=301] {\weierstrasscos} ;
\addplot [color=red, samples=301] {\weierstrasssin} ;
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}[domain=-360:360]\SetWeierstrass {x}{2}{1/2}{3}%
\begin{axis}[xmin=-360, xmax=+360, ymin=-2, ymax=+2, width=2.8cm,
height=2.8cm, scale only axis]%
\addplot [color=blue, samples=301] {\weierstrasscos} ;
\addplot [color=red, samples=301] {\weierstrasssin} ;
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}[domain=-360:360]\SetWeierstrass {x}{3}{1/2}{3}%
\begin{axis}[xmin=-360, xmax=+360, ymin=-2, ymax=+2, width=2.8cm,
height=2.8cm, scale only axis]%
\addplot [color=blue, samples=301] {\weierstrasscos} ;
\addplot [color=red, samples=301] {\weierstrasssin} ;
\end{axis}
\end{tikzpicture}
\end{preview}
\end{document}

=)