m-mathfun.mkxl /size: 7329 b    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=m-mathfun,
3%D        version=2021.02.20,
4%D          title=\CONTEXT\ Extra Modules,
5%D       subtitle=Wried Math Stuff,
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%D Occasionaly some experiment results in weird feature. It doesn't make sense
15%D to make this core functionality but if also makes no sense to throw it away. By
16%D making it a module the user can decide. It's actually an example of abusing a
17%D \LUA\ interfacing mechanism that is meant for something else.
18
19%D At some point this will move to \type {m-mathfun.lmt}:
20
21\startluacode
22    local type, load = type, load
23    local gmatch = string.gmatch
24
25    local context       = context
26    local ctx_mfunction = context.mfunctionlabeltext
27    local ctx_getvalue  = context.getvalue
28
29    local scanoptional  = tokens.scanners.optional
30    local scanargument  = tokens.scanners.argument
31
32    local createtoken   = tokens.create
33    local defined       = tokens.defined
34
35    local implement     = interfaces.implement
36
37    local compute_code  = 1
38
39    local function smart(what,name,kind)
40        if what == "value" or what == compute_code then
41            local temp = scanoptional()
42            if temp and temp ~= "" then
43                temp = "%" .. temp
44            else
45                temp = "%.6N"
46            end
47            if kind == "constant" then
48                context(temp,math[name])
49            else
50                local code = scanargument()
51                local func = load("return "..name.."("..code..")","mathfunction","t",math)
52                if type(func) == "function" then
53                    context(temp,func())
54                else
55                    context(code)
56                end
57            end
58        elseif kind == "constant" then
59          -- context[name]() -- recursion
60            name = "normal"..name
61            if defined(name) then
62                context(createtoken(name))
63            else
64                context(name)
65            end
66        else
67--          ctx_mfunction(name)
68            ctx_getvalue("normal"..name)
69        end
70    end
71
72    local template = { name = false, usage = "value", public = true, protected = true, actions = false, overload = true }
73
74    local function install(str,kind)
75        for name in gmatch(str,"[^ ,]+") do
76            template.name    = name
77            template.actions = function(what) smart(what,name,kind) end
78            implement(template)
79        end
80    end
81
82    implement {
83        name      = "installmathfunction",
84        public    = true,
85        protected = true,
86        actions   = install,
87        arguments = { "optional", "optional" },
88    }
89
90 -- install("sind cosd tand sin cos tan")
91 -- install("sqrt")
92
93    ---------------------------------------------------------
94
95    local type, load = type, load
96
97    local xmath         = xmath
98    local xcomplex      = xcomplex
99    local xdecimal      = xdecimal
100
101    local context       = context
102
103    local scanoptional  = tokens.scanners.optional
104    local scanargument  = tokens.scanners.argument
105
106    local implement     = interfaces.implement
107
108    local function mathexpr()
109        local temp = scanoptional()
110        local code = scanargument()
111        local func = load("return " .. code,"mathexpr","t",xmath)
112        if type(func) == "function" then
113            local result = func()
114            if result then
115                if temp and temp ~= "" then
116                    temp = "%" .. temp
117                else
118                    temp = "%.6N"
119                end
120                context(temp,result)
121                return
122            end
123        end
124        context(code)
125    end
126
127    local tostring    = xdecimal.tostring
128    local toengstring = xdecimal.toengstring -- todo
129
130    local function decimalexpr()
131        local temp = scanoptional()
132        local code = scanargument()
133        local func = load("return " .. code,"decimalexpr","t",xdecimal)
134        if type(func) == "function" then
135            local result = func()
136            if result then
137                result = tostring(func())
138                if temp and temp ~= "" then
139                    context("%"..temp,result)
140                else
141                    context(result)
142                end
143                return
144            end
145        end
146        context(code)
147    end
148
149    local topair = xcomplex.topair
150
151    local function complexexpr()
152        local temp = scanoptional()
153        local code = scanargument()
154        local func = load("return " .. code,"complexexpr","t",xcomplex)
155        if type(func) == "function" then
156            if temp and temp ~= "" then
157                temp = "%" .. temp
158            else
159                temp = "%.6N"
160            end
161            local result = func()
162            if result then
163                local r, i = topair(result)
164                if r == 0 then
165                    if i == 0 then
166                        context("0") -- ask MS fo prefered rendering
167                    elseif i == 1 then
168                        context("\\ii")
169                    elseif i == -1 then
170                        context("-\\ii")
171                    else
172                        context(temp.."\\ii",i)
173                    end
174                else
175                    if i == 0 then
176                        context(temp,r)
177                    elseif i == 1 then
178                        context(temp.."+\\ii",r)
179                    elseif i == -1 then
180                        context(temp.."-\\ii",r)
181                    elseif i > 0 then
182                        context(temp.."+"..temp.."\\ii",r,i)
183                    else
184                        context(temp.."-"..temp.."\\ii",r,-i)
185                    end
186                end
187                return
188            end
189        end
190        context(code)
191    end
192
193    implement {
194        name    = "mathexpr",
195        public  = true,
196        actions = mathexpr,
197    }
198
199    implement {
200        name    = "decimalexpr",
201        public  = true,
202        actions = decimalexpr,
203    }
204
205    implement {
206        name    = "complexexpr",
207        public  = true,
208        actions = complexexpr,
209    }
210
211\stopluacode
212
213%D The code that overloads \type {\sin} to behave as function (prefixed by \type
214%D {\the}) has been removed because it add overhead to its nromal usage that we
215%D don't want (think: \im {\sin (x) = \the \sin {pi/2}}. .
216
217\continueifinputfile{m-mathfun.mkxl}
218
219\usemodule[scite] \setupbodyfont[dejavu] \setuplayout[tight]
220
221\starttext
222
223\startbuffer
224\im { \sin (x)  = \luaexpr       {math.sin(math.pi/2)}    }
225\im { \sin (x)  = \luaexpr    [.4N] {math.sin(math.pi/2)} }
226\im { \sqrt(x)  = \luaexpr          {math.sqrt(2)}        }
227\im { \sqrt(x)  = \luaexpr    [.6N] {math.sqrt(2)}        }
228\im { \pi       = \mathexpr   [.40N]{pi}                  }
229\im { \sqrt(11) = \mathexpr   [.80N]{sqrt(11)}            }
230\im { \pi       = \decimalexpr[.80N]{sqrt(11)}            }
231\im { \sqrt(11) = \decimalexpr      {sqrt(11)}            }
232\im { c         = \complexexpr      {123 + new(456,789)}  }
233\stopbuffer
234
235Code:
236
237\typebuffer[option=TEX]
238
239And get:
240
241\startlines
242    \getbuffer
243\stoplines
244
245\stoptext
246