Minkowski question-mark function: Difference between revisions

Add C# implementation
(J: it's not ieee 754 representation, it's the algorithm)
(Add C# implementation)
 
(18 intermediate revisions by 6 users not shown)
Line 30:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">-V MAXITER = 151
 
F minkowski(x) -> Float
Line 119:
print(‘#2.16 #2.16’.format(minkowski(0.5 * (1 + sqrt(5))), 5.0 / 3.0))
print(‘#2.16 #2.16’.format(minkowski_inv(-5.0 / 9.0), (sqrt(13) - 7) / 6))
print(‘#2.16 #2.16’.format(minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))))</langsyntaxhighlight>
 
{{out}}
Line 128:
</pre>
 
=={{header|C#}}==
{{trans|Go}}
<syntaxhighlight lang="C#">
using System;
 
class Program
{
const int MAXITER = 151;
 
static double Minkowski(double x)
{
if (x > 1 || x < 0)
{
return Math.Floor(x) + Minkowski(x - Math.Floor(x));
}
ulong p = (ulong)x;
ulong q = 1;
ulong r = p + 1;
ulong s = 1;
double d = 1.0;
double y = (double)p;
while (true)
{
d = d / 2;
if (y + d == y)
{
break;
}
ulong m = p + r;
if (m < 0 || p < 0)
{
break;
}
ulong n = q + s;
if (n < 0)
{
break;
}
if (x < (double)m / (double)n)
{
r = m;
s = n;
}
else
{
y = y + d;
p = m;
q = n;
}
}
return y + d;
}
 
static double MinkowskiInv(double x)
{
if (x > 1 || x < 0)
{
return Math.Floor(x) + MinkowskiInv(x - Math.Floor(x));
}
if (x == 1 || x == 0)
{
return x;
}
uint[] contFrac = new uint[] { 0 };
uint curr = 0;
uint count = 1;
int i = 0;
while (true)
{
x *= 2;
if (curr == 0)
{
if (x < 1)
{
count++;
}
else
{
i++;
Array.Resize(ref contFrac, i + 1);
contFrac[i - 1] = count;
count = 1;
curr = 1;
x--;
}
}
else
{
if (x > 1)
{
count++;
x--;
}
else
{
i++;
Array.Resize(ref contFrac, i + 1);
contFrac[i - 1] = count;
count = 1;
curr = 0;
}
}
if (x == Math.Floor(x))
{
contFrac[i] = count;
break;
}
if (i == MAXITER)
{
break;
}
}
double ret = 1.0 / contFrac[i];
for (int j = i - 1; j >= 0; j--)
{
ret = contFrac[j] + 1.0 / ret;
}
return 1.0 / ret;
}
 
static void Main(string[] args)
{
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", Minkowski(0.5 * (1 + Math.Sqrt(5))), 5.0 / 3.0);
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", MinkowskiInv(-5.0 / 9.0), (Math.Sqrt(13) - 7) / 6);
Console.WriteLine("{0,19:0.0000000000000000} {1,19:0.0000000000000000}", Minkowski(MinkowskiInv(0.718281828)),
MinkowskiInv(Minkowski(0.1213141516171819)));
}
}
</syntaxhighlight>
{{out}}
<pre>
1.6666666666697000 1.6666666666666700
-0.5657414540893350 -0.5657414540893350
0.7182818280000090 0.1213141516171820
 
</pre>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cmath>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <vector>
 
constexpr int32_t MAX_ITERATIONS = 151;
 
double minkowski(const double& x) {
if ( x < 0 || x > 1 ) {
return floor(x) + minkowski(x - floor(x));
}
 
int64_t p = (int64_t) x;
int64_t q = 1;
int64_t r = p + 1;
int64_t s = 1;
double d = 1.0;
double y = (double) p;
 
while ( true ) {
d /= 2;
if ( d == 0.0 ) {
break;
}
 
int64_t m = p + r;
if ( m < 0 || p < 0 ) {
break;
}
 
int64_t n = q + s;
if ( n < 0 ) {
break;
}
 
if ( x < (double) m / n ) {
r = m;
s = n;
} else {
y += d;
p = m;
q = n;
}
}
return y + d;
}
 
double minkowski_inverse(double x) {
if ( x < 0 || x > 1 ) {
return floor(x) + minkowski_inverse(x - floor(x));
}
 
if ( x == 0 || x == 1 ) {
return x;
}
 
std::vector<int32_t> continued_fraction(1, 0);
int32_t current = 0;
int32_t count = 1;
int32_t i = 0;
 
while ( true ) {
x *= 2;
if ( current == 0 ) {
if ( x < 1 ) {
count += 1;
} else {
continued_fraction.emplace_back(0);
continued_fraction[i] = count;
 
i += 1;
count = 1;
current = 1;
x -= 1;
}
} else {
if ( x > 1 ) {
count += 1;
x -= 1;
} else {
continued_fraction.emplace_back(0);
continued_fraction[i] = count;
 
i += 1;
count = 1;
current = 0;
}
}
 
if ( x == floor(x) ) {
continued_fraction[i] = count;
break;
}
 
if ( i == MAX_ITERATIONS ) {
break;
}
}
 
double reciprocal = 1.0 / continued_fraction[i];
for ( int32_t j = i - 1; j >= 0; --j ) {
reciprocal = continued_fraction[j] + 1.0 / reciprocal;
}
 
return 1.0 / reciprocal;
}
 
int main() {
std::cout << std::setw(20) << std::fixed << std::setprecision(16) << minkowski(0.5 * ( 1 + sqrt(5) ))
<< std::setw(20) << 5.0 / 3.0 << std::endl;
std::cout << std::setw(20) << minkowski_inverse(-5.0 / 9.0)
<< std::setw(20) << ( sqrt(13) - 7 ) / 6 << std::endl;
std::cout << std::setw(20) << minkowski(minkowski_inverse(0.718281828182818))
<< std::setw(20) << 0.718281828182818 << std::endl;
std::cout << std::setw(20) << minkowski_inverse(minkowski(0.1213141516271819))
<< std::setw(20) << 0.1213141516171819 << std::endl;
}
</syntaxhighlight>
{{ out }}
<pre>
1.6666666666696983 1.6666666666666667
-0.5657414540893351 -0.5657414540893352
0.7182818281828269 0.7182818281828180
0.1213141516171819 0.1213141516171819
</pre>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
// Minkowski question-mark function. Nigel Galloway: July 14th., 2023
let fN g=let n=(int>>float)g in ((if g<0.0 then -1.0 else 1.0),abs n,abs (g-n))
let fI(n,_,(nl,nh))(g,_,(gl,gh))=let l,h=nl+gl,nh+gh in ((n+g)/2.0,(float l)/(float h),(l,h))
let fG n g=(max n g)-(min n g)
let fE(s,z,l)=Seq.unfold(fun(i,e)->let (n,g,_) as r=fI i e in Some((s*(z+n),s*(g+z)),if l<n then (i,r) else if l=n then (r,r) else (r,e)))((0.0,0.0,(0,1)),(1.0,1.0,(1,1)))
let fL(s,z,l)=Seq.unfold(fun(i,e)->let (n,g,_) as r=fI i e in Some((s*(z+n),s*(g+z)),if l<g then (i,r) else if l=g then (r,r) else (r,e)))((0.0,0.0,(0,1)),(1.0,1.0,(1,1)))
let f2M g=let _,(n,_)=fL(fN g)|>Seq.pairwise|>Seq.find(fun((n,_),(g,_))->(fG n g)<2.328306437e-11) in n
let m2F g=let _,(_,n)=fE(fN g)|>Seq.pairwise|>Seq.find(fun((_,n),(_,g))->(fG n g)<2.328306437e-11) in n
 
printfn $"?(φ) = 5/3 is %A{fG(f2M 1.61803398874989490253)(5.0/3.0)<2.328306437e-10}"
printfn $"?⁻¹(-5/9) = (√13-7)/6 is %A{fG(m2F(-5.0/9.0))((sqrt(13.0)-7.0)/6.0)<2.328306437e-10}"
let n=42.0/23.0 in printfn $"?⁻¹(?(n)) = n is %A{(fG(m2F(f2M n)) n)<2.328306437e-10}"
let n= -3.0/13.0 in printfn $"?(?⁻¹(n)) = n is %A{(fG(f2M(m2F n)) n)<2.328306437e-10}"
</syntaxhighlight>
{{out}}
<pre>
?(φ) = 5/3 is true
?⁻¹(-5/9) = (√13-7)/6 is true
?⁻¹(?(n)) = n is true
?(?⁻¹(n)) = n is true
</pre>
=={{header|Factor}}==
{{works with|Factor|0.99 2020-08-14}}
<langsyntaxhighlight lang="factor">USING: formatting kernel make math math.constants
math.continued-fractions math.functions math.parser
math.statistics sequences sequences.extras splitting.monotonic
Line 165 ⟶ 454:
phi ? 5 3 /f compare
-5/9 ?⁻¹ 13 sqrt 7 - 6 /f compare
0.718281828 ?⁻¹ ? 0.1213141516171819 ? ?⁻¹ compare</langsyntaxhighlight>
{{out}}
<pre>
Line 175 ⟶ 464:
=={{header|FreeBASIC}}==
 
<langsyntaxhighlight lang="freebasic">#define MAXITER 151
 
function minkowski( x as double ) as double
Line 246 ⟶ 535:
print minkowski_inv( -5./9 ), (sqr(13)-7)/6
print minkowski(minkowski_inv(0.718281828)), minkowski_inv(minkowski(0.1213141516171819))
</syntaxhighlight>
</lang>
{{out}}
<pre> 1.666666666669698 1.666666666666667
Line 254 ⟶ 543:
=={{header|Go}}==
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 358 ⟶ 647:
fmt.Printf("%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819)))
}</langsyntaxhighlight>
 
{{out}}
Line 376 ⟶ 665:
This recursive definition can be implemented as lazy corecursion, i.e. by generating two infinite binary trees: '''mediant'''-based Stern-Brocot tree, containing all rationals, and '''mean'''-based tree with corresponding values of Minkowsky ?-function. There is one-to-one correspondence between these two trees so both {{math|?(x)}} and {{math|?<sup>-1</sup>(x)}} may be implemented as mapping between them. For details see the paper [[https://habr.com/ru/post/591949/]] (in Russian).
 
<langsyntaxhighlight lang="haskell">import Data.Tree
import Data.Ratio
import Data.List
Line 431 ⟶ 720:
questionMarkF, invQuestionMarkF :: Double -> Double
questionMarkF = sternBrocotF ==> minkowskiF
invQuestionMarkF = minkowskiF ==> sternBrocotF</langsyntaxhighlight>
 
<pre>λ> mapM_ print $ take 4 $ levels farey
Line 469 ⟶ 758:
Implementation:
 
<syntaxhighlight lang="j">ITERCOUNT=: 52
<lang J>minkowski=: {{
 
minkowski=: {{
f=. 1|y
node=. *i.2 2 NB. node of Stern-Brocot tree
B=. ''
for. i.52ITERCOUNT do.
B=. B, b=. f>:%/t=. +/node
node=. t (1-b)} node
end.
(<.y)+B+/ .*2^-1+i.52ITERCOUNT
}}
 
invmink=: {{
f=. 1|y
cf=. i.0
cur=. 0 NB. 1 if generating "top" side of cf
cnt=. 1 NB. bitsproposed continued fraction element
for. i.52ITERCOUNT do.
if. f=<. f do.
cf=. cf,%cnt break.
end.
f=. f*2
c=. -.b=. 1 >`<@.cur f
cf=. cf,c(-.b)#cnt
cnt=. 1+b*cnt
cur=. cur=b
Line 497 ⟶ 788:
end.
(+%)/(<.y),cf
}}</langsyntaxhighlight>
 
Task examples:
 
<lang J> minkowski 0.5*1+%:5
1.66667
((%:13)-7)%6
_0.565741
invmink _5%9
_0.565741
(p:%%:)2
3.53553
invmink minkowski (p:%%:)2
3.53553
minkowski invmink (p:%%:)2
3.53553</lang>
 
That said, note that this algorithm introduces significant numeric instability for √7 divided by 3:
 
<langsyntaxhighlight Jlang="j"> (minkowski@invmink - invmink@minkowski) (p:%%:)3
1.10713e_6</langsyntaxhighlight>
 
I see this same instability using the python implementation and appending:
 
<langsyntaxhighlight lang="python"> print(
"{:19.16f} {:19.16f}".format(
minkowski(minkowski_inv(4.04145188432738056)),
minkowski_inv(minkowski(4.04145188432738056)),
)
)</langsyntaxhighlight>
 
Using an exact fraction for 4.04145188432738056 and bumping the iteration count from 52 up to 200 changes that difference to 1.43622e_12.
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.List;
 
public final class MinkowskiQuestionMarkFunction {
 
public static void main(String[] aArgs) {
System.out.println(String.format("%20.16f%20.16f", minkowski(0.5 * ( 1 + Math.sqrt(5) )), 5.0 / 3.0));
System.out.println(String.format("%20.16f%20.16f", minkowskiInverse(-5.0 / 9.0), ( Math.sqrt(13) - 7 ) / 6 ));
System.out.println(String.format("%20.16f%20.16f", minkowski(minkowskiInverse(0.718281828)), 0.718281828));
System.out.println(String.format("%20.16f%20.16f",
minkowskiInverse(minkowski(0.1213141516271819)), 0.1213141516171819));
}
private static double minkowski(double aX) {
if ( aX < 0 || aX > 1 ) {
return Math.floor(aX) + minkowski(aX - Math.floor(aX));
}
long p = (long) aX;
long q = 1;
long r = p + 1;
long s = 1;
double d = 1.0;
double y = (double) p;
while ( true ) {
d /= 2;
if ( d == 0.0 ) {
break;
}
long m = p + r;
if ( m < 0 || p < 0 ) {
break;
}
long n = q + s;
if ( n < 0 ) {
break;
}
if ( aX < (double) m / n ) {
r = m;
s = n;
} else {
y += d;
p = m;
q = n;
}
}
return y + d;
}
private static double minkowskiInverse(double aX) {
if ( aX < 0 || aX > 1 ) {
return Math.floor(aX) + minkowskiInverse(aX - Math.floor(aX));
}
if ( aX == 0 || aX == 1 ) {
return aX;
}
List<Integer> continuedFraction = new ArrayList<Integer>();
continuedFraction.add(0);
int current = 0;
int count = 1;
int i = 0;
while ( true ) {
aX *= 2;
if ( current == 0 ) {
if ( aX < 1 ) {
count += 1;
} else {
continuedFraction.add(0);
continuedFraction.set(i, count);
 
i += 1;
count = 1;
current = 1;
aX -= 1;
}
} else {
if ( aX > 1 ) {
count += 1;
aX -= 1;
} else {
continuedFraction.add(0);
continuedFraction.set(i, count);
 
i += 1;
count = 1;
current = 0;
}
}
 
if ( aX == Math.floor(aX) ) {
continuedFraction.set(i, count);
break;
}
 
if ( i == MAX_ITERATIONS ) {
break;
}
}
 
double reciprocal = 1.0 / continuedFraction.get(i);
for ( int j = i - 1; j >= 0; j-- ) {
reciprocal = continuedFraction.get(j) + 1.0 / reciprocal;
}
 
return 1.0 / reciprocal;
}
private static final int MAX_ITERATIONS = 150;
 
}
</syntaxhighlight>
{{ out }}
<pre>
1.6666666666696983 1.6666666666666667
-0.5657414540893351 -0.5657414540893352
0.7182818280000092 0.7182818280000000
0.1213141516271825 0.1213141516171819
</pre>
 
=={{header|Julia}}==
 
{{trans|FreeBASIC}}
<langsyntaxhighlight lang="julia">function minkowskiquestionmark(x)
y, p = Int(floorfldmod(x), 1)
(xq, >d = 1 || x < 0) && return- p, + minkowski(x).5
q,while r, s, m, n = 1, py + 1, 1,d 0,> 0y
d, y p < q ? (q -= 1.0,p) : Float64(p -= q; y += d)
while true d /= 2
d /= 2.0
y + d == y && break
m = p + r
(m < 0 || p < 0) && break
n = q + s
n < 0 && break
if x < (m / n)
r, s = m, n
else
y, p, q = y + d, m, n
end
end
return y + d
end
 
function minkowski_invquestionmark_inv(x, maxiter=151)
py, bits = Int(floorfldmod(x), 1)
lo, hi = [0, 1], [1, 1]
(x > 1 || x < 0) && return p + minkowski_inv(x - p, maxiter)
while (xy ==+ 1/(lo...)) ||< x(y ==+ 0/(hi...)) && return x
bit, bits = fldmod(2bits, 1)
contfrac = [0]
bit > 0 ? (lo .+= hi) : (hi .+= lo)
curr, coun, i = 0, 1, 0
while i < maxiter
x *= 2
if curr == 0
if x < 1
coun += 1
else
i += 1
push!(contfrac, 0)
contfrac[i] = coun
coun = 1
curr = 1
x -= 1
end
else
if x > 1
coun += 1
x -= 1
else
i += 1
push!(contfrac, 0)
contfrac[i] = coun
coun = 1
curr = 0
end
end
if x == Int(floor(x))
contfrac[i + 1] = coun
break
end
end
rety =+ 1/(lo.0 / contfrac[i + 1]..)
for j in i:-1:1
ret = contfrac[j] + 1.0 / ret
end
return 1.0 / ret
end
 
x, y = 0.7182818281828, 0.1213141516171819
println(" ", minkowski((1 + sqrt(5)) / 2), " ", 5 / 3)
for (a, b) ∈ [
println(minkowski_inv(-5/9), " ", (sqrt(13) - 7) / 6)
(5/3, questionmark((1 + √5)/2)),
println(" ", minkowski(minkowski_inv(0.718281828)), " ",
((√13-7)/6, questionmark_inv(-5/9)),
minkowski_inv(minkowski(0.1213141516171819)))
(x, questionmark_inv(questionmark(x))),
</lang>{{out}}
(y, questionmark(questionmark_inv(y)))]
println(a, a ≈ b ? " ≈ " : " != ", b)
end
</syntaxhighlight>{{out}}
<pre>
1.6666666666666667 ≈ 1.666666666667894
1.6666666666696983 1.6666666666666667
-0.5657414540893352 ≈ -0.5657414540893351
-0.5657414540893351 -0.5657414540893352
0.7182818281828 ≈ 0.7182818281828183
0.7182818280000092 0.12131415161718191
0.1213141516171819 ≈ 0.12131415161718095
</pre>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">ClearAll[InverseMinkowskiQuestionMark]
InverseMinkowskiQuestionMark[val_] := Module[{x}, (x /. FindRoot[MinkowskiQuestionMark[x] == val, {x, Floor[val], Ceiling[val]}])]
MinkowskiQuestionMark[GoldenRatio]
InverseMinkowskiQuestionMark[-5/9] // RootApproximant
MinkowskiQuestionMark[InverseMinkowskiQuestionMark[0.1213141516171819]]
InverseMinkowskiQuestionMark[MinkowskiQuestionMark[0.1213141516171819]]</langsyntaxhighlight>
{{out}}
<pre>5/3
Line 622 ⟶ 987:
=={{header|Nim}}==
{{trans|Go}}
<langsyntaxhighlight Nimlang="nim">import math, strformat
 
const MaxIter = 151
Line 708 ⟶ 1,073:
echo &"{minkowskiInv(-5/9):19.16f}, {(sqrt(13.0)-7)/6:19.16f}"
echo &"{minkowski(minkowskiInv(0.718281828)):19.16f}, " &
&"{minkowskiInv(minkowski(0.1213141516171819)):19.16f}"</langsyntaxhighlight>
 
{{out}}
Line 717 ⟶ 1,082:
=={{header|Perl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 784 ⟶ 1,149:
printf "%19.16f %19.16f\n", minkowski(0.5*(1 + sqrt(5))), 5/3;
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (sqrt(13)-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)), minkowskiInv(minkowski(0.1213141516171819));</langsyntaxhighlight>
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
Line 792 ⟶ 1,157:
=={{header|Phix}}==
{{trans|FreeBASIC}}
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAXITER</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">151</span>
Line 862 ⟶ 1,227:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%20.16f %20.16f\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.718281828</span><span style="color: #0000FF;">)),</span>
<span style="color: #000000;">minkowski_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">minkowski</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.1213141516171819</span><span style="color: #0000FF;">))})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 872 ⟶ 1,237:
=={{header|Python}}==
{{trans|Go}}
<langsyntaxhighlight lang="python">import math
 
MAXITER = 151
Line 985 ⟶ 1,350:
)
)
</syntaxhighlight>
</lang>
 
{{out}}
Line 996 ⟶ 1,361:
=={{header|Raku}}==
{{trans|Go}}
<syntaxhighlight lang="raku" perl6line># 20201120 Raku programming solution
 
my \MAXITER = 151;
Line 1,060 ⟶ 1,425:
printf "%19.16f %19.16f\n", minkowskiInv(-5/9), (13.sqrt-7)/6;
printf "%19.16f %19.16f\n", minkowski(minkowskiInv(0.718281828)),
minkowskiInv(minkowski(0.1213141516171819))</langsyntaxhighlight>
{{out}}
<pre> 1.6666666666696983 1.6666666666666667
Line 1,069 ⟶ 1,434:
{{trans|FreeBASIC}}
{{trans|Phix}}
<langsyntaxhighlight lang="rexx">/*REXX program uses the Minkowski question─mark function to convert a continued fraction*/
numeric digits 40 /*use enough dec. digits for precision.*/
say fmt( mink( 0.5 * (1+sqrt(5) ) ) ) fmt( 5/3 )
Line 1,110 ⟶ 1,475:
numeric form; m.=9; parse value format(x,2,1,,0) 'E0' with g "E" _ .; g=g *.5'e'_ %2
do j=0 while h>9; m.j= h; h= h % 2 + 1; end /*j*/
do k=j+5 to 0 by -1; numeric digits m.k; g= (g + x/g) * .5; end /*k*/; return g</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the internal default inputs:}}
<pre>
Line 1,121 ⟶ 1,486:
{{trans|FreeBASIC}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./fmt" for Fmt
 
var MAXITER = 151
Line 1,204 ⟶ 1,569:
Fmt.print("$17.14f $17.14f", minkowskiInv.call(-5/9), (13.sqrt - 7)/6)
Fmt.print("$17.14f $17.14f", minkowski.call(minkowskiInv.call(0.718281828)),
minkowskiInv.call(minkowski.call(0.1213141516171819)))</langsyntaxhighlight>
 
{{out}}
337

edits