if not modules then modules = { } end modules ['cldf-pos'] = {
    version   = 1.001,
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

-- https://cse512-19s.github.io/FP-Well-Rounded/

local tostring, load, type, tonumber  = tostring, load, type, tonumber
local lpegmatch = lpeg.match
local context = context

local setmetatableindex = table.setmetatableindex

local implement         = interfaces.implement

local fromposit         = posit.fromposit
local toposit           = posit.toposit
local posittonumber     = posit.tonumber

local boolean_code      <const> = tokens.values.boolean
local float_code        <const> = tokens.values.float

local scanners          = tokens.scanners
local scanposit         = scanners.posit
local scanfloat         = scanners.float
local scaninteger       = scanners.integer
local scancsname        = scanners.csname

do -- these are only for testing and might go to a module eventually

    local codes             = tex.codes

    local global_code       <const> = tex.flagcodes["global"]

    local savelua           = token.savelua
    ----- isdefined         = token.isdefined

    local newsparse         = sparse.new
    local setsparse         = sparse.set
    ----- wipesparse        = sparse.wipe
    local restoresparse     = sparse.restore

    local registerfunction  = context.functions.register

    implement {
        name      = "positunumdef",
        public    = true,
        untraced  = true,
        protected = true,
        actions   = function(what)
            local name    = scancsname(true)
            local code    = newsparse()
            local restore = registerfunction(function() restoresparse(code) end)
            implement {
                name      = name,
                public    = true,
                protected = true,
                usage     = "value",
                actions   = function(what)
                    local n = scaninteger()
                    if what == "value" then
                        local v = fromposit(code[n])
                     -- return float_code, v
                        context("%.99g",v)
                    else
                        local v = toposit(scanfloat())
                        if what and (tonumber(what) & global_code) then
                            setsparse(code,"global",n,v)
                        else
                            savelua(restore,true) -- only once
                            setsparse(code,n,v)
                        end
                    end
                end,
            }
            codes[name] = code
        end,
    }

    do

        local p_number = lpeg.patterns.number
        local p = lpeg.Cs(
            lpeg.Cc("local new = new ; return ")
        * (
                lpeg.C(p_number) / function(s)
                    return "new(" .. s .. ")"
                end
                + lpeg.P(1)
            )^0
        )

        local t = setmetatableindex({ new = posit.new }, posit)

        local function calculate(s)
            local new = lpegmatch(p,s)
            new = load(new,nil,nil,t)
            if new then
                new = new()
                if new then
                    return new
                end
            end
            return old
        end

        implement {
            name      = "positunum",
            public    = true,
            arguments = "string",
            actions   = function(s)
                local r = calculate(s)
                local t = type(r)
                if t == "boolean" then
                    context(tostring(r))
                elseif t == "string" then
                    context(r)
                else
                    context("%N",posittonumber(r))
                end
            end
        }

        implement {
            name      = "ifpositunum",
            public    = true,
            usage     = "condition",
            arguments = "string",
            actions   = function(s)
                return boolean_code, calculate(s) and true or false
            end,
        }

    end

end

do

    local xsin = xmath.sin local xasin = xmath.asin local xsinh  = xmath.sinh local xasinh = xmath.asinh
    local xcos = xmath.cos local xacos = xmath.acos local xcosh  = xmath.cosh local xacosh = xmath.acosh
    local xtan = xmath.tan local xatan = xmath.atan local xtanh  = xmath.tanh local xatanh = xmath.atanh

    local xsqrt  = xmath.sqrt
    local xlog   = xmath.log
    local xexp   = xmath.exp
    local xpow   = xmath.pow
    local xceil  = xmath.ceil
    local xfloor = xmath.floor
    local xround = xmath.round
    local xabs   = xmath.fabs
    local xmod   = xmath.fmod
    local xrem   = xmath.remainder
    local xrad   = xmath.rad
    local xdeg   = xmath.deg
    local xatan2 = xmath.atan2

    implement { name = "pfsin",     public = true, usage = "value", actions = function() return float_code, xsin  (scanposit(true)) end }
    implement { name = "pfcos",     public = true, usage = "value", actions = function() return float_code, xcos  (scanposit(true)) end }
    implement { name = "pftan",     public = true, usage = "value", actions = function() return float_code, xtan  (scanposit(true)) end }
    implement { name = "pfasin",    public = true, usage = "value", actions = function() return float_code, xasin (scanposit(true)) end }
    implement { name = "pfacos",    public = true, usage = "value", actions = function() return float_code, xacos (scanposit(true)) end }
    implement { name = "pfatan",    public = true, usage = "value", actions = function() return float_code, xatan (scanposit(true)) end }
    implement { name = "pfsinh",    public = true, usage = "value", actions = function() return float_code, xsinh (scanposit(true)) end }
    implement { name = "pfcosh",    public = true, usage = "value", actions = function() return float_code, xcosh (scanposit(true)) end }
    implement { name = "pftanh",    public = true, usage = "value", actions = function() return float_code, xtanh (scanposit(true)) end }
    implement { name = "pfasinh",   public = true, usage = "value", actions = function() return float_code, xasinh(scanposit(true)) end }
    implement { name = "pfacosh",   public = true, usage = "value", actions = function() return float_code, xacosh(scanposit(true)) end }
    implement { name = "pfatanh",   public = true, usage = "value", actions = function() return float_code, xatanh(scanposit(true)) end }
    implement { name = "pfsqrt",    public = true, usage = "value", actions = function() return float_code, xsqrt (scanposit(true)) end }
    implement { name = "pflog",     public = true, usage = "value", actions = function() return float_code, xlog  (scanposit(true)) end }
    implement { name = "pfexp",     public = true, usage = "value", actions = function() return float_code, xexp  (scanposit(true)) end }
    implement { name = "pfceil",    public = true, usage = "value", actions = function() return float_code, xceil (scanposit(true)) end }
    implement { name = "pffloor",   public = true, usage = "value", actions = function() return float_code, xfloor(scanposit(true)) end }
    implement { name = "pfround",   public = true, usage = "value", actions = function() return float_code, xround(scanposit(true)) end }
    implement { name = "pfabs",     public = true, usage = "value", actions = function() return float_code, xabs  (scanposit(true)) end }
    implement { name = "pfrad",     public = true, usage = "value", actions = function() return float_code, xrad  (scanposit(true)) end }
    implement { name = "pfdeg",     public = true, usage = "value", actions = function() return float_code, xdeg  (scanposit(true)) end }
    implement { name = "pfatantwo", public = true, usage = "value", actions = function() return float_code, xatan2(scanposit(true),scanposit(true)) end }
    implement { name = "pfpow",     public = true, usage = "value", actions = function() return float_code, xpow  (scanposit(true),scanposit(true)) end }
    implement { name = "pfmod",     public = true, usage = "value", actions = function() return float_code, xmod  (scanposit(true),scanposit(true)) end }
    implement { name = "pfrem",     public = true, usage = "value", actions = function() return float_code, xrem  (scanposit(true),scanposit(true)) end }

end
