---
title: Lua numbers in Tarantool
tags: Tarantool, Talk
description: View the slide with "Slide Mode".
slideOptions:
theme: dark
transition: none
backgroundTransition: none
width: 960
height: 540
margin: 0
---
<!-- {{{ -->
<style type="text/css">
* { tab-size: 4; }
/* Resets & overrides */
.reveal dl { display: block; }
.reveal pre { width: auto; box-shadow: none; }
.reveal pre code { width: auto; max-height: initial; }
.reveal blockquote { width: auto; }
.reveal .slides .pdf-page { pointer-events: initial; }
.reveal .slides { text-align: left; }
/* Font style defs */
html, .reveal {
font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}
.reveal pre code {
font-family: "PTM55F", "Monaco", monospace;
}
/* Color defs */
.reveal pre code {
background: #2d2d2d;
}
/* Backgrounds */
.reveal .slide-background-content {
background-color: #222;
}
.reveal .first .slide-background-content {
background-color: #222;
}
.reveal section {
background-color: #333;
background-size: cover;
background-image: url(https://slides.hb.bizmrg.com/tarantool/dark/page.png);
}
.reveal .slides section h1,
.reveal .slides section h2,
.reveal .slides section h3,
.reveal .slides section h4,
.reveal .slides section h5,
.reveal .slides section h6{
background: rgba(0,0,0,0.25);
}
/* Font-sizes */
html {
font-size: 32px;
}
.reveal {
font-size: 1rem;
}
.reveal .slides section h1,
.reveal .slides section h2,
.reveal .slides section h3,
.reveal .slides section h4,
.reveal .slides section h5,
.reveal .slides section h6{
font-size: 40px;
}
/*
.reveal .slides section h1 { font-size: 42px }
.reveal .slides section h2 { font-size: 40px }
.reveal .slides section h3 { font-size: 38px }
.reveal .slides section h4 { font-size: 36px }
.reveal .slides section h5 { font-size: 34px }
.reveal .slides section h6 { font-size: 32px }
*/
.reveal pre {
font-size: 20px;
line-height: 1.11;
}
.reveal pre code {
font-size: inherit;
}
.reveal blockquote {
font-size: 28px;
}
/* Paddings */
.reveal .slides section {
width: 960px;
height: 540px;
}
.reveal .slides > section,
.reveal .slides > section > section {
padding: 20px;
}
.reveal .slides > section > section {
margin: 0 -20px;
}
.reveal .slides section h1,
.reveal .slides section h2,
.reveal .slides section h3,
.reveal .slides section h4,
.reveal .slides section h5,
.reveal .slides section h6{
margin: -5px -20px 15px -20px;
padding: 5px 20px;
}
.reveal dl { margin: 0; }
.reveal dd { margin-bottom: 0.25em; }
.reveal pre {
margin: 10px -20px 20px -20px;
padding: 0;
}
.reveal pre code {
padding: 10px 20px;
}
.reveal blockquote {
margin: 20px -20px 20px -20px;
padding: 0;
}
.reveal blockquote > p {
margin: 0 0 0 40px;
padding: 0 0 0 5px;
}
/*** Helpers ***/
.reveal .slides section.center.present {
display: grid !important;
align-items: center;
}
.lr {
display:grid;
grid-gap: 0 50px;
grid-template-columns: 1fr 1fr;
}
section.only-code pre {
position: absolute;
top: 10px;
bottom: 10px;
left: 0;
right: 0;
margin: 0;
}
section.only-code pre code {
height: 100%;
}
/*** Modding ***/
.reveal .slides section .fragment.current-only {
opacity: 1;
visibility: visible;
display: none;
}
.reveal .slides section .fragment.current-only.current-fragment {
display: block;
}
.reveal .slides section li.fragment.current-only.current-fragment {
display: list-item;
}
.reveal .slides section span.fragment.current-only.current-fragment {
display: inline;
}
.reveal .slides section .fragment.visible-blurred {
opacity: 1;
visibility: visible;
filter: blur(2px);
}
.reveal .slides section .fragment.visible-blurred.visible {
filter: none;
}
.reveal .slides section .fragment.visible-blurred.visible.current-fragment {
filter: none;
text-shadow: 2px 2px #676767;
}
/*** Stylings ***/
dd { font-style: italic; }
dd * { font-style: initial; }
.reveal pre code { overflow: hidden; }
.reveal blockquote > p { border-left: solid #333 10px; }
.reveal .slides section { overflow: hidden; }
section.first *[data-title] {
position: absolute;
left : 0;
bottom: 0px;
}
.reveal .slides section.first h1 {
margin-top: 25px;
background: none;
}
.reveal .slides section.first h2 {
background: none;
}
section.first .author {
position: absolute;
left : 20px;
bottom: 20px;
}
</style>
<!-- }}} -->
<!-- .slide: class="first" -->
# Lua numbers in Tarantool
<address class="author">
Igor Munkin
</address>
---
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- <result>
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- <result>
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- false
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- false
...
tarantool> 2^53 == 2^53 + 1
–––
- <result>
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- false
...
tarantool> 2^53 == 2^53 + 1
–––
- true
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- false
...
tarantool> 2^53 == 2^53 + 1
–––
- true
...
tarantool> 2^53 == 2^53 + 2
–––
- <result>
...
</code></pre>
----
# Problem #1
<pre><code class="tarantool hljs">
tarantool> 2^52 == 2^52 + 0.5
–––
- true
...
tarantool> 2^52 == 2^52 + 1
–––
- false
...
tarantool> 2^53 == 2^53 + 1
–––
- true
...
tarantool> 2^53 == 2^53 + 2
–––
- false
...
</code></pre>
---
# Effect #1.1
<pre><code class="tarantool hljs">
tarantool> box.cfg{} <snip> box.space.s:create_index('i')
–––
- <snip>
...
</code></pre>
----
# Effect #1.1
<pre><code class="tarantool hljs">
tarantool> box.cfg{} <snip> box.space.s:create_index('i')
–––
- <snip>
...
tarantool> box.space.s:insert({2^53})
–––
- <result>
...
</code></pre>
----
# Effect #1.1
<pre><code class="tarantool hljs">
tarantool> box.cfg{} <snip> box.space.s:create_index('i')
–––
- <snip>
...
tarantool> box.space.s:insert({2^53})
–––
- [9007199254740992]
...
</code></pre>
----
# Effect #1.1
<pre><code class="tarantool hljs">
tarantool> box.cfg{} <snip> box.space.s:create_index('i')
–––
- <snip>
...
tarantool> box.space.s:insert({2^53})
–––
- [9007199254740992]
...
tarantool> box.space.s:insert({2^53 + 1})
–––
- <result>
...
</code></pre>
----
# Effect #1.1
<pre><code class="tarantool hljs">
tarantool> box.cfg{} <snip> box.space.s:create_index('i')
–––
- <snip>
...
tarantool> box.space.s:insert({2^53})
–––
- [9007199254740992]
...
tarantool> box.space.s:insert({2^53 + 1})
–––
- error: Duplicate key exists in unique index 'i' in space 's'
...
</code></pre>
---
# Effect #1.2
<pre><code class="tarantool hljs">
tarantool> box.space.s:select({2^53})
–––
- <result>
...
</code></pre>
----
# Effect #1.2
<pre><code class="tarantool hljs">
tarantool> box.space.s:select({2^53})
–––
- [9007199254740992]
...
</code></pre>
----
# Effect #1.2
<pre><code class="tarantool hljs">
tarantool> box.space.s:select({2^53})
–––
- [9007199254740992]
...
tarantool> box.space.s:select({2^53 + 1})
–––
- <result>
...
</code></pre>
----
# Effect #1.2
<pre><code class="tarantool hljs">
tarantool> box.space.s:select({2^53})
–––
- [9007199254740992]
...
tarantool> box.space.s:select({2^53 + 1})
–––
- [9007199254740992]
...
</code></pre>
---
# WAT #1
<pre><code class="tarantool hljs">
tarantool> type(box.space.s:select({2^53})[1])
–––
- <result>
...
</code></pre>
----
# WAT #1
<pre><code class="tarantool hljs">
tarantool> type(box.space.s:select({2^53})[1])
–––
- cdata
...
</code></pre>
----
# WAT #1
<div align="center">
<img src=https://media1.tenor.com/images/d3733ebb0b001e1baac25db96723f478/tenor.gif>
</div>
---
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- <result>
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- 9007199254740992
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- 9007199254740992
...
tarantool> type(9007199254740992ULL)
–––
- <result>
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- 9007199254740992
...
tarantool> type(9007199254740992ULL)
–––
- cdata
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- 9007199254740992
...
tarantool> type(9007199254740992ULL)
–––
- cdata
...
tarantool> 9007199254740992ULL + 1
–––
- <result>
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL
–––
- 9007199254740992
...
tarantool> type(9007199254740992ULL)
–––
- cdata
...
tarantool> 9007199254740992ULL + 1
–––
- 9007199254740993
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL + 1
–––
- 9007199254740993
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 1
–––
- <result>
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL + 1
–––
- 9007199254740993
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 1
–––
- false
...
</code></pre>
----
# Workaround #1
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL + 1
–––
- 9007199254740993
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 1
–––
- false
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 0.5
–––
- <result>
...
</code></pre>
----
# Workaround #1 (?)
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL + 1
–––
- 9007199254740993
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 1
–––
- false
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 0.5
–––
- true
...
</code></pre>
----
# Workaround #1 (?)
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL == 9007199254740992ULL + 1
–––
- false
...
tarantool> 9007199254740992ULL == 9007199254740992ULL + 0.5
–––
- true
...
tarantool> 9007199254740992ULL + 0.5
–––
- 9007199254740992
...
</code></pre>
---
# Problem #2
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL < 9007199254740992ULL + 1
–––
- <result>
...
</code></pre>
----
# Problem #2
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL < 9007199254740992ULL + 1
–––
- true
...
</code></pre>
----
# Problem #2
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL < 9007199254740992ULL + 1
–––
- true
...
tarantool> 9007199254740992ULL < -1
–––
- <result>
...
</code></pre>
----
# Problem #2
<pre><code class="tarantool hljs">
tarantool> 9007199254740992ULL < 9007199254740992ULL + 1
–––
- true
...
tarantool> 9007199254740992ULL < -1
–––
- true
...
</code></pre>
---
# Effect #2
<pre><code class="tarantool hljs">
tarantool> box.cfg{listen = 3313} <snip> c = nb.connect(box.cfg.listen)
<snip>
–––
...
</code></pre>
----
# Effect #2
<pre><code class="tarantool hljs">
tarantool> box.cfg{listen = 3313} <snip> c = nb.connect(box.cfg.listen)
<snip>
–––
...
tarantool> t = {} for _ = 1, 10 do
> table.insert(t,
> c:execute('SELECT random()').rows[1]
> :totable()[1]
> )
> end
–––
...
</code></pre>
----
# Effect #2
<pre><code class="tarantool hljs">
tarantool> box.cfg{listen = 3313} <snip> c = nb.connect(box.cfg.listen)
<snip>
–––
...
tarantool> t = {} for _ = 1, 10 do
> table.insert(t,
> c:execute('SELECT random()').rows[1]
> :totable()[1]
> )
> end
–––
...
tarantool> table.sort(t)
–––
...
</code></pre>
----
# Effect #2
<pre><code class="tarantool hljs">
tarantool> t
–––
- <result>
...
</code></pre>
----
# Effect #2
<pre><code class="tarantool hljs">
tarantool> t
–––
- - 1064442337705904389
- 5430535088656468933
- 8084626668617668138
- -7957167126669429942
- -6755436305203424895
- -6476727283901405634
- -5944830508420504980
- -2428743323307643782
- -1162597621816885600
- -108704732427766924
...
</code></pre>
---
# Long story short
* Native Lua numeric type
* Lack of precision for several groups of numbers
* FFI cdata numeric types
* 64-bit integer promotion and cast rules according to C standard
**Odd arithmetics for both existing numeric types**
---
# Bonus tracks
* [cdata double type arithmetics](https://blog.imun.cloud/Oh-Mike-Pall-1/)
* [math.huge — huge or not?](https://blog.imun.cloud/Oh-Mike-Pall-2/)