% --------------------------------------------------------------------------- % TeX macros implementing a standard set of PostScript transformations % made in BOP (1993--2001), Gda\'nsk, Poland -- public domain software % authors: Bogus\l{}aw Jackowski, Piotr Pianowski, Piotr Strzelczyk % e-mail contact: bop@bop.com.pl % --------------------------------------------------------------------------- % S Y N O P S I S % % In the sequel, `box' means \hbox, \vbox, \box, or \copy, `dimen' means % a sequence of dimens to be summed up; all macros mentioned below expand % to \hbox{...}, they can therefore be used wherever \hbox can be. % % 1) % x_scale and y_scale are given in percents (>0) % \zscale changes uniformly x_size and y_size (x_scale=y_scale=scale) % \xscale changes only x_size (y_scale=100) % \yscale changes only y_size (x_scale=100) % % \zscale{scale} followed by a box % \xyscale{x_scale}{y_scale} followed by a box % \yxscale{y_scale}{x_scale} followed by a box % \xscale{x_scale} followed by a box % \yscale{y_scale} followed by a box % % 2) % \xyscaleto resizes a box uniformly such that the resulting wd=dimen % \yxscaleto resizes a box uniformly such that the resulting ht=dimen % \xscaleto resizes a box horizontally such that the resulting wd=dimen % \yscaleto resizes a box verically such that the resulting ht=dimen % % \xyscaleto{dimen} followed by a box % \yxscaleto{dimen} followed by a box % \xscaleto{dimen} followed by a box % \yscaleto{dimen} followed by a box % % 3) % \revolve rotates anticlockwise the box (either \hbox or \vbox % following the command) by 90 degree; for the resulting box % width=height+depth of the original box, height=width % of the original box, and the reference point is the left top corner % of the original box; this means that revolving a box four times % yields the original box if and only if its depth is zero; % \revolvedir- is equivalent to \revolve, \revolvedir+ rotates % the box clockwise % % \revolve followed by a box % \revolvedir+ followed by a box % \revolvedir- followed by a box % \revolveleft followed by a box (equivalent to \revolvedir-) % \revolveright followed by a box (equivalent to \revolvedir+) % \revolvepi followed by a box (equivalent to \xflip\yflip % but not to \revolve\revolve) % \rotatepi followed by a box (equivalent to \revolvepi; % cf. also plain METAFONT rotatedaround and rotatedabout macros) % 4) % \rotate rotates a box by an arbitrary angle, clockwise for angle>0, % width=height=depth=0pt for the resulting box % % \rotate{angle} followed by a box % % \rotatebb rotates a box by an arbitrary angle, clockwise for angle>0; % the result is placed in a box having the dimensions of the resulting % bounding box, protrusion to the left is compensated by appropriate % shifting (see the macro \put_into_bb) % % \rotatebb{angle} followed by a box % % 5) % \xflip and \yflip flip the box horizontally and vertically, % respectively, i.e., with respect to the vertical and horizontal % axis of the box, without changing the dimensions of the \box % % \xflip followed by a box % \yflip followed by a box % % 6) % \slant slopes a box by an angle alpha such that tan(alpha)=slant, % without changing dimensions of the \box; % % \slant{slant} followed a box % % (negative argument value means slanting to the left) % % \slantbb slopes a box by an angle alpha such that tan(alpha)=slant, % the result is placed in a box having the dimensions of the resulting % bounding box, protrusion to the left is compensated by appropriate % shifting (see the macro \put_into_bb) % % \slantbb{slant} followed a box % % 7) % \clipbox clips the contents of a box that follows the command; % the macro expects three dimen parameters: the width, the height % and the depth of the resulting box % % \clipbox{width}{height}{depth} followed a box % % Any parameter can be empty; in such a case, the respective dimension % of the original box is used % --------------------------------------------------------------------------- % HISTORY: % 18 VIII 1993 ver. 0.1 % * first release % 30--31 VIII 1993 ver. 0.2 % * third parameter eliminated from \scale (via \afterassignment % and \aftergroup hackery) % * added \zscale, \xyscale, \yxscale, \xscale, and \yscale % with scaling given in percents % * added \scaleto, \xyscaleto, \yxscaleto, \xscaleto, and \yscaleto % 3 IX 1993 ver. 0.21 % * \the_scale renamed to \lastscale and made global, thus it became % available to a user % 8 IX 1993 ver. 0.22 % * all transformations return \hbox, because of currentpoint % positioning % * the old version of \scale is become undefined % * \slant and \rotate fit the new convention of parameter's % hackery -- they are assumed to be followed by an \hbox % or a \vbox % 6 XII 1993 ver. 0.23 % * \revolve added % * \rotate with \vbox patched % 10 II 1994 ver. 0.24 % * \revolvedir+, \revolvedir-, \xflip, and \yflip added % 20 III 2000 ver. 0.5 (pre-release) % * total reconstruction: % -- all macros expand to \hbox, so that it is possible to % superpose them, e.g., \xscale{200}\yscale{50}\hbox{...}; % one must remeber, however, that \rotate yields a box having % null dimensions, so an attempt to scale the result % to a given dimen will produce erroneous PostScript code % -- the possibility of changing \ht and \dp of a \vbox abolished; % such an operation yields hardly intuitive results; try, e.g.: % \hrule width\hsize % \hbox{\setbox0\hbox{\vrule height1cmwidth1cm}\ht0 0mm \box0} % \kern20mm % \hrule width\hsize % \hbox{\setbox0\vbox{\hrule height1cmwidth1cm}\ht0 0mm \box0} % -- the box expected by all macros can be a TeX box expression: % \hbox, \vbox, \box, and \copy % -- scaling height or width to a given dimension yields exact value % of the height or width, respectively (or both); this change is % backward incompatible (but reasonable, one should think) % -- all transformations store information about the position of the % lower left corner and the upper right corner of the resulting % bounding box (with respect to the base point of the transformed % box) in four globally defined macros: % \transllx, \translly, \transurx, \transury % (a piece of funny code for vector rotation was added) % -- \rotatebb and \slantbb added % 25 III 2000 ver. 0.51 % * fraction multiplication improved (speedup in trigonometric % calculations ca 30%) % * trigonometry calculations are performed in a group (otherwise using % them within another \loop ... \repeat would be inconvenient); % the result is a pair of globally defined macros (instead of dimen % registers); they expand to a series of digits (i.e., they contain % a count representation of the resulting dimen) % * \unhbox (introduced in order to reduce the level of box nesting) % should be used only in \rotatebb % * internal macro naming changed % 27 III 2000 ver. 0.52 % * a dimen parameter can be a sequence of dimens to be summed up % * \clipbox added % 7--10 X 2000 ver. 0.53 % * a bug in \slant[bb] fixed: \ht and \dp were interchanged due to % a fallacious interpretation of a slant sign (recall that in dvips % PostScript, unlike in METAFONT, `-' denotes slanting to the right, % `+' -- to the left, because the y-axis is directed downwards); % actually, the problem is much more complex: relying (unconsciously) % on dvips coordinates means, in this case, that for non-square pixels % both rotate and slant will not work -- need to be fixed! % 13 XI 2000 ver. 0.54 % * @ is a letter during reading trans macros (AMSTeX uses active @) % * local macro \undtranscode renamed to \transundcode % 9 VI 2001 ver 0.55 % * ``mnemonic'' macros added: \revolveleft, \revolveright, \revolvepi % and \rotatepi % --------------------------------------------------------------------------- \def\transspecial#1{\special{ps:#1}}% driver-oriented; default is dvips % --- \edef\transundcode{\the\catcode`\_}\catcode`\_11 \edef\transatcode{\the\catcode`\@}\catcode`\@11 % \z@ (0pt) and \p@ (1pt) are borrowed from plain % --- % a pretty general macro \def\sumto#1{\def\sum_to_what{#1}\sum_to_what=\z@\relax \sumto_} \def\sumto_{\futurelet\sum_tok\sumto__} \def\sumto__{\ifx\sum_tok\relax\else\expandafter\sumto___\fi} \def\sumto___{\afterassignment\sumto_\advance\sum_to_what} % --- \newbox\tmp_box % temporary box register \newdimen\tmp_dim % temporary dimen registers \newdimen\tmp_dim_a \newdimen\tmp_dim_b \newdimen\tmp_dim_c \newdimen\tmp_dim_d \newcount\tmp_count_a % temporary count registers \newcount\tmp_count_b \newcount\tmp_count_c \newif\ifput_into_bb % --- \def\jump_setbox{\ifvoid\tmp_box % every box is initially void \aftergroup\after_setbox \else \after_setbox \fi}% a general trick % --- \def\set_std_bb{% \xdef\transllx{\the\z@}% \xdef\translly{\ifdim\dp\tmp_box>\z@ -\fi\the\dp\tmp_box}% \xdef\transurx{\the\wd\tmp_box}% \xdef\transury{\the\ht\tmp_box}% } \def\put_into_bb#1{% #1 = operation: \unhbox for rotation, \box for slanting \setbox\tmp_box\hbox{\kern-\transllx\rlap{#1\tmp_box}\kern\transurx}% \ht\tmp_box\transury \dp\tmp_box-\translly \relax } % --- \def\perc_scale#1#2{% #1 -- xscale, #2 -- yscale, in percents, % to be followed by an \hbox or a \vbox \def\after_setbox{% \setbox\tmp_box\hbox{% \transspecial{gsave currentpoint #2 100 div div exch #1 100 div div exch currentpoint neg #2 100 div mul exch neg #1 100 div mul exch translate #1 100 div #2 100 div scale translate}% \box\tmp_box \transspecial{grestore}}% \ifdim#1\p@=100\p@ \else % special treatment of special case (100%) \tmp_dim\wd\tmp_box \advance\tmp_dim50sp \divide\tmp_dim100 % rounding rather than floor \wd\tmp_box#1\tmp_dim \fi \ifdim#2\p@=100\p@ \else % ditto \tmp_dim\ht\tmp_box \advance\tmp_dim50sp \divide\tmp_dim100 % ditto \ht\tmp_box#2\tmp_dim \tmp_dim\dp\tmp_box \advance\tmp_dim50sp \divide\tmp_dim100 % ditto \dp\tmp_box#2\tmp_dim \fi \set_std_bb \box\tmp_box\egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% % --- \def\xyscale#1#2{\hbox\bgroup\perc_scale{#1}{#2}} \def\zscale#1{\xyscale{#1}{#1}} \def\yxscale#1#2{\xyscale{#2}{#1}} \def\xscale#1{\xyscale{#1}{100}} \def\yscale#1{\xyscale{100}{#1}} % --- {\catcode`\p12 \catcode`\t12 \gdef\PT_{pt}} \def\hull_num{\expandafter\hull_num_} \expandafter\def\expandafter\hull_num_\expandafter#\expandafter1\PT_{#1} % --- \def\find_scale#1#2{% #1 -- size after rescaling, #2 -- \wd or \ht % Finds a scale (\lastscale macro) such that the box following the macro % call would have the respective dimen (i.e., #2) equal to #1 after rescaling % NOTE: it is assumed that prior to calling \find_scale a macro % \extra_complete is defined \def\after_setbox{% \resize\tmp_dim{100\p@}{#1}{#2\tmp_box}% \xdef\lastscale{\hull_num\the\tmp_dim}\extra_complete}% \afterassignment\jump_setbox\setbox\tmp_box = } % --- \def\scaleto#1#2#3#4{% #1 -- size of dimen #2 (\wd or \ht) after scaling % #3 -- actual x-size, #4 -- actual y-size \hbox\bgroup % `initial' hbox \sumto\tmp_dim#1\relax % freeze the argument; must not be empty \setbox\tmp_box\hbox\bgroup % one more setbox in order to control % the specified dimen \def\extra_complete{% \perc_scale{#3}{#4}\box\tmp_box % finish setbox above #2\tmp_box=\tmp_dim % force the exactness of the specified dimension \set_std_bb \box\tmp_box \egroup % close `initial' hbox }% \find_scale{\tmp_dim}#2} % \def\xyscaleto#1{\scaleto{#1}\wd\lastscale\lastscale} \def\yxscaleto#1{\scaleto{#1}\ht\lastscale\lastscale} \def\xscaleto#1{\scaleto{#1}\wd\lastscale{100}} \def\yscaleto#1{\scaleto{#1}\ht{100}\lastscale} % --- \def\slant{\hbox\bgroup \put_into_bbfalse \slant_} \def\slantbb{\hbox\bgroup \put_into_bbtrue \slant_} \def\slant_#1{% #1 (slant) = tan(alpha), where alpha is the slant angle, % to be followed by a box \def\after_setbox{% \transspecial{gsave 0 currentpoint neg exch pop 0 currentpoint exch pop translate [1 0 #1 1 0 0] concat translate}% % set bounding box \dim_x\wd\tmp_box \ifdim#1\p@>\z@ \dim_t-#1\ht\tmp_box \advance\dim_x#1\dp\tmp_box \else \dim_t#1\dp\tmp_box \advance\dim_x-#1\ht\tmp_box \fi \xdef\transllx{\the\dim_t}% \xdef\translly{\ifdim\dp\tmp_box>\z@ -\fi\the\dp\tmp_box}% \xdef\transurx{\the\dim_x}% \xdef\transury{\the\ht\tmp_box}% \ifput_into_bb \put_into_bb\box \fi \box\tmp_box \transspecial{grestore}\egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% % --- \def\update_bb#1#2#3{% used in \rotate \trigcompute{-#1}{#2}{#3}% clockwise vs anti-clockwise \ifdim\transllx>\trigxresult sp\xdef\transllx{\trigxresult sp}\fi \ifdim\translly>\trigyresult sp\xdef\translly{\trigyresult sp}\fi \ifdim\transurx<\trigxresult sp\xdef\transurx{\trigxresult sp}\fi \ifdim\transury<\trigyresult sp\xdef\transury{\trigyresult sp}\fi } \def\rotate{\hbox\bgroup \put_into_bbfalse \rotate_} \def\rotatebb{\hbox\bgroup \put_into_bbtrue \rotate_} \def\rotate_#1{% #1 -- angle, % to be followed by a box \def\after_setbox{% \setbox\tmp_box\hbox{% otherwise does not work with \vbox \transspecial{gsave currentpoint currentpoint translate #1 rotate neg exch neg exch translate}% \box\tmp_box \transspecial{grestore}}% % set bounding box \xdef\transllx{\the\z@}\xdef\translly{\the\z@}% \xdef\transurx{\the\z@}\xdef\transury{\the\z@}% \update_bb{#1}{\z@}{\ht\tmp_box}% \update_bb{#1}{\z@}{-\dp\tmp_box}% \update_bb{#1}{\wd\tmp_box}{\ht\tmp_box}% \update_bb{#1}{\wd\tmp_box}{-\dp\tmp_box}% % \wd\tmp_box\z@ \ht\tmp_box\z@ \dp\tmp_box\z@ \ifput_into_bb \put_into_bb\unhbox \fi \box\tmp_box\egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% % --- \def\plus_{+} \def\minus_{-} \def\revolvedir#1{% to be followed by a box \hbox\bgroup % check parameter: \def\param_{#1}% \ifx\param_\plus_ \else \ifx\param_\minus_ \else \errhelp{I would rather suggest to stop immediately.}% \errmessage{Argument to \noexpand\revolvedir should be either + or -}% \fi\fi \def\after_setbox{% \tmp_dim_a\wd\tmp_box % prepare to revolving: \setbox\tmp_box\hbox{% \ifx\param_\plus_\kern-\tmp_dim_a\fi \box\tmp_box \ifx\param_\plus_\kern\tmp_dim_a\fi}% % compute dimensions of the box to be revolved: \tmp_dim_a\ht\tmp_box \advance\tmp_dim_a\dp\tmp_box \tmp_dim_b\ht\tmp_box \tmp_dim_c\dp\tmp_box \dp\tmp_box\z@ \ht\tmp_box\wd\tmp_box \wd\tmp_box\tmp_dim_a % revolve: \kern \ifx\param_\plus_ \tmp_dim_c \else \tmp_dim_b \fi \transspecial{gsave currentpoint currentpoint translate #190 rotate neg exch neg exch translate}% \set_std_bb \box\tmp_box \transspecial{grestore}% \kern -\ifx\param_\plus_ \tmp_dim_c \else \tmp_dim_b \fi \egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% \def\revolveleft{\revolvedir-} \def\revolveright{\revolvedir+} \def\revolvepi{\xflip\yflip} \let\revolve\revolveleft \let\rotatepi\revolvepi % --- \def\xflip{% to be followed by a box \hbox\bgroup \def\after_setbox{% \tmp_dim_a.5\wd\tmp_box % prepare to flipping: \setbox\tmp_box \hbox{\kern-\tmp_dim_a \box\tmp_box \kern\tmp_dim_a}% % flip: \kern\tmp_dim_a \transspecial{gsave currentpoint currentpoint translate [-1 0 0 1 0 0] concat neg exch neg exch translate}% \set_std_bb \box\tmp_box \transspecial{grestore}% \kern-\tmp_dim_a \egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% % --- \def\yflip{% to be followed by a box \hbox\bgroup \def\after_setbox{% \tmp_dim_a\ht\tmp_box \tmp_dim_b\dp\tmp_box \tmp_dim_c\tmp_dim_a \advance\tmp_dim_c\tmp_dim_b \tmp_dim_c.5\tmp_dim_c % prepare to flipping: \setbox\tmp_box\vbox{% \kern\tmp_dim_c\box\tmp_box\kern-\tmp_dim_c}% % flip: \advance\tmp_dim_c-\tmp_dim_b \setbox\tmp_box\hbox{% \transspecial{gsave currentpoint currentpoint translate [1 0 0 -1 0 0] concat neg exch neg exch translate}% \lower\tmp_dim_c\box\tmp_box \transspecial{grestore}}% % restore dimensions of the flipped box: \ht\tmp_box\tmp_dim_a \dp\tmp_box\tmp_dim_b \set_std_bb \box\tmp_box \egroup}% \afterassignment\jump_setbox\setbox\tmp_box = }% % --- % save TeX registers: \let\clip_wd\tmp_dim_a \let\clip_ht\tmp_dim_b \let\clip_dp\tmp_dim_c % --- \def\tracingclipcmyk{1 0 0 0} \def\clip_fix_pos#1{\transspecial{% currentpoint /clip_#1_y exch def /clip_#1_x exch def% }} \def\clip_use_pos#1{clip_#1_x clip_#1_y} \def\clip_delta#1#2{#1 #2 3 -1 roll exch sub 3 1 roll sub exch} % \def\do_clip{\transspecial{% newpath \clip_use_pos{LL} moveto \clip_delta{\clip_use_pos{UR}}{\clip_use_pos{UL}} rlineto \clip_delta{\clip_use_pos{UR}}{\clip_use_pos{LR}} rlineto \clip_delta{\clip_use_pos{LL}}{\clip_use_pos{LR}} rlineto closepath \ifx\tracingclip\unknown \else gsave \tracingclipcmyk\space setcmykcolor fill grestore \fi clip newpath% }} % \def\clip_use_dim#1{% #1 = wd, ht, or dp \ifdim\csname clip_#1\endcsname=\maxdimen \csname#1\endcsname\tmp_box \else \csname clip_#1\endcsname\fi } % \def\clip_fix_dim#1#2{% \edef\clip_use_dim_param{#2}% \ifx\clip_use_dim_param\empty #1\maxdimen\else \ifx\clip_use_dim_param\space #1\maxdimen\else \sumto#1#2\relax \fi\fi } % \def\clipbox#1#2#3{% desired height, width and depth to be followed by a box \hbox\bgroup \clip_fix_dim\clip_wd{#1}% \clip_fix_dim\clip_ht{#2}% \clip_fix_dim\clip_dp{#3}% \clipbox_ } \def\clipbox_{% \def\after_setbox{% \setbox\tmp_box\hbox{\box\tmp_box}% \clip_wd\clip_use_dim{wd}% freeze dimen \clip_ht\clip_use_dim{ht}% ditto \clip_dp\clip_use_dim{dp}% ditto \transspecial{gsave}% \rlap{% \lower \clip_dp \vbox{% \hbox to\clip_wd{\clip_fix_pos{UL}\hss\clip_fix_pos{UR}} \kern\clip_ht \kern\clip_dp \nointerlineskip \hbox to\clip_wd{\clip_fix_pos{LL}\hss\clip_fix_pos{LR}} \do_clip }% }% \wd\tmp_box=\clip_wd \ht\tmp_box=\clip_ht \dp\tmp_box=\clip_dp \set_std_bb \box\tmp_box \transspecial{grestore}\egroup}% \afterassignment\jump_setbox\setbox\tmp_box = } % --------------------------------------------------------------------------- % ``floating point arithmetic'' (excerpted from T. Rokicki): % r y % % ^ % | % | % | % | % | % 0--------------> t x % % save TeX registers: \let\dim_x\tmp_dim_a % horizontal size after scaling \let\dim_y\tmp_dim_b % vertical size after scaling \let\dim_t\tmp_dim_c % horizontal size before scaling \let\dim_r\tmp_dim_d % vertical size before scaling %\tmp_dim % register for arithmetic manipulation (already declared) % --- \def\resize % dimen registers: #1% y make y such that y/r=x/t #2% r #3% x #4% t % We have a sticky problem here: TeX doesn't do floating point arithmetic! % Our goal is to compute y = rx/t. The following loop does this reasonably % fast, with an error of at most about 16 sp (about 1/4000 pt). {% % save parameters to the internal variables: \dim_r#2\relax \dim_x#3\relax \dim_t#4\relax \tmp_dim=\dim_r \divide\tmp_dim\dim_t \dim_y=\dim_x \multiply\dim_y\tmp_dim \multiply\tmp_dim\dim_t \advance\dim_r-\tmp_dim \tmp_dim=\dim_x \loop \advance\dim_r\dim_r \divide\tmp_dim 2 \ifnum\tmp_dim>0 \ifnum\dim_r<\dim_t\else \advance\dim_r-\dim_t \advance\dim_y\tmp_dim \fi \repeat % assign result: #1\dim_y\relax } % --------------------------------------------------------------------------- % ``fixed point arithmetic'' -- fractions and trigometry, inspired by mf.web: % % save TeX registers: \let\fracint\tmp_dim \let\fracfrac\tmp_count_a \let\fracprod\tmp_count_b \def\fracpowlimit{30}% \def\fracone{1073741824}% = 2^\fracpowlimit % --- \def\fracproduct#1#2{% #1 = fraction * 2^\fracpowlimit, #2 = integer % result: macro \fracresult = floor(#1 * #2 / 2^\fracpowlimit + 1/2) % expanding to the count equivalent of the respective dimen \begingroup \fracfrac#1\relax % \fracfrac <= 2^30 \fracint#2\relax % \fracint <= \maxdimen \ifdim\fracint<0pt \fracint-\fracint\def\fracsign{-}\else\def\fracsign{}\fi \ifnum\fracone=\fracfrac \fracprod\fracint \else \advance\fracfrac\fracone % \fracfrac < 2^31 \fracprod\fracone % if \fracprod were dimen, this would yield error \divide\fracprod2 % \fracprod = 2^29 (representation of 1/2) \loop \ifodd\fracfrac \advance \fracprod\fracint \fi \divide\fracprod2 \divide\fracfrac2 \ifnum \fracfrac>1 \repeat \fi \xdef\fracresult{\fracsign\number\fracprod}% \endgroup } % --- \newdimen\onedegree \onedegree16pt % this must be consistent with the table below % save TeX registers: \let\trigangle\tmp_dim_a \let\trigxpart\tmp_dim_b \let\trigypart\tmp_dim_c \let\trigxtmp\tmp_dim \let\trigiter\tmp_count_a \def\triglimit{28}% % --- \def\trigvalarg#1{\csname argscaled:\number#1\endcsname} \def\trigvalcos#1{\csname cosscaled:\number#1\endcsname} \def\trigvalsin#1{\csname sinscaled:\number#1\endcsname} \def\defspectrig#1#2#3#4{% % #1 -- ordering number (index) % #2 -- angle in degrees * \onedegree expressed in sp; alpha=#1*2^(-20) % #3 -- floor(cosd(alpha)*2^30+1/2) (30=\fracpowlimit) % #4 -- floor(sind(alpha)*2^30+1/2) \expandafter\def\csname argscaled:#1\endcsname{#2}% \expandafter\def\csname cosscaled:#1\endcsname{#3}% \expandafter\def\csname sinscaled:#1\endcsname{#4}% } \defspectrig{1}{62914560}{536870912}{929887697} % alpha=60 \defspectrig{2}{47185920}{759250125}{759250125} % 45 \defspectrig{3}{31457280}{929887697}{536870912} % 30 \defspectrig{4}{16777216}{1032146887}{295963357} % 2^4 \defspectrig{5}{8388608}{1063292242}{149435979} % 2^3 \defspectrig{6}{4194304}{1071126243}{74900443} % 2^2 \defspectrig{7}{2097152}{1073087729}{37473049} % 2^1 \defspectrig{8}{1048576}{1073578288}{18739379} % 2^0 \defspectrig{9}{524288}{1073700939}{9370046} % 2^-1 \defspectrig{10}{262144}{1073731603}{4685068} % 2^-2 \defspectrig{11}{131072}{1073739269}{2342539} % 2^-3 \defspectrig{12}{65536}{1073741185}{1171270} % 2^-4 \defspectrig{13}{32768}{1073741664}{585635} % 2^-5 \defspectrig{14}{16384}{1073741784}{292818} % 2^-6 \defspectrig{15}{8192}{1073741814}{146409} % 2^-7 \defspectrig{16}{4096}{1073741822}{73204} % 2^-8 \defspectrig{17}{2048}{1073741823}{36602} % 2^-9 \defspectrig{18}{1024}{1073741824}{18301} % 2^-10 \defspectrig{19}{512}{1073741824}{9151} % 2^-11 \defspectrig{20}{256}{1073741824}{4575} % 2^-12 \defspectrig{21}{128}{1073741824}{2288} % 2^-13 \defspectrig{22}{64}{1073741824}{1144} % 2^-14 \defspectrig{23}{32}{1073741824}{572} % 2^-15 \defspectrig{24}{16}{1073741824}{286} % 2^-16 \defspectrig{25}{8}{1073741824}{143} % 2^-17 \defspectrig{26}{4}{1073741824}{71} % 2^-18 \defspectrig{27}{2}{1073741824}{36} % 2^-19 \defspectrig{28}{1}{1073741824}{18} % 2^-20 % --- \def\trigcompute#1#2#3{% % #1 angle in degrees (a) % #2 initial xpart (x) % #3 initial ypart (y) % result: (x',y')=(x,y) rotated a; the pair of macros % \trigxresult and \trigyresult contain x' and y', respectively; % both expand to the count equivalent of the respective dimen \begingroup \trigangle#1\onedegree \trigxpart#2\relax \trigypart#3\relax \loop \ifdim\trigangle<0sp \advance\trigangle360\onedegree \repeat \loop \ifdim\trigangle>360\onedegree \advance\trigangle-360\onedegree \repeat \ifdim\trigangle=360\onedegree \trigangle0sp \fi \ifdim\trigangle<180\onedegree \else % >= \trigxpart-\trigxpart \trigypart-\trigypart \advance\trigangle-180\onedegree \fi \ifdim\trigangle<90\onedegree \else % >= \trigxtmp\trigxpart \trigxpart-\trigypart \trigypart\trigxtmp \advance\trigangle-90\onedegree \fi \trigiter1\relax \loop \ifnum\trigvalarg\trigiter>\trigangle \else % <= \advance\trigangle-\trigvalarg\trigiter sp \trigxtmp\trigxpart % x=x*cos[i]-y*sin[i] : \fracproduct{\trigvalcos\trigiter}\trigxpart \trigxpart\fracresult sp \fracproduct{\trigvalsin\trigiter}\trigypart \advance\trigxpart-\fracresult sp % y=y*cos[i]+x*sin[i] : \fracproduct{\trigvalcos\trigiter}\trigypart \trigypart\fracresult sp \fracproduct{\trigvalsin\trigiter}\trigxtmp \advance\trigypart\fracresult sp \fi \advance\trigiter1 \ifnum\trigangle>0 \repeat % result in dimen registers: \trigxpart and \trigypart \xdef\trigxresult{\number\trigxpart}% \xdef\trigyresult{\number\trigypart}% \endgroup } % --------------------------------------------------------------------------- % restore original catcodes: \catcode`\@\transatcode \catcode`\_\transundcode % --------------------------------------------------------------------------- \endinput