math-rad.mklx /size: 15 Kb    last modification: 2024-01-16 09:02
1%D \module
2%D   [       file=math-rad,
3%D        version=2013.07.13,
4%D          title=\CONTEXT\ Math Macros,
5%D       subtitle=Radicals,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Math Macros / Radicals}
15
16\unprotect
17
18%D \starttyping
19%D $\sqrt[3]{10}$
20%D \stoptyping
21%D
22%D This root command will be overloaded later:
23
24%D Old stuff:
25
26% \def\rootradical{\Uroot    0 "221A } % can be done in char-def
27% \def\surdradical{\Uradical 0 "221A } % can be done in char-def
28
29% \protected\def\sqrt{\doifelsenextoptionalcs\rootwithdegree\rootwithoutdegree} % will be redefined
30
31% \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
32%   {\normalexpanded{\math_radical_common
33%      {\normalunexpanded{#1}}%
34%      {\noexpand\triggermathstyle{\number\normalmathstyle}%
35%       \normalunexpanded{#2}}}}
36
37% experimental new keyword: (maybe keywords should come after the symbol)
38%
39% \permanent\protected\def\styledrootradical#1#2% so that \text works ok ... \rootradical behaves somewhat weird
40%   {\Uroot style \normalmathstyle "0 "221A {#1}{#2}}
41
42% \permanent\protected\def\rootwithdegree[#1]{\math_radical_common{#1}}
43% \permanent\protected\def\rootwithoutdegree {\math_radical_common  {}}
44
45%D Even older stuff:
46
47% % is now a ordinary character
48%
49% \let\normalsurd\surd % \Uradical "0 "221A
50% \permanent\protected\def\surd{\normalsurd{}}
51
52%D The real thing. If needed one can control matters with one of the many
53%D \type {\Umath...} parameters.
54%D
55%D \starttyping
56%D \def\R {\Umathradicaldegreeafter\textstyle0pt}
57%D \def\RR{\Umathradicaldegreeafter\textstyle\dimexpr
58%D    \Umathradicaldegreeafter\textstyle+.1em\relax}
59%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle\dimexpr
60%D    \Umathradicaldegreeafter\textstyle+.2em\relax}
61%D
62%D $    \sqrt[3]{5}   \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
63%D $    \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
64%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
65%D
66%D \def\R  {\Umathradicaldegreeafter\textstyle
67%D            0pt}
68%D \def\RR {\Umathradicaldegreeafter\textstyle
69%D            0.95\Umathradicaldegreeafter\textstyle}
70%D \def\RRR{\frozen\Umathradicaldegreeafter\textstyle
71%D            0.9\Umathradicaldegreeafter\textstyle}
72%D
73%D $    \sqrt[3]{5}   \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
74%D $    \sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
75%D $ \RR\sqrt[3]{5} {\RRR\sqrt[3]{5}} \sqrt[3]{5} $\par
76%D
77%D \def\RR {\mathopenupparameter\Umathradicaldegreeafter{.1}}
78%D
79%D $ \sqrt[3]{5}  \RR\sqrt[3]{5}  \sqrt[3]{5} $\par
80%D $ \sqrt[3]{5} {\RR\sqrt[3]{5}} \sqrt[3]{5} $\par
81%D \stoptyping
82%D
83%D And:
84%D
85%D \starttyping
86%D \definemathradical[lsqrt][strut=yes]
87%D \definemathradical[msqrt][strut=math]
88%D \definemathradical[xsqrt][height=3ex,depth=2ex]
89%D
90%D $\sqrt[strut=no][3]{y}$
91%D $\sqrt[strut=no,n=5]{y}$
92%D $\sqrt[strut=no,n=5][6]{y}$
93%D $\sqrt[strut=math]{y}$
94%D $\sqrt[3]{y}$
95%D \stoptyping
96
97\installcorenamespace{mathradical}
98\installcorenamespace{mathradicalalternative}
99
100\installcommandhandler \??mathradical {mathradical} \??mathradical
101
102\setupmathradical
103  [\c!alternative=\v!normal,
104   \c!mpoffset=.25\exheight,
105   \c!height=\zeropoint,
106   \c!depth=\zeropoint,
107   \c!strut=\v!height,
108 % \c!mindepth=\zeropoint,
109   \c!mindepth=.20\exheight, % a reasonable default for: \im { \sqrt{1+x} + \sqrt{1-x} }
110   \c!source=\zerocount,
111   \c!left="221A,
112   \c!mathstyle=\v!normal,
113   \c!right=\zerocount,
114   \c!leftmargin=\zeropoint,
115   \c!rightmargin=\zeropoint]
116
117\appendtoks
118    \frozen\protected\instance\edefcsname\currentmathradical\endcsname{\math_radical_handle{\currentmathradical}}
119\to \everydefinemathradical
120
121\mutable\lettonothing\currentmathradical
122\mutable\lettonothing\currentmathradicaldegree
123
124\setmathignore\Umathradicaldegreebefore\plusone
125
126\installcorenamespace{mathwhateverstrut}
127
128\defcsname\??mathwhateverstrut\v!height\endcsname{\mathheightstrut}
129\defcsname\??mathwhateverstrut\v!depth \endcsname{\mathdepthstrut}
130\defcsname\??mathwhateverstrut\v!math  \endcsname{\mathstrut}
131\defcsname\??mathwhateverstrut\v!yes   \endcsname{\strut}
132%letcsname\??mathwhateverstrut\v!no    \endcsname\relax
133
134\tolerant\protected\def\math_radical_handle#tag#*[#S#settings]#*[#degree]#:#body%
135  {\begingroup
136   \cdef\currentmathradical{#tag}%
137   \ifhastok={#settings}%
138     \lettonothing\currentmathradicaldegree
139     \setupcurrentmathradical[#settings]%
140     \ifparameter#degree\or
141        \edef\currentmathradicaldegree{#degree}%
142     \else
143        \edef\currentmathradicaldegree{\mathradicalparameter\c!n}%
144     \fi
145   \else
146     \edef\currentmathradicaldegree{#settings}%
147   \fi
148   \ifempty\currentmathradicaldegree
149     \let\currentmathradicaldegree\m_math_no_degree
150   \fi
151   \ifcase\mathradicalparameter\c!right\else
152     \let\currentmathradicaldegree\m_math_no_degree
153   \fi
154   \math_radical_alternative{%
155     \begincsname\??mathwhateverstrut\mathradicalparameter\c!strut\endcsname
156     \scratchdimen\mathradicalparameter\c!leftmargin \relax\ifzeropt\scratchdimen\else\kern\scratchdimen\fi
157     #body%
158     \scratchdimen\mathradicalparameter\c!rightmargin\relax\ifzeropt\scratchdimen\else\kern\scratchdimen\fi
159   }%
160   \endgroup}
161
162\def\m_math_no_degree{{}}
163
164% for every font
165%
166% \appendtoks
167%    \Umathradicaldegreebefore\allmathstyles\zeropoint
168% \to \everymathematics
169
170% style width [options: left middle right]
171
172%D \starttyping
173%D \definemathradical[esqrt][sqrt][height=\maxdimen,depth=\maxdimen]
174%D \definemathradical[fsqrt][sqrt][height=3ex,depth=2ex]
175%D \definemathradical[ssqrt][sqrt][height=-.5pt,depth=-.5pt]
176%D
177%D \def\TestSqrt#1%
178%D   {test $      #1{x}           + #1{\sin(x)}                         $ test\par
179%D    test $      #1{x}           + #1{\sin(x)} + #1{\frac{1}{x}}       $ test\par
180%D    test $      #1{x} + #1{x^2}                                       $ test\par
181%D    test $\left(#1{x} + #1{x^2}                                \right)$ test\par}
182%D
183%D \TestSqrt\sqrt \blank % dynamic
184%D \TestSqrt\esqrt\blank % equal
185%D \TestSqrt\fsqrt\blank % fixed
186%D \TestSqrt\ssqrt\blank % squeezed
187%D \stoptyping
188
189\def\math_radical_alternative{\csname\??mathradicalalternative\mathradicalparameter\c!alternative\endcsname}
190
191% We use a strut in the degree because not all fonts have the right gaps set up but
192% as struts are sort of predictable we can now fix all fonts in the lfg file.
193
194\protected\def\math_radical_common#degree#body%
195  {\scratchcounter\ifcstok{\mathradicalparameter\c!rule}\v!symbol
196     \mathradicalparameter\c!top\relax
197   \else
198     \zerocount
199   \fi
200   \edef\xxx{\expandedmathstyleparameter\mathradicalparameter\c!mathstyle}
201   \Urooted
202     \s!height\dimexpr\ifcstok{\mathradicalparameter\c!height}\v!none\scaledpoint\else\mathradicalparameter\c!height\fi\relax
203     \s!depth \dimexpr\ifcstok{\mathradicalparameter\c!depth }\v!none\scaledpoint\else\mathradicalparameter\c!depth \fi\relax
204     \s!source\numexpr\namedboxanchor{\mathradicalparameter\c!source}\relax
205     \s!style \normalmathstyle % not needed
206     \ifzeronum\scratchcounter\else
207       top % \s!top
208     \fi
209     \ifcstok{\mathradicalparameter\c!rule}\v!no
210        norule
211     \orelse\ifcstok{\lastnamedcs}\v!bottom
212        reflected %
213     \fi
214     \zerocount \mathradicalparameter\c!left
215     \zerocount \mathradicalparameter\c!right
216     \ifzeronum\scratchcounter\else
217        \zerocount\scratchcounter
218     \fi
219     \relax
220   {\mathstrut#degree}%
221   {% we need to also adapt the strut
222    \expandedmathstyleparameter\mathradicalparameter\c!mathstyle
223    #body}}
224
225\protected\def\math_radical_mindepth
226  {\scratchdepth\mathradicalparameter\c!mindepth\relax
227   \ifzerodim\scratchdepth\else
228     \srule \s!depth\scratchdepth\s!height\zeropoint\s!width\zeropoint\relax
229   \fi}
230
231\defcsname\??mathradicalalternative\v!default\endcsname#body%
232  {\math_radical_common{\currentmathradicaldegree}{\math_radical_mindepth#body}}
233
234\defcsname\??mathradicalalternative\v!normal\endcsname#body%
235  {\edef\p_color{\mathradicalparameter\c!color}%
236   \ifempty\p_color
237     \math_radical_common{\currentmathradicaldegree}{\math_radical_mindepth#body}% {} really needed as \rootradical expands first
238   \orelse\ifempty\currentmathradicaldegree
239     \pushcolor[\p_color]%
240     \math_radical_common{}%
241     {\popcolor\math_radical_mindepth#body}%
242   \else
243     \pushcolor[\p_color]%
244     \math_radical_common{\popcolor\currentmathradicaldegree\pushcolor[\p_color]}%
245     {\popcolor\math_radical_mindepth#body}%
246   \fi}
247
248\startMPextensions
249    vardef math_radical_simple(expr w,h,d,o) =
250        (-h/2-o,h/2-o) --
251        (-h/4-o,-d-o)  --
252        (-o,h+o)       --
253        (w+o,h+o)      --
254        (w+o,h-h/10+o)
255    enddef ;
256\stopMPextensions
257
258\startuniqueMPgraphic{minifun::math:radical:default}%{...}
259    draw
260        math_radical_simple(OverlayWidth,OverlayHeight,OverlayDepth,OverlayOffset)
261      % withpen pencircle xscaled (2OverlayLineWidth) yscaled (3OverlayLineWidth/4) rotated 30
262        withpen pencircle scaled OverlayLineWidth
263      % dashed evenly
264        withcolor OverlayLineColor ;
265\stopuniqueMPgraphic
266
267% todo: spacing .. this is just an experiment (article driven)
268
269\defcsname\??mathradicalalternative\v!mp\endcsname#body% we could use dowithnextbox
270  {\begingroup
271   \scratchoffset\mathradicalparameter\c!mpoffset
272   \setbox\nextbox\mathstylehbox{#body}%
273   % we use the \overlay variables as these are passes anyway and
274   % it's more efficient than using parameters
275   \d_overlay_width    \wd\nextbox
276   \d_overlay_height   \ht\nextbox
277   \d_overlay_depth    \dp\nextbox
278   \d_overlay_offset   \scratchoffset
279   \d_overlay_linewidth\the\dimexpr\triggeredmathstyleparameter\Umathfractionrule
280   %
281   \edef\overlaylinecolor{\mathradicalparameter\c!color}%
282   %
283   \edef\p_mp{\mathradicalparameter\c!mp}%
284   %
285   \setbox\scratchbox\hpack\bgroup % todo: tag this box as sqrt
286     \uniqueMPgraphic
287       {\p_mp}%
288      %{...}%
289   \egroup
290   \scratchdimen       \wd\scratchbox
291   \scratchtopoffset   \dimexpr\scratchoffset+\dp\nextbox\relax
292   \scratchbottomoffset\dimexpr\scratchoffset+\ht\nextbox/2\relax
293   \hpack to \scratchdimen{\hss\box\nextbox\kern\scratchoffset}%
294   \kern-\scratchdimen
295   \lower\dimexpr\scratchtopoffset\box\scratchbox%
296   \ifx\currentmathradicaldegree\empty \else
297     \setbox\scratchbox\mathstylehbox{\scriptscriptstyle\currentmathradicaldegree\hss}%
298     \wd\scratchbox\scratchdimen
299     \kern-\scratchdimen
300     \raise\dimexpr\scratchbottomoffset\box\scratchbox
301   \fi
302   \endgroup}
303
304\pushoverloadmode
305
306\definemathradical[root][mp=minifun::math:radical:default]
307\definemathradical[sqrt][root]
308
309\popoverloadmode
310
311% \setupmathradical[sqrt][alternative=normal,color=darkblue]
312% \setupmathradical[sqrt][alternative=mp,color=darkgreen]
313
314%D Because I wanted to illustrate some more fun stuff another mechanism
315%D is provided as well ... let's put some dangerous tools in the hand of
316%D math jugglers like Aditya.
317
318\installcorenamespace{mathornament}
319\installcorenamespace{mathornamentalternative}
320
321\installcommandhandler \??mathornament {mathornament} \??mathornament
322
323\setupmathornament
324  [\c!alternative=\v!mp, % currently mp only .. maybe some day layer too
325   \c!mpoffset=.25\exheight]
326
327\appendtoks
328    \frozen\protected\instance\edefcsname\currentmathornament\endcsname
329      {\math_ornament_handle{\currentmathornament}}%
330\to \everydefinemathornament
331
332\protected\def\math_ornament_handle#tag#body%
333  {\begingroup
334   \cdef\currentmathornament{#tag}%
335   \csname\??mathornamentalternative\mathornamentparameter\c!alternative\endcsname{#body}%
336   \endgroup}
337
338\defcsname\??mathornamentalternative\v!mp\endcsname#body% we could use dowithnextbox
339  {\begingroup
340   \scratchoffset\mathornamentparameter\c!mpoffset
341   \setbox\nextbox\mathstylehbox{#body}%
342   \d_overlay_width    \wd\nextbox
343   \d_overlay_height   \ht\nextbox
344   \d_overlay_depth    \dp\nextbox
345   \d_overlay_offset   \scratchoffset
346   \d_overlay_linewidth\linewidth
347   \edef\overlaylinecolor{\mathornamentparameter\c!color}%
348   \edef\p_mp{\mathornamentparameter\c!mp}%
349   % the width of the graphic determines the width of the final result
350   \setbox\scratchbox\hpack{\uniqueMPgraphic{\p_mp}}% todo: add code key + tag
351   \hpack to \wd\scratchbox{\hss\box\nextbox\hss}%
352   \kern-\wd\scratchbox
353   \box\scratchbox
354   \endgroup}
355
356% \startMPextensions
357%     vardef math_ornament_hat(expr w,h,d,o,l) =
358%         image ( path p ; p :=
359%             (w/2,h + 10l) --
360%             (o + w,h + o) --
361%             (w/2,h + 7l) --
362%             (-o,h + o) --
363%             cycle ;
364%             fill p ;
365%             setbounds currentpicture to (-o,0) -- (w+o,0) -- (w+o,h+2o) -- (-o,h+2o) -- cycle ;
366%         )
367%     enddef ;
368% \stopMPextensions
369%
370% \startuniqueMPgraphic{math:ornament:hat}
371%     draw
372%         math_ornament_hat(
373%             OverlayWidth,
374%             OverlayHeight,
375%             OverlayDepth,
376%             OverlayOffset,
377%             OverlayLineWidth
378%         )
379%     withpen
380%         pencircle
381%             xscaled (2OverlayLineWidth)
382%             yscaled (3OverlayLineWidth/4)
383%             rotated 30
384%     withcolor
385%         OverlayLineColor ;
386%         draw boundingbox currentpicture;
387% \stopuniqueMPgraphic
388%
389% \definemathornament [mathhat] [mp=math:ornament:hat]
390%
391% \dorecurse{8}{$\mathhat{\blackrule[width=#1ex,color=gray]}$ }
392
393% \annuity {(x+1)} \tocharacter"20E7
394
395\integerdef\radicalbarextenderuc\privatecharactercode{radical bar extender}
396
397\integerdef\delimitedleftannuitylonguc  \privatecharactercode{delimited left annuity long}
398\integerdef\delimitedleftannuityshortuc \privatecharactercode{delimited left annuity short}
399\integerdef\delimitedrightannuitylonguc \privatecharactercode{delimited right annuity long}
400\integerdef\delimitedrightannuityshortuc\privatecharactercode{delimited right annuity short}
401
402\integerdef\delimitedbottomleftannuitylonguc  \privatecharactercode{delimited bottom left annuity long}
403\integerdef\delimitedbottomleftannuityshortuc \privatecharactercode{delimited bottom left annuity short}
404\integerdef\delimitedbottomrightannuitylonguc \privatecharactercode{delimited bottom right annuity long}
405\integerdef\delimitedbottomrightannuityshortuc\privatecharactercode{delimited bottom right annuity short}
406
407%D We now default to nice bars:
408
409\setupmathradical
410  [\c!rule=\v!symbol,
411   \c!top=\radicalbarextenderuc]
412
413\definemathradical
414  [rannuity]
415  [\c!rule=\v!yes,
416   \c!left=\zerocount,
417   \c!right=\delimitedrightannuitylonguc,
418   \c!rightmargin=.05\emwidth]
419
420\definemathradical
421  [lannuity]
422  [\c!rule=\v!yes,
423   \c!left=\delimitedleftannuitylonguc,
424   \c!right=\zerocount,
425   \c!leftmargin=.05\emwidth]
426
427\definemathradical
428  [lrannuity]
429  [\c!rule=\v!yes,
430   \c!left=\delimitedleftannuityshortuc,
431   \c!right=\delimitedrightannuitylonguc,
432   \c!leftmargin=.05\emwidth,
433   \c!rightmargin=.05\emwidth]
434
435\definemathradical
436  [rlannuity]
437  [\c!rule=\v!yes,
438   \c!left=\delimitedleftannuitylonguc,
439   \c!right=\delimitedrightannuityshortuc,
440   \c!leftmargin=.05\emwidth,
441   \c!rightmargin=.05\emwidth]
442
443\definemathradical
444  [annuity]
445  [rannuity]
446
447\definemathradical
448  [lbannuity]
449  [lannuity]
450  [\c!rule=\v!bottom,
451   \c!left=\delimitedbottomleftannuitylonguc]
452
453\definemathradical
454  [rbannuity]
455  [rannuity]
456  [\c!rule=\v!bottom,
457   \c!right=\delimitedbottomrightannuitylonguc]
458
459\definemathradical
460  [rlbannuity]
461  [rlannuity]
462  [\c!rule=\v!bottom,
463   \c!left=\delimitedbottomleftannuityshortuc,
464   \c!right=\delimitedbottomrightannuitylonguc]
465
466\definemathradical
467  [lrbannuity]
468  [lrannuity]
469  [\c!rule=\v!bottom,
470   \c!left=\delimitedbottomleftannuitylonguc,
471   \c!right=\delimitedbottomrightannuityshortuc]
472
473\protect \endinput
474