diff --git a/README.md b/README.md
index 47d8de92..85932305 100644
--- a/README.md
+++ b/README.md
@@ -47,104 +47,108 @@ The measured values are:
All values are presented as: `median`±`median absolute deviation`.
-UPDATE: 2020-10-30
+UPDATE: 2020-12-01
# Test Cases
## Brainfuck
Testing brainfuck implementations using two code samples (bench.b and mandel.b).
+Supports two mode:
+
+ - Verbose (default). Prints the output immediately.
+ - Quiet (if QUIET environment variable is set). Accumulates the output using Fletcher-16 checksum, and prints it out after the benchmark.
[Brainfuck](brainfuck)
### bench.b
-| Language | Time, s | Memory, MiB | Energy, J |
-| :----------------------- | -----------------------: | ------------------------------------------------: | -------------------------: |
-| C++/g++ | 0.876±0.010 | 1.50±00.00 + 0.00±00.00 | 17.08±00.19 |
-| Nim/gcc | 1.826±0.010 | 1.80±00.08 + 0.00±00.00 | 33.07±00.41 |
-| Vala/gcc | 1.830±0.009 | 3.98±00.04 + 0.00±00.00 | 33.87±00.54 |
-| C/gcc | 1.854±0.036 | 0.55±00.01 + 0.00±00.00 | 35.34±01.45 |
-| Kotlin | 1.867±0.026 | 37.01±00.14 + 2.88±00.26 | 35.09±00.90 |
-| OCaml | 1.868±0.045 | 2.57±00.02 + 2.48±00.03 | 38.04±01.74 |
-| D/ldc2 | 1.934±0.019 | 2.98±00.05 + 0.00±00.00 | 36.46±00.54 |
-| Nim/clang | 1.939±0.048 | 2.29±00.05 + 0.00±00.00 | 38.99±01.12 |
-| Vala/clang | 1.975±0.027 | 3.94±00.06 + 0.00±00.00 | 41.58±00.67 |
-| D/gdc | 2.027±0.037 | 6.28±00.04 + 0.00±00.00 | 39.34±01.18 |
-| Rust | 2.102±0.050 | 2.03±00.09 + 0.00±00.00 | 41.01±01.32 |
-| Go/gccgo | 2.206±0.074 | 20.78±00.21 + 0.00±00.00 | 45.18±02.77 |
-| C/clang | 2.245±0.024 | 0.50±00.01 + 0.00±00.00 | 42.46±02.19 |
-| Java | 2.337±0.022 | 35.96±00.18 + 1.89±00.30 | 42.72±00.65 |
-| C#/.NET Core | 2.451±0.037 | 33.26±00.12 + 1.30±00.05 | 46.20±01.47 |
-| Go | 2.475±0.035 | 3.38±00.08 + 0.00±00.00 | 48.20±01.90 |
-| MLton | 2.493±0.024 | 0.55±00.03 + 0.00±00.00 | 52.45±02.54 |
-| V/gcc | 2.530±0.063 | 0.50±00.00 + 0.00±00.00 | 51.52±02.51 |
-| Crystal | 2.670±0.014 | 3.35±00.05 + 0.00±00.00 | 51.04±01.64 |
-| F#/.NET Core | 2.794±0.062 | 35.15±00.13 + 90.27±00.91 | 55.36±01.72 |
-| V/clang | 2.867±0.077 | 0.87±00.01 + 0.00±00.00 | 56.10±03.03 |
-| Chez Scheme | 2.936±0.054 | 22.88±00.06 + 6.24±00.05 | 58.09±03.11 |
-| Julia | 3.242±0.133 | 155.09±00.47 + 21.86±00.38 | 64.32±04.93 |
-| Scala | 3.496±0.078 | 80.21±00.68 + 57.68±05.60 | 71.55±02.78 |
-| D/dmd | 3.771±0.039 | 3.49±00.05 + 0.00±00.00 | 66.90±02.18 |
-| Haskell (MArray) | 4.380±0.073 | 4.11±00.08 + 1.25±00.00 | 101.37±03.59 |
-| C#/Mono | 4.459±0.179 | 20.03±00.05 + 0.37±00.00 | 90.94±07.00 |
-| Node.js | 5.063±0.030 | 29.49±00.02 + 1.97±00.19 | 88.66±01.54 |
-| Lua/luajit | 7.571±0.151 | 2.82±00.08 + 0.00±00.00 | 128.54±04.21 |
-| Racket | 8.077±0.170 | 106.98±00.08 + 0.00±00.00 | 141.31±03.73 |
-| Python/pypy | 13.003±0.274 | 63.79±00.21 + 45.38±00.00 | 315.76±02.70 |
-| Haskell | 16.686±0.512 | 4.11±00.04 + 1.34±00.00 | 310.02±13.55 |
-| Ruby/truffleruby (--jvm) | 18.445±0.329 | 596.26±11.32 + 324.76±14.58 | 522.27±23.71 |
-| Ruby/truffleruby | 51.534±2.159 | 260.91±00.06 + 277.20±10.48 | 978.82±137.20 |
-| Lua | 56.908±1.507 | 2.64±00.02 + 0.00±00.00 | 1203.05±52.83 |
-| Ruby (--jit) | 61.920±1.734 | 14.12±00.04 + 0.15±00.00 | 1110.14±49.84 |
-| Ruby | 82.990±1.020 | 14.08±00.01 + 0.00±00.00 | 1771.74±67.67 |
-| Ruby/jruby | 111.106±3.402 | 199.68±05.79 + 242.16±03.23 | 2182.73±161.51 |
-| Elixir | 113.521±0.406 | 53.51±00.27 + 0.47±00.15 | 2493.22±31.14 |
-| Python | 220.743±3.369 | 9.32±00.04 + 0.00±00.00 | 4797.72±88.75 |
-| Tcl (FP) | 274.283±3.413 | 4.27±00.04 + 0.00±00.00 | 5234.49±210.69 |
-| Perl | 339.112±7.722 | 6.43±00.02 + 0.00±00.00 | 7050.02±301.70 |
-| Tcl (OOP) | 529.515±6.545 | 4.28±00.05 + 0.00±00.00 | 11591.55±176.57 |
+| Language | Time, s | Memory, MiB | Energy, J |
+| :----------------------- | ------------------------: | ------------------------------------------------: | -------------------------: |
+| C++/g++ | 0.892±0.044 | 1.49±00.03 + 0.00±00.00 | 15.92±00.43 |
+| Kotlin | 1.705±0.018 | 38.11±00.12 + 2.12±00.07 | 38.89±00.47 |
+| D/ldc2 | 1.832±0.023 | 3.06±00.03 + 0.00±00.00 | 33.17±01.19 |
+| Nim/gcc | 1.860±0.036 | 1.92±00.04 + 0.00±00.00 | 35.16±02.06 |
+| C/gcc | 1.887±0.034 | 0.50±00.00 + 0.00±00.00 | 36.04±00.71 |
+| Rust | 1.921±0.036 | 2.02±00.06 + 0.00±00.00 | 45.72±01.08 |
+| Nim/clang | 1.921±0.036 | 2.37±00.05 + 0.00±00.00 | 44.39±01.02 |
+| D/gdc | 1.950±0.034 | 6.34±00.07 + 0.00±00.00 | 37.39±01.93 |
+| C/clang | 2.223±0.066 | 0.50±00.00 + 0.00±00.00 | 42.64±01.37 |
+| OCaml | 2.230±0.026 | 2.60±00.02 + 2.50±00.03 | 42.50±01.23 |
+| Go | 2.241±0.034 | 3.53±00.08 + 0.00±00.00 | 50.55±01.43 |
+| Vala/clang | 2.316±0.026 | 3.73±00.04 + 0.00±00.00 | 54.54±00.49 |
+| Crystal | 2.317±0.021 | 3.37±00.01 + 0.00±00.00 | 55.93±01.28 |
+| Vala/gcc | 2.335±0.062 | 3.77±00.04 + 0.00±00.00 | 47.62±01.82 |
+| C#/.NET Core | 2.341±0.089 | 34.18±00.04 + 0.01±00.00 | 48.13±04.76 |
+| V/gcc | 2.433±0.071 | 0.50±00.00 + 0.00±00.00 | 51.49±01.99 |
+| Java | 2.458±0.113 | 37.49±00.09 + 0.96±00.11 | 48.82±02.17 |
+| Go/gccgo | 2.593±0.203 | 20.93±00.22 + 0.00±00.00 | 52.43±10.28 |
+| V/clang | 2.742±0.106 | 0.87±00.00 + 0.00±00.00 | 57.97±03.80 |
+| MLton | 2.841±0.030 | 1.44±00.05 + 0.25±00.00 | 69.59±01.25 |
+| Chez Scheme | 2.898±0.136 | 24.87±00.05 + 4.23±00.09 | 61.62±05.33 |
+| Julia | 2.989±0.124 | 169.09±00.12 + 0.00±00.00 | 52.77±03.78 |
+| D/dmd | 3.398±0.051 | 3.58±00.04 + 0.00±00.00 | 75.85±04.16 |
+| Scala | 3.451±0.036 | 80.33±00.31 + 63.22±04.38 | 70.71±01.84 |
+| Node.js | 3.876±0.091 | 29.72±00.07 + 2.08±00.00 | 86.57±02.19 |
+| C#/Mono | 4.047±0.035 | 20.14±00.06 + 0.00±00.00 | 93.13±00.66 |
+| Haskell (MArray) | 4.626±0.065 | 3.52±00.05 + 1.23±00.00 | 104.52±07.29 |
+| F#/.NET Core | 5.759±0.060 | 36.41±00.05 + 90.04±00.54 | 122.34±02.41 |
+| Lua/luajit | 6.266±0.056 | 2.84±00.05 + 0.00±00.00 | 134.09±03.45 |
+| Racket | 10.241±0.263 | 101.02±00.05 + 0.00±00.00 | 188.03±09.99 |
+| Ruby/truffleruby (--jvm) | 11.014±0.785 | 554.32±05.28 + 467.70±85.03 | 346.21±23.03 |
+| Python/pypy | 14.634±0.483 | 63.77±00.19 + 45.38±00.00 | 348.98±16.82 |
+| Haskell | 16.436±0.405 | 4.28±00.05 + 1.00±00.00 | 320.67±10.52 |
+| Ruby/truffleruby | 21.492±1.470 | 253.22±00.14 + 638.77±14.18 | 517.59±37.53 |
+| Lua | 57.236±1.627 | 2.67±00.01 + 0.00±00.00 | 1122.15±58.58 |
+| Ruby (--jit) | 61.421±1.978 | 14.12±00.05 + 0.15±00.00 | 1122.68±34.10 |
+| Ruby | 82.449±3.315 | 14.15±00.05 + 0.00±00.00 | 1706.93±130.86 |
+| Ruby/jruby | 109.907±2.647 | 202.52±03.44 + 236.59±02.42 | 2259.77±110.02 |
+| Elixir | 119.090±1.217 | 56.61±01.01 + 0.00±00.00 | 2268.87±68.60 |
+| Python | 235.009±4.679 | 9.45±00.03 + 0.00±00.00 | 4650.00±179.37 |
+| Tcl (FP) | 279.844±8.099 | 4.28±00.03 + 0.00±00.00 | 5693.86±351.71 |
+| Perl | 361.937±3.237 | 6.51±00.04 + 0.00±00.00 | 7386.06±407.83 |
+| Tcl (OOP) | 540.958±12.988 | 4.26±00.09 + 0.00±00.00 | 11178.46±579.19 |
### mandel.b
[Mandel in Brainfuck](brainfuck/mandel.b)
-| Language | Time, s | Memory, MiB | Energy, J |
-| :----------------------- | ------------------------: | ------------------------------------------------: | ------------------------: |
-| C++/g++ | 11.750±0.200 | 1.50±00.03 + 2.20±00.03 | 238.08±19.76 |
-| C/gcc | 13.152±0.230 | 0.55±00.01 + 1.09±00.03 | 226.01±09.52 |
-| Vala/gcc | 13.553±0.141 | 0.00±00.00 + 0.00±00.00 | 232.63±09.26 |
-| D/gdc | 14.056±0.695 | 6.60±00.06 + 0.52±00.00 | 256.56±26.63 |
-| D/ldc2 | 15.040±0.137 | 3.09±00.02 + 0.77±00.00 | 319.73±08.24 |
-| Vala/clang | 15.198±0.222 | 0.00±00.00 + 0.00±00.00 | 328.05±10.27 |
-| Crystal | 15.442±0.156 | 3.36±00.01 + 0.41±00.02 | 322.26±06.55 |
-| V/gcc | 16.213±0.211 | 0.53±00.03 + 1.92±00.03 | 303.77±17.59 |
-| C/clang | 18.020±0.552 | 0.55±00.01 + 1.06±00.04 | 329.77±13.16 |
-| Nim/clang | 18.082±0.336 | 2.32±00.04 + 0.51±00.00 | 382.29±19.97 |
-| C#/.NET Core | 18.168±0.287 | 33.42±00.03 + 2.48±00.05 | 377.64±08.61 |
-| Rust | 18.961±0.684 | 2.02±00.07 + 0.28±00.03 | 356.32±27.58 |
-| V/clang | 19.085±0.786 | 0.86±00.06 + 1.98±00.12 | 338.08±24.00 |
-| Nim/gcc | 20.081±0.098 | 1.86±00.04 + 0.51±00.00 | 447.29±05.66 |
-| Java | 21.567±1.482 | 35.91±00.21 + 7.39±00.35 | 422.11±40.28 |
-| Kotlin | 22.433±0.767 | 36.90±00.03 + 8.33±00.17 | 461.84±23.20 |
-| Scala | 23.711±0.735 | 72.71±00.27 + 32.66±05.22 | 493.04±40.26 |
-| MLton | 24.570±0.317 | 1.24±00.04 + 1.78±00.00 | 420.67±12.22 |
-| Go/gccgo | 27.242±0.228 | 21.23±00.51 + 1.28±00.00 | 455.59±17.41 |
-| OCaml | 29.912±1.068 | 3.29±00.02 + 7.26±01.97 | 565.03±42.35 |
-| Go | 32.794±0.618 | 2.78±00.09 + 1.25±00.00 | 686.73±17.76 |
-| D/dmd | 44.664±1.621 | 3.63±00.04 + 0.77±00.00 | 838.73±38.99 |
-| C#/Mono | 46.634±0.426 | 20.14±00.05 + 1.14±00.00 | 990.63±12.21 |
-| Chez Scheme | 48.198±1.162 | 23.48±00.03 + 5.73±00.04 | 936.23±64.37 |
-| Node.js | 58.719±1.972 | 29.56±00.15 + 6.96±00.13 | 1164.88±81.55 |
-| Julia | 59.297±0.975 | 154.91±00.49 + 21.99±00.40 | 1277.50±17.66 |
-| Haskell (MArray) | 62.629±0.442 | 4.09±00.05 + 2.45±00.00 | 1401.28±13.64 |
-| Lua/luajit | 64.387±0.450 | 2.88±00.06 + 0.85±00.00 | 1364.42±54.12 |
-| Python/pypy | 70.615±0.932 | 63.83±00.25 + 46.61±00.10 | 1326.94±73.41 |
-| Ruby/truffleruby (--jvm) | 113.544±1.747 | 589.01±03.74 + 341.00±21.87 | 2375.13±83.06 |
-| F#/.NET Core | 124.378±0.274 | 35.29±00.07 + 93.01±00.09 | 2416.39±10.62 |
-| Racket | 136.034±4.331 | 106.99±00.03 + 0.00±00.00 | 2542.90±190.09 |
-| Ruby/truffleruby | 194.627±15.454 | 261.21±00.27 + 251.62±11.10 | 3804.72±383.77 |
-| Haskell | 214.731±1.549 | 4.01±00.08 + 2.54±00.00 | 4658.95±141.03 |
+| Language | Time, s | Memory, MiB | Energy, J |
+| :----------------------- | -----------------------: | ------------------------------------------------: | ------------------------: |
+| D/ldc2 | 13.023±0.141 | 3.02±00.04 + 0.77±00.00 | 282.47±15.54 |
+| C/gcc | 13.024±0.044 | 0.49±00.00 + 1.11±00.02 | 232.35±06.92 |
+| C++/g++ | 13.508±0.519 | 3.14±00.14 + 0.49±00.02 | 243.38±14.88 |
+| D/gdc | 13.622±0.486 | 6.68±00.06 + 0.52±00.00 | 284.97±15.61 |
+| V/gcc | 13.929±0.345 | 0.55±00.05 + 1.88±00.06 | 263.36±22.17 |
+| Kotlin | 16.201±0.639 | 37.89±00.20 + 2.53±00.14 | 333.78±12.48 |
+| C/clang | 17.205±0.296 | 0.54±00.00 + 1.09±00.02 | 409.86±07.81 |
+| C#/.NET Core | 17.817±0.206 | 34.36±00.02 + 1.06±00.06 | 386.31±09.90 |
+| Nim/gcc | 18.909±0.573 | 1.81±00.04 + 0.57±00.05 | 364.59±13.74 |
+| Rust | 19.121±0.365 | 2.06±00.09 + 0.28±00.03 | 450.43±14.62 |
+| V/clang | 19.954±0.144 | 0.85±00.00 + 1.97±00.09 | 354.30±05.02 |
+| Nim/clang | 21.089±0.839 | 2.31±00.07 + 0.51±00.00 | 427.52±33.64 |
+| Vala/clang | 21.997±0.558 | 3.54±00.04 + 2.02±00.02 | 417.73±08.93 |
+| Java | 22.059±2.009 | 37.61±00.10 + 1.41±00.15 | 438.82±32.38 |
+| Vala/gcc | 22.339±0.495 | 3.55±00.02 + 2.05±00.02 | 395.91±13.76 |
+| Scala | 22.953±0.280 | 80.06±00.43 + 38.70±03.31 | 533.87±10.60 |
+| Go/gccgo | 23.761±0.456 | 33.35±00.22 + 1.28±00.05 | 519.74±23.32 |
+| Crystal | 23.958±0.297 | 3.32±00.04 + 0.45±00.02 | 442.85±08.69 |
+| Go | 34.576±0.772 | 3.50±00.03 + 1.24±00.01 | 636.21±19.42 |
+| OCaml | 36.101±0.674 | 3.81±00.03 + 7.19±01.04 | 809.54±37.56 |
+| Chez Scheme | 38.361±0.223 | 25.47±00.03 + 3.65±00.02 | 928.03±21.01 |
+| D/dmd | 40.256±0.116 | 3.48±00.03 + 0.77±00.00 | 890.37±04.94 |
+| C#/Mono | 43.907±0.601 | 20.06±00.06 + 0.88±00.00 | 974.19±30.51 |
+| Node.js | 45.577±1.511 | 29.36±00.12 + 6.12±00.01 | 911.95±74.08 |
+| MLton | 52.145±0.592 | 1.40±00.03 + 4.11±00.00 | 997.68±30.34 |
+| Julia | 57.873±1.982 | 168.56±00.17 + 0.00±00.00 | 1150.80±96.19 |
+| Python/pypy | 65.443±0.415 | 64.01±00.25 + 45.97±00.09 | 1537.62±41.76 |
+| Haskell (MArray) | 65.728±1.731 | 3.56±00.09 + 2.74±00.00 | 1333.81±82.75 |
+| Ruby/truffleruby (--jvm) | 127.906±1.069 | 553.57±06.48 + 384.87±17.42 | 2850.44±62.68 |
+| F#/.NET Core | 133.896±0.448 | 36.46±00.05 + 91.62±00.12 | 2663.72±08.90 |
+| Racket | 167.016±3.127 | 100.96±00.07 + 0.00±00.00 | 3106.19±93.72 |
+| Ruby/truffleruby | 169.044±5.202 | 252.82±00.38 + 661.55±17.47 | 3637.07±123.52 |
+| Haskell | 224.213±5.516 | 3.65±00.06 + 26.29±00.00 | 4739.08±376.63 |
+| Lua/luajit | 246.285±3.792 | 2.79±00.03 + 0.86±00.00 | 4889.38±291.91 |
## Base64
@@ -154,38 +158,38 @@ Testing base64 encoding/decoding of the large blob into the newly allocated buff
| Language | Time, s | Memory, MiB | Energy, J |
| :------------------------ | ----------------------: | ------------------------------------------------: | ----------------------: |
-| C/gcc (aklomp) | 0.157±0.002 | 1.92±00.03 + 0.00±00.00 | 3.41±00.14 |
-| V/clang | 0.831±0.032 | 1.97±00.01 + 0.43±00.10 | 14.57±01.00 |
-| C/gcc | 1.237±0.067 | 1.88±00.03 + 0.00±00.00 | 22.43±02.28 |
-| Rust | 1.256±0.022 | 2.55±00.05 + 0.01±00.00 | 27.66±01.25 |
-| V/gcc | 1.474±0.026 | 1.72±00.04 + 0.23±00.07 | 31.07±01.58 |
-| Nim/clang | 1.578±0.036 | 2.72±00.05 + 4.41±00.03 | 35.12±02.09 |
-| D/ldc2 | 1.897±0.039 | 3.42±00.04 + 3.61±00.00 | 32.52±01.16 |
-| Crystal | 1.982±0.014 | 3.83±00.04 + 1.80±00.02 | 46.74±00.43 |
-| Nim/gcc | 1.983±0.024 | 2.27±00.04 + 4.44±00.00 | 43.66±01.35 |
-| Java | 2.271±0.078 | 38.62±00.04 + 327.05±22.71 | 48.84±03.76 |
-| D/gdc | 2.306±0.098 | 7.11±00.06 + 3.47±00.05 | 45.83±05.01 |
-| Kotlin | 2.427±0.038 | 39.58±00.05 + 345.29±04.26 | 56.48±01.80 |
-| Go | 2.505±0.013 | 4.61±00.03 + 4.50±00.17 | 47.49±00.47 |
-| Ruby (--jit) | 2.549±0.096 | 14.51±00.02 + 43.25±00.57 | 47.31±03.07 |
-| Scala | 2.554±0.031 | 80.89±00.67 + 71.32±05.09 | 51.15±03.92 |
-| Ruby | 2.569±0.075 | 14.53±00.02 + 43.50±00.16 | 44.80±00.80 |
-| Perl (MIME::Base64) | 2.646±0.104 | 14.45±00.08 + 0.02±00.00 | 48.60±04.70 |
-| C++/g++ (libcrypto) | 2.719±0.084 | 5.34±00.16 + 0.07±00.00 | 62.23±03.17 |
-| PHP | 2.942±0.101 | 15.80±00.08 + 0.00±00.00 | 49.58±01.39 |
-| Node.js | 3.123±0.105 | 31.01±00.06 + 1029.64±00.08 | 68.11±01.22 |
-| Go/gccgo | 3.506±0.010 | 22.03±00.17 + 7.14±00.14 | 72.97±01.36 |
-| D/dmd | 3.815±0.128 | 3.69±00.06 + 3.67±00.06 | 65.92±04.33 |
-| Tcl | 4.008±0.080 | 5.23±00.03 + 0.00±00.00 | 87.92±02.24 |
-| Python | 5.166±0.061 | 9.37±00.02 + 0.18±00.00 | 117.11±03.97 |
-| Python/pypy | 5.475±0.300 | 63.99±00.11 + 45.65±00.07 | 106.11±11.82 |
-| C#/.NET Core | 5.513±0.093 | 33.86±00.11 + 40.39±00.61 | 104.92±01.62 |
-| Julia | 5.623±0.132 | 199.35±00.31 + 43.17±00.15 | 131.97±01.86 |
-| Ruby/truffleruby (--jvm) | 6.183±0.233 | 595.53±10.25 + 132.10±12.97 | 125.76±15.33 |
-| C#/Mono | 7.263±0.080 | 20.73±00.07 + 18.50±00.02 | 173.29±05.14 |
-| Ruby/jruby | 10.530±0.747 | 206.29±07.04 + 169.80±07.50 | 215.73±13.87 |
-| Perl (MIME::Base64::Perl) | 16.329±0.482 | 15.77±00.12 + 0.25±00.04 | 358.67±13.10 |
-| Ruby/truffleruby | 24.242±0.227 | 263.40±00.14 + 354.47±00.19 | 411.96±05.26 |
+| C/gcc (aklomp) | 0.156±0.002 | 1.90±00.02 + 0.00±00.00 | 3.43±00.14 |
+| C/gcc | 1.190±0.010 | 1.87±00.04 + 0.00±00.00 | 24.92±00.52 |
+| Rust | 1.246±0.045 | 2.49±00.08 + 0.01±00.01 | 28.21±00.74 |
+| V/clang | 1.522±0.026 | 1.98±00.04 + 0.47±00.01 | 32.63±00.77 |
+| V/gcc | 1.624±0.026 | 1.73±00.03 + 0.23±00.11 | 35.31±01.20 |
+| D/ldc2 | 1.745±0.011 | 3.40±00.02 + 3.66±00.00 | 30.74±00.31 |
+| Nim/clang | 1.877±0.024 | 2.68±00.06 + 4.41±00.03 | 33.76±01.21 |
+| Nim/gcc | 2.048±0.075 | 2.23±00.05 + 4.44±00.00 | 40.58±03.26 |
+| Crystal | 2.100±0.006 | 3.76±00.03 + 1.79±00.02 | 43.08±00.46 |
+| D/gdc | 2.137±0.015 | 7.05±00.09 + 3.46±00.03 | 37.92±01.38 |
+| Java | 2.248±0.032 | 38.45±00.09 + 360.35±13.12 | 49.02±02.22 |
+| Ruby | 2.336±0.029 | 14.41±00.05 + 42.64±00.90 | 53.21±02.22 |
+| Ruby (--jit) | 2.364±0.048 | 14.47±00.04 + 43.78±00.06 | 53.65±03.10 |
+| Kotlin | 2.411±0.058 | 39.43±00.08 + 339.98±11.43 | 51.45±02.95 |
+| Go | 2.497±0.007 | 4.52±00.13 + 4.89±00.10 | 47.17±00.43 |
+| Scala | 2.518±0.028 | 81.21±00.46 + 64.54±07.62 | 55.40±03.45 |
+| C++/g++ (libcrypto) | 2.623±0.028 | 5.34±00.04 + 0.07±00.00 | 47.14±00.51 |
+| PHP | 2.945±0.031 | 15.72±00.15 + 0.00±00.00 | 51.14±01.07 |
+| Perl (MIME::Base64) | 3.024±0.046 | 14.16±00.03 + 0.02±00.00 | 52.92±01.33 |
+| Node.js | 3.065±0.030 | 29.89±00.05 + 1029.92±00.07 | 67.19±00.76 |
+| Go/gccgo | 3.660±0.012 | 22.07±00.12 + 7.22±00.22 | 72.73±00.40 |
+| D/dmd | 3.663±0.066 | 3.67±00.06 + 3.67±00.00 | 74.06±00.79 |
+| Tcl | 4.295±0.072 | 5.06±00.05 + 0.00±00.00 | 73.76±01.81 |
+| Python/pypy | 4.723±0.117 | 64.13±00.15 + 45.72±00.05 | 101.07±05.88 |
+| C#/.NET Core | 5.213±0.062 | 34.44±00.09 + 41.21±01.20 | 97.46±00.94 |
+| Python | 5.448±0.112 | 9.21±00.05 + 0.18±00.00 | 102.56±05.80 |
+| Julia | 5.857±0.093 | 200.32±00.21 + 42.88±00.21 | 111.74±01.76 |
+| Ruby/truffleruby (--jvm) | 5.859±0.142 | 551.20±02.74 + 399.55±28.65 | 124.74±07.81 |
+| C#/Mono | 7.565±0.204 | 20.60±00.05 + 18.49±00.06 | 144.66±05.48 |
+| Ruby/jruby | 9.862±0.279 | 192.07±03.01 + 173.11±05.41 | 213.68±16.56 |
+| Perl (MIME::Base64::Perl) | 16.414±0.631 | 15.46±00.05 + 0.20±00.08 | 353.95±27.54 |
+| Ruby/truffleruby | 20.647±0.721 | 253.00±00.31 + 404.70±00.60 | 413.32±37.94 |
## Json
@@ -193,58 +197,58 @@ Testing parsing and simple calculating of values from a big JSON file.
[Json](json)
-| Language | Time, s | Memory, MiB | Energy, J |
-| :------------------------------ | ----------------------: | -------------------------------------------------: | -----------------------: |
-| C++/g++ (DAW JSON Link) | 0.087±0.003 | 109.28±00.04 + 0.00±00.00 | 1.73±00.10 |
-| C++/g++ (simdjson On-Demand) | 0.091±0.002 | 109.62±00.24 + 59.90±00.09 | 1.72±00.11 |
-| D/gdc (fast) | 0.111±0.000 | 219.99±00.10 + 11.09±00.00 | 2.15±00.08 |
-| Rust (Serde Custom) | 0.152±0.003 | 108.40±00.06 + 0.00±00.00 | 2.54±00.07 |
-| Rust (Serde Typed) | 0.158±0.002 | 108.50±00.09 + 11.77±00.19 | 2.60±00.10 |
-| C++/g++ (gason) | 0.163±0.003 | 109.26±00.01 + 97.17±00.00 | 3.19±00.15 |
-| C++/g++ (simdjson DOM) | 0.169±0.002 | 109.85±00.05 + 176.60±00.00 | 3.22±00.06 |
-| C++/g++ (RapidJSON) | 0.227±0.007 | 109.26±00.01 + 128.85±00.03 | 5.00±00.44 |
-| C++/g++ (Boost.JSON) | 0.502±0.010 | 109.76±00.01 + 435.70±00.00 | 11.39±00.55 |
-| Java | 0.522±0.018 | 252.52±00.10 + 74.25±00.75 | 14.47±00.36 |
-| C++/g++ (RapidJSON SAX) | 0.567±0.014 | 109.46±00.04 + 0.00±00.00 | 11.43±00.56 |
-| Scala | 0.588±0.016 | 327.12±00.93 + 74.86±00.92 | 15.12±00.83 |
-| Node.js | 0.665±0.021 | 243.12±00.07 + 184.81±00.18 | 15.24±01.17 |
-| Go (jsoniter) | 0.703±0.022 | 224.85±00.09 + 13.71±00.10 | 14.27±00.99 |
-| Julia (JSON3) | 0.710±0.019 | 408.21±00.90 + 141.92±00.89 | 12.78±00.14 |
-| Python/pypy | 0.827±0.020 | 277.20±00.18 + 127.96±00.00 | 18.50±01.17 |
-| Rust (Serde Untyped) | 0.875±0.012 | 108.46±00.07 + 839.98±00.00 | 19.34±00.64 |
-| Crystal (Schema) | 0.889±0.045 | 110.32±00.05 + 46.85±00.09 | 16.80±00.73 |
-| Crystal (Pull) | 0.901±0.043 | 110.34±00.04 + 18.23±00.01 | 15.21±01.31 |
-| Perl (Cpanel::JSON::XS) | 1.025±0.020 | 121.62±00.08 + 402.76±00.03 | 19.48±00.72 |
-| Go | 1.107±0.031 | 113.88±00.13 + 95.54±00.16 | 24.14±01.13 |
-| Crystal | 1.159±0.017 | 110.31±00.07 + 393.35±00.02 | 24.91±00.86 |
-| V/clang | 1.232±0.018 | 107.89±00.02 + 484.45±00.06 | 27.71±00.73 |
-| PHP | 1.243±0.020 | 121.59±00.04 + 682.01±00.00 | 25.89±00.38 |
-| V/gcc | 1.330±0.017 | 107.43±00.05 + 484.56±00.00 | 23.84±00.92 |
-| Go/gccgo | 1.443±0.024 | 132.33±00.23 + 96.04±00.04 | 31.07±00.79 |
-| Nim/clang (Packedjson) | 1.477±0.024 | 109.02±00.06 + 290.81±00.00 | 32.36±00.67 |
-| C++/g++ (json-c) | 1.541±0.052 | 109.48±00.03 + 1216.08±00.00 | 34.25±01.00 |
-| Nim/gcc (Packedjson) | 1.566±0.015 | 108.54±00.04 + 290.81±00.00 | 27.16±00.44 |
-| Clojure | 1.611±0.019 | 483.89±04.47 + 529.38±25.20 | 41.64±01.98 |
-| Haskell | 1.740±0.036 | 4.79±00.06 + 5.76±00.08 | 39.03±00.59 |
-| Python | 1.785±0.042 | 115.90±00.03 + 377.23±00.01 | 37.85±02.11 |
-| CPython (UltraJSON) | 1.813±0.026 | 117.51±00.06 + 544.41±01.03 | 39.64±01.78 |
-| Nim/gcc | 1.858±0.058 | 108.55±00.01 + 915.81±00.00 | 36.52±02.83 |
-| Nim/clang | 1.969±0.021 | 109.01±00.03 + 915.75±00.00 | 35.52±00.93 |
-| C#/.NET Core | 2.047±0.042 | 472.62±00.04 + 288.50±00.03 | 43.35±02.30 |
-| Ruby | 2.197±0.020 | 120.73±00.03 + 277.82±00.05 | 50.09±00.62 |
-| D/gdc | 2.211±0.017 | 113.23±00.10 + 600.30±00.00 | 46.68±01.28 |
-| Ruby (YAJL) | 2.223±0.014 | 120.66±00.03 + 287.03±00.01 | 49.99±01.09 |
-| C#/Mono | 2.233±0.041 | 462.10±00.08 + 0.17±00.00 | 39.21±01.32 |
-| Ruby (--jit) | 2.245±0.059 | 120.77±00.05 + 277.87±00.16 | 50.96±00.94 |
-| D/ldc2 | 2.560±0.023 | 109.60±00.04 + 680.21±00.00 | 51.78±00.54 |
-| Rust (jq) | 3.753±0.117 | 110.43±00.04 + 775.50±00.77 | 77.53±04.71 |
-| Ruby/jruby | 3.834±0.087 | 477.64±08.08 + 1485.96±39.70 | 112.73±03.38 |
-| C++/g++ (Boost.PropertyTree) | 4.629±0.110 | 109.59±00.02 + 1440.03±00.03 | 89.83±06.60 |
-| D/dmd | 5.052±0.027 | 110.11±00.05 + 680.11±00.01 | 98.13±01.90 |
-| C#/.NET Core (System.Text.Json) | 7.049±0.162 | 463.86±00.06 + 183.08±00.02 | 151.72±08.05 |
-| Perl (JSON::Tiny) | 11.629±0.119 | 122.21±00.07 + 525.14±00.04 | 256.57±04.73 |
-| Ruby/truffleruby (--jvm) | 23.532±0.665 | 842.35±06.97 + 1280.99±74.13 | 597.41±27.51 |
-| Ruby/truffleruby | 66.911±1.141 | 532.60±00.30 + 2336.97±87.82 | 1503.14±30.64 |
+| Language | Time, s | Memory, MiB | Energy, J |
+| :------------------------------ | -----------------------: | -------------------------------------------------: | -------------------------: |
+| C++/g++ (DAW JSON Link) | 0.082±0.002 | 109.27±00.02 + 0.00±00.00 | 1.95±00.06 |
+| C++/g++ (simdjson On-Demand) | 0.088±0.001 | 109.90±00.05 + 59.81±00.12 | 1.69±00.08 |
+| D/gdc (fast) | 0.100±0.001 | 219.98±00.03 + 11.12±00.03 | 2.58±00.06 |
+| Rust (Serde Custom) | 0.141±0.001 | 108.43±00.09 + 0.00±00.00 | 2.35±00.04 |
+| Rust (Serde Typed) | 0.150±0.001 | 108.48±00.07 + 11.51±00.03 | 2.52±00.04 |
+| C++/g++ (gason) | 0.158±0.004 | 109.25±00.01 + 97.17±00.03 | 3.19±00.21 |
+| C++/g++ (simdjson DOM) | 0.160±0.003 | 109.81±00.03 + 176.60±00.00 | 3.21±00.08 |
+| C++/g++ (RapidJSON) | 0.229±0.006 | 109.27±00.02 + 128.82±00.00 | 4.51±00.35 |
+| C++/g++ (Boost.JSON) | 0.481±0.009 | 109.80±00.03 + 435.70±00.00 | 11.83±00.26 |
+| Java | 0.528±0.018 | 252.65±00.15 + 75.46±01.57 | 14.53±00.36 |
+| C++/g++ (RapidJSON SAX) | 0.534±0.021 | 109.46±00.02 + 0.00±00.00 | 11.52±00.82 |
+| Scala | 0.609±0.009 | 327.43±00.58 + 73.55±00.87 | 16.90±00.72 |
+| Julia (JSON3) | 0.615±0.031 | 355.85±00.44 + 243.86±02.20 | 13.47±01.25 |
+| Node.js | 0.663±0.010 | 242.73±00.08 + 185.38±00.82 | 14.04±00.37 |
+| Go (jsoniter) | 0.702±0.019 | 224.79±00.11 + 13.89±00.15 | 14.43±01.07 |
+| Python/pypy | 0.780±0.013 | 277.41±00.16 + 127.96±00.00 | 18.71±00.61 |
+| Rust (Serde Untyped) | 0.846±0.013 | 108.48±00.08 + 839.98±00.00 | 19.09±00.42 |
+| Crystal (Pull) | 0.856±0.033 | 110.30±00.05 + 18.20±00.04 | 16.65±01.40 |
+| Crystal (Schema) | 0.883±0.039 | 110.36±00.03 + 47.05±00.08 | 15.84±01.53 |
+| C#/.NET Core (System.Text.Json) | 0.982±0.018 | 465.50±00.22 + 135.59±00.10 | 22.84±00.75 |
+| Perl (Cpanel::JSON::XS) | 1.000±0.013 | 121.32±00.06 + 402.72±00.00 | 18.21±00.37 |
+| Go | 1.129±0.049 | 113.94±00.19 + 95.95±00.02 | 22.35±01.99 |
+| Crystal | 1.147±0.029 | 110.37±00.03 + 393.35±00.03 | 24.00±01.31 |
+| PHP | 1.204±0.012 | 121.69±00.09 + 682.01±00.00 | 25.92±00.20 |
+| V/gcc | 1.211±0.024 | 107.42±00.01 + 484.49±00.03 | 27.41±00.83 |
+| V/clang | 1.299±0.021 | 107.91±00.03 + 484.48±00.03 | 29.13±01.05 |
+| Go/gccgo | 1.401±0.025 | 132.57±00.07 + 95.88±00.20 | 31.66±01.06 |
+| Nim/gcc (Packedjson) | 1.458±0.035 | 108.80±00.04 + 290.55±00.00 | 31.04±03.08 |
+| Nim/clang (Packedjson) | 1.459±0.028 | 109.22±00.08 + 290.55±00.00 | 34.02±00.59 |
+| C++/g++ (json-c) | 1.561±0.044 | 109.42±00.01 + 1216.08±00.00 | 30.31±01.55 |
+| Clojure | 1.561±0.053 | 491.24±08.10 + 516.55±22.59 | 42.27±01.67 |
+| Haskell | 1.701±0.024 | 4.41±00.03 + 5.42±00.03 | 39.66±00.56 |
+| C#/.NET Core | 1.736±0.054 | 474.19±00.09 + 288.64±00.06 | 30.96±01.72 |
+| Nim/gcc | 1.756±0.020 | 108.60±00.11 + 915.75±00.06 | 39.94±01.11 |
+| Python | 1.757±0.056 | 115.88±00.05 + 377.23±00.01 | 38.02±02.48 |
+| CPython (UltraJSON) | 1.771±0.020 | 117.52±00.04 + 545.45±00.90 | 35.77±00.50 |
+| Nim/clang | 1.880±0.064 | 109.09±00.10 + 915.65±00.10 | 37.34±03.24 |
+| C#/Mono | 2.072±0.048 | 462.61±00.08 + 0.18±00.00 | 45.96±02.08 |
+| Ruby (YAJL) | 2.183±0.061 | 120.60±00.03 + 286.98±00.01 | 50.23±02.52 |
+| D/gdc | 2.234±0.115 | 113.23±00.03 + 600.32±00.00 | 44.22±05.07 |
+| Ruby | 2.260±0.067 | 120.71±00.04 + 277.85±00.04 | 42.18±01.80 |
+| Ruby (--jit) | 2.316±0.029 | 120.76±00.02 + 277.83±00.05 | 44.52±01.57 |
+| D/ldc2 | 2.503±0.033 | 109.55±00.05 + 680.07±00.04 | 50.98±01.91 |
+| Rust (jq) | 3.578±0.063 | 110.41±00.05 + 774.34±00.26 | 79.25±01.55 |
+| Ruby/jruby | 3.815±0.041 | 473.21±08.23 + 1448.93±24.01 | 116.78±04.54 |
+| C++/g++ (Boost.PropertyTree) | 4.353±0.127 | 109.59±00.02 + 1440.00±00.00 | 94.67±07.97 |
+| D/dmd | 4.867±0.131 | 110.06±00.04 + 680.07±00.03 | 101.12±04.66 |
+| Perl (JSON::Tiny) | 11.508±0.117 | 121.91±00.06 + 525.12±00.04 | 268.69±04.33 |
+| Ruby/truffleruby (--jvm) | 101.930±0.923 | 730.89±03.57 + 1288.83±43.61 | 2876.01±27.44 |
+| Ruby/truffleruby | 582.209±8.945 | 731.12±00.18 + 2184.33±38.93 | 11738.06±202.59 |
## Matmul
@@ -254,42 +258,42 @@ Testing allocating and multiplying matrices.
| Language | Time, s | Memory, MiB | Energy, J |
| :----------------------- | ------------------------: | ------------------------------------------------: | -------------------------: |
-| D/ldc2 (lubeck) | 0.137±0.001 | 6.72±00.09 + 51.74±00.08 | 7.52±00.04 |
-| Nim/clang (Arraymancer) | 0.142±0.002 | 5.48±00.04 + 51.56±00.00 | 7.78±00.07 |
-| Nim/gcc (Arraymancer) | 0.150±0.000 | 5.57±00.02 + 51.56±00.00 | 8.35±00.04 |
-| Python (NumPy) | 0.179±0.003 | 27.09±00.07 + 51.76±00.00 | 9.69±00.05 |
-| Java (ND4J) | 0.187±0.016 | 136.80±03.36 + 87.35±00.00 | 8.93±01.00 |
-| Julia (threads: 8) | 0.194±0.002 | 239.15±00.44 + 46.04±00.22 | 10.09±00.13 |
-| Julia (threads: 1) | 0.523±0.008 | 239.18±00.25 + 45.49±00.01 | 12.43±00.50 |
-| D/ldc2 | 1.944±0.005 | 3.46±00.09 + 70.11±00.00 | 42.60±00.52 |
-| D/gdc | 2.057±0.012 | 6.67±00.04 + 70.71±00.00 | 47.61±00.92 |
-| D/dmd | 2.100±0.026 | 3.84±00.04 + 70.43±00.00 | 47.27±00.61 |
-| Java | 3.275±0.011 | 37.94±00.07 + 77.19±00.13 | 75.91±01.83 |
-| C/gcc | 3.288±0.006 | 2.03±00.02 + 68.06±00.00 | 75.73±01.24 |
-| Rust | 3.355±0.008 | 2.61±00.11 + 68.32±00.00 | 68.01±00.52 |
-| Nim/gcc | 3.425±0.011 | 2.55±00.09 + 77.34±07.09 | 69.39±01.38 |
-| Scala | 3.450±0.015 | 79.25±05.38 + 71.40±05.68 | 80.02±02.01 |
-| Nim/clang | 3.459±0.025 | 3.09±00.03 + 75.80±05.67 | 71.13±00.84 |
-| Julia (no BLAS) | 3.478±0.049 | 175.71±00.08 + 70.04±00.04 | 72.18±00.85 |
-| Go/gccgo | 3.535±0.031 | 21.32±00.15 + 72.88±00.12 | 73.13±01.32 |
-| Go | 3.549±0.019 | 3.72±00.02 + 73.50±00.23 | 75.80±01.20 |
-| V/gcc | 3.561±0.015 | 1.96±00.04 + 68.84±00.00 | 78.66±04.04 |
-| Swift | 3.577±0.015 | 149.02±00.06 + 59.88±00.10 | 88.52±00.94 |
-| V/clang | 3.589±0.023 | 2.41±00.04 + 68.84±00.00 | 78.70±03.86 |
-| Crystal | 3.735±0.120 | 4.15±00.06 + 59.66±00.05 | 86.20±03.69 |
-| Node.js | 3.844±0.137 | 33.97±00.05 + 70.96±00.09 | 78.02±08.53 |
-| Kotlin | 3.975±0.176 | 37.60±00.11 + 78.11±00.12 | 73.55±05.83 |
-| Python/pypy | 6.357±0.166 | 64.19±00.07 + 69.19±00.02 | 115.30±06.42 |
-| C#/.NET Core | 6.801±0.194 | 33.19±00.04 + 69.24±00.01 | 152.98±08.29 |
-| C#/Mono | 10.657±0.226 | 20.15±00.04 + 69.04±00.03 | 227.93±10.56 |
-| Ruby/truffleruby | 51.967±1.464 | 423.34±00.44 + 320.91±01.45 | 1094.70±90.05 |
-| Ruby/truffleruby (--jvm) | 71.432±0.730 | 736.79±19.45 + 310.91±14.36 | 1751.33±46.57 |
-| Ruby | 218.581±6.384 | 15.12±00.02 + 68.87±00.03 | 4453.92±329.16 |
-| Ruby (--jit) | 219.854±5.378 | 15.18±00.02 + 69.08±00.06 | 4231.52±319.08 |
-| Python | 247.284±5.100 | 9.97±00.01 + 68.58±00.00 | 4808.31±369.14 |
-| Tcl | 350.227±14.139 | 7.22±00.03 + 400.44±00.03 | 7283.56±481.47 |
-| Perl | 384.838±3.283 | 8.88±00.05 + 599.59±00.03 | 9488.54±129.93 |
-| Ruby/jruby | 491.907±6.937 | 268.25±03.80 + 669.53±05.06 | 10651.33±411.72 |
+| D/ldc2 (lubeck) | 0.069±0.001 | 6.70±00.04 + 56.29±00.19 | 3.83±00.09 |
+| Nim/clang (Arraymancer) | 0.070±0.001 | 5.54±00.04 + 57.67±00.02 | 4.02±00.04 |
+| Nim/gcc (Arraymancer) | 0.079±0.001 | 5.53±00.04 + 57.67±00.02 | 4.70±00.09 |
+| Python (NumPy) | 0.105±0.002 | 27.06±00.06 + 57.64±00.04 | 5.91±00.21 |
+| Julia (threads: 8) | 0.190±0.003 | 222.04±00.19 + 52.41±00.12 | 11.08±00.30 |
+| Java (ND4J) | 0.206±0.026 | 137.15±03.95 + 87.35±00.00 | 9.96±01.00 |
+| Julia (threads: 1) | 0.531±0.019 | 221.56±00.17 + 53.05±00.22 | 12.27±00.94 |
+| D/ldc2 | 1.965±0.010 | 3.55±00.04 + 70.11±00.00 | 43.78±00.60 |
+| D/gdc | 2.072±0.027 | 6.68±00.05 + 70.70±00.01 | 48.59±01.94 |
+| D/dmd | 2.103±0.009 | 3.75±00.11 + 70.43±00.13 | 48.29±00.94 |
+| Java | 3.289±0.020 | 37.92±00.04 + 77.27±00.26 | 74.62±01.52 |
+| C/gcc | 3.320±0.010 | 2.03±00.02 + 68.06±00.00 | 76.08±01.58 |
+| Rust | 3.363±0.008 | 2.62±00.06 + 68.32±00.00 | 69.32±01.58 |
+| Nim/gcc | 3.434±0.017 | 2.63±00.03 + 74.77±04.64 | 70.32±01.18 |
+| Scala | 3.451±0.039 | 84.70±00.88 + 80.50±03.14 | 80.20±01.58 |
+| Nim/clang | 3.454±0.009 | 3.08±00.06 + 72.19±02.19 | 71.54±01.32 |
+| Julia (no BLAS) | 3.503±0.024 | 177.98±00.14 + 69.74±00.07 | 74.83±00.82 |
+| Go | 3.572±0.037 | 3.79±00.08 + 73.24±00.23 | 76.44±01.29 |
+| Go/gccgo | 3.604±0.055 | 27.67±06.19 + 72.72±00.21 | 75.21±00.74 |
+| Crystal | 3.623±0.010 | 4.13±00.04 + 59.70±00.01 | 90.24±00.72 |
+| V/clang | 3.642±0.054 | 2.44±00.01 + 68.84±00.00 | 90.91±01.22 |
+| Swift | 3.657±0.059 | 148.95±00.13 + 59.76±00.07 | 87.78±02.97 |
+| Node.js | 3.891±0.137 | 33.06±00.01 + 71.18±00.03 | 82.84±05.76 |
+| Kotlin | 3.990±0.016 | 37.62±00.11 + 77.96±00.23 | 69.54±02.71 |
+| V/gcc | 4.671±0.152 | 1.97±00.05 + 68.84±00.00 | 97.06±09.17 |
+| Python/pypy | 6.261±0.256 | 64.29±00.20 + 69.20±00.03 | 122.94±12.29 |
+| C#/.NET Core | 6.892±0.269 | 33.88±00.14 + 69.12±00.01 | 150.17±12.02 |
+| C#/Mono | 10.532±0.078 | 20.20±00.05 + 69.02±00.01 | 237.07±02.79 |
+| Ruby/truffleruby | 38.623±0.297 | 527.69±00.21 + 482.24±03.58 | 706.62±15.54 |
+| Ruby/truffleruby (--jvm) | 70.781±1.848 | 597.32±03.94 + 330.89±08.63 | 1912.53±68.70 |
+| Ruby (--jit) | 213.343±7.607 | 15.17±00.04 + 69.09±00.00 | 4581.51±99.85 |
+| Ruby | 214.756±3.892 | 15.14±00.04 + 68.89±00.00 | 4585.32±103.55 |
+| Python | 240.588±5.667 | 9.84±00.04 + 68.58±00.00 | 5021.18±181.03 |
+| Tcl | 348.604±8.750 | 7.25±00.03 + 400.41±00.03 | 7605.35±576.78 |
+| Perl | 402.099±5.437 | 8.96±00.08 + 599.69±00.05 | 8531.93±821.67 |
+| Ruby/jruby | 488.395±11.851 | 279.21±05.66 + 658.86±07.14 | 10808.74±390.65 |
## Havlak
@@ -299,20 +303,20 @@ Testing Havlak's loop finder implementations.
| Language | Time, s | Memory, MiB | Energy, J |
| :----------- | -----------------------: | ------------------------------------------------: | ------------------------: |
-| Crystal | 6.919±0.034 | 3.31±00.03 + 225.37±00.68 | 170.28±02.29 |
-| C++/g++ | 13.672±0.160 | 1.49±00.00 + 176.77±00.03 | 294.67±03.91 |
-| Nim/gcc | 13.863±0.319 | 1.85±00.04 + 498.51±03.35 | 318.93±19.72 |
-| Nim/clang | 13.891±0.151 | 2.29±00.01 + 504.69±00.16 | 342.27±07.22 |
-| C#/.NET Core | 14.928±0.117 | 32.35±00.05 + 1357.19±39.35 | 371.50±01.94 |
-| Scala | 17.869±0.326 | 75.99±03.94 + 312.90±01.65 | 559.85±12.85 |
-| Go | 18.582±0.064 | 3.58±00.03 + 364.18±00.38 | 427.98±04.67 |
-| D/ldc2 | 18.731±0.256 | 2.95±00.03 + 475.72±04.96 | 498.51±07.46 |
-| D/gdc | 22.151±0.494 | 6.25±00.07 + 345.21±00.01 | 480.81±24.95 |
-| D/dmd | 23.633±0.093 | 3.20±00.07 + 438.16±00.34 | 569.98±08.72 |
-| C#/Mono | 25.318±0.340 | 19.79±00.03 + 314.47±01.46 | 621.60±42.61 |
-| Go/gccgo | 26.014±0.120 | 21.01±00.32 + 361.91±04.37 | 663.53±10.03 |
-| Python/pypy | 28.480±0.449 | 65.90±00.25 + 569.64±06.46 | 685.08±14.01 |
-| Python | 103.731±2.547 | 9.02±00.03 + 398.56±00.00 | 2379.21±104.07 |
+| Crystal | 6.967±0.047 | 3.35±00.02 + 225.61±00.81 | 168.07±01.75 |
+| Nim/clang | 13.876±0.242 | 2.32±00.05 + 504.98±00.32 | 339.76±09.64 |
+| Nim/gcc | 13.951±0.290 | 1.84±00.06 + 514.59±02.96 | 319.73±19.33 |
+| C#/.NET Core | 14.376±0.124 | 33.19±00.05 + 1325.18±49.91 | 354.88±02.69 |
+| C++/g++ | 14.675±0.092 | 1.49±00.01 + 176.74±00.02 | 319.49±03.11 |
+| Scala | 18.237±0.566 | 79.12±00.19 + 307.60±05.21 | 558.81±14.47 |
+| Go | 18.649±0.070 | 3.58±00.01 + 365.72±03.81 | 427.89±02.08 |
+| D/ldc2 | 18.784±0.311 | 2.98±00.04 + 475.59±00.64 | 496.34±11.13 |
+| D/gdc | 21.677±0.106 | 6.27±00.03 + 345.24±00.01 | 500.98±06.03 |
+| D/dmd | 23.556±0.149 | 3.24±00.03 + 438.52±00.27 | 573.23±05.91 |
+| C#/Mono | 25.040±0.277 | 19.86±00.07 + 316.46±01.31 | 636.95±27.02 |
+| Go/gccgo | 26.036±0.202 | 20.96±00.13 + 358.92±06.52 | 662.70±08.52 |
+| Python/pypy | 28.213±0.522 | 65.76±00.21 + 560.36±51.36 | 677.92±15.99 |
+| Python | 101.997±2.348 | 9.03±00.04 + 398.56±00.00 | 2319.85±150.21 |
# Tests Execution
@@ -324,45 +328,45 @@ Base Docker image: Debian GNU/Linux bullseye/sid
| Language | Version |
| ---------------- | ------------------------------- |
-| .NET Core | 3.1.109 |
-| C#/.NET Core | 3.4.1-beta4-20127-10 (d8180a5e) |
+| .NET Core | 5.0.100 |
+| C#/.NET Core | 3.8.0-5.20519.18 (4c195c3a) |
| C#/Mono | 6.12.0.90 |
-| C/clang | 10.0.1 |
+| C/clang | 11.0.0 |
| C/gcc | 10.2.0 |
| Chez Scheme | 9.5.4 |
| Clojure | "1.10.1" |
| Crystal | 0.35.1 |
-| D/dmd | v2.094.0 |
+| D/dmd | v2.094.2 |
| D/gdc | 10.2.0 |
-| D/ldc2 | 1.23.0 |
+| D/ldc2 | 1.24.0 |
| Elixir | 1.10.3 |
-| F#/.NET Core | 10.7.0.0 for F# 4.7 |
-| Go | go1.15.2 |
+| F#/.NET Core | 11.0.0.0 for F# 5.0 |
+| Go | go1.15.5 |
| Go/gccgo | 10.2.0 |
| Haskell | 8.10.2 |
-| Java | 15 |
-| Julia | v"1.5.2" |
-| Kotlin | 1.4.10 |
+| Java | 15.0.1 |
+| Julia | v"1.5.3" |
+| Kotlin | 1.4.20 |
| Lua | Lua 5.4 |
| Lua/luajit | LuaJIT 2.1.0-beta3 |
| MLton | 20201002 |
-| Nim | 1.2.6 |
-| Node.js | v14.13.1 |
+| Nim | 1.4.0 |
+| Node.js | v15.3.0 |
| OCaml | 4.11.1 |
-| PHP | 7.4.10 |
-| Perl | v5.30.3 |
+| PHP | 7.4.11 |
+| Perl | v5.32.0 |
| Python | 3.8.6 |
-| Python/pypy | 7.3.2-alpha0 for Python 3.7.4 |
-| Racket | "7.8" |
+| Python/pypy | 7.3.3-beta0 for Python 3.7.9 |
+| Racket | "7.9" |
| Ruby | 2.7.2p137 |
| Ruby/jruby | 9.2.13.0 |
-| Ruby/truffleruby | 20.2.0 |
-| Rust | 1.47.0 |
-| Scala | 2.13.3 |
-| Swift | swift-5.3-RELEASE |
+| Ruby/truffleruby | 20.3.0 |
+| Rust | 1.48.0 |
+| Scala | 2.13.4 |
+| Swift | swift-5.3.1-RELEASE |
| Tcl | 8.6 |
-| V | 0.1.29 |
-| Vala | 0.48.11 |
+| V | 0.1.30 |
+| Vala | 0.48.12 |
## Using Docker
@@ -457,8 +461,10 @@ For Lua:
For Haskell:
- - [network-simple](http://hackage.haskell.org/package/network-simple) for
+ - [network](http://hackage.haskell.org/package/network) for
TCP connectivity between the tests and the test runner.
+ - [raw-strings-qq](http://hackage.haskell.org/package/raw-strings-qq) for
+raw string literals used in tests.
For Perl:
diff --git a/analyze.rb b/analyze.rb
index a6e035f5..bb08650a 100755
--- a/analyze.rb
+++ b/analyze.rb
@@ -12,6 +12,7 @@
ATTEMPTS.times do |n|
puts "--- Iteration #{n + 1}"
+ ENV['QUIET'] = '1'
exit unless system(*ARGV)
end
end
diff --git a/base64/Makefile b/base64/Makefile
index 238c0327..1c8c5535 100644
--- a/base64/Makefile
+++ b/base64/Makefile
@@ -22,7 +22,7 @@ artifacts := $(executables) \
target/Base64Java.class \
target/Test-kt.jar \
target/test.exe \
- target/Release/netcoreapp3.1/base64.dll
+ target/Release/net5.0/base64.dll
all_runners := $(patsubst %,run[%], $(artifacts)) \
run[test.pl] \
@@ -104,8 +104,8 @@ base64.rs/target/release/base64: $(base64-rs-toml)
target/test.exe: test.cs | target
$(MCS_BUILD)
-.PHONY: target/Release/netcoreapp3.1/base64.dll
-target/Release/netcoreapp3.1/base64.dll: base64.csproj | target
+.PHONY: target/Release/net5.0/base64.dll
+target/Release/net5.0/base64.dll: base64.csproj | target
$(DOTNET_BUILD)
target/base64_v_gcc: test.v | $(v_fmt)
@@ -141,7 +141,7 @@ run[target/Test-kt.jar]:: run[%]: %
run[target/test.exe]:: run[%]: %
$(MONO_RUN)
-run[target/Release/netcoreapp3.1/base64.dll]:: run[%]: %
+run[target/Release/net5.0/base64.dll]:: run[%]: %
$(DOTNET_RUN)
.PHONY: base64_perl
diff --git a/base64/base64.csproj b/base64/base64.csproj
index 5f35b2e5..8f612967 100644
--- a/base64/base64.csproj
+++ b/base64/base64.csproj
@@ -1,6 +1,6 @@
- netcoreapp3.1
+ net5.0
Exe
diff --git a/base64/base64.rs/Cargo.lock b/base64/base64.rs/Cargo.lock
index 66f4d227..6cb7bfa6 100644
--- a/base64/base64.rs/Cargo.lock
+++ b/base64/base64.rs/Cargo.lock
@@ -2,15 +2,13 @@
# It is not intended for manual editing.
[[package]]
name = "base64"
-version = "0.12.3"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "base64_rs"
version = "0.0.1"
dependencies = [
- "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "base64",
]
-
-[metadata]
-"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
diff --git a/base64/base64.rs/Cargo.toml b/base64/base64.rs/Cargo.toml
index e31f2f45..693cb95e 100644
--- a/base64/base64.rs/Cargo.toml
+++ b/base64/base64.rs/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.0.1"
edition = "2018"
[dependencies]
-base64 = "0.12.3"
+base64 = "0.13.0"
[profile.release]
lto = true
diff --git a/base64/test-xs.pl b/base64/test-xs.pl
index f5e9e0ae..eb29c707 100644
--- a/base64/test-xs.pl
+++ b/base64/test-xs.pl
@@ -1,7 +1,8 @@
-use v5.12;
+use v5.32;
use warnings;
+no feature qw(indirect);
use feature qw(signatures);
-no warnings qw(experimental::signatures);
+no warnings qw(experimental);
use MIME::Base64 qw(encode_base64 decode_base64);
use Time::HiRes 'time';
diff --git a/base64/test.js b/base64/test.js
index cc3137b1..f5c269e7 100644
--- a/base64/test.js
+++ b/base64/test.js
@@ -1,4 +1,7 @@
+'use strict';
+
const assert = require("assert");
+const net = require('net');
const util = require('util');
const STR_SIZE = 131072;
@@ -9,7 +12,7 @@ async function main() {
const str2 = b.toString('base64');
const str3 = Buffer.from(str2, 'base64');
- await notify(`Node.js\t${require('process').pid}`);
+ await notify(`Node.js\t${process.pid}`);
var s_encoded = 0;
const start = new Date();
@@ -40,7 +43,7 @@ async function main() {
function notify(msg) {
return new Promise(resolve => {
- const client = require('net').connect(9001, 'localhost', () => {
+ const client = net.connect(9001, 'localhost', () => {
client.end(msg, 'utf8', () => {
client.destroy();
resolve();
diff --git a/base64/test.pl b/base64/test.pl
index 16623572..91494a5d 100644
--- a/base64/test.pl
+++ b/base64/test.pl
@@ -1,7 +1,8 @@
-use v5.12;
+use v5.32;
use warnings;
+no feature qw(indirect);
use feature qw(signatures);
-no warnings qw(experimental::signatures);
+no warnings qw(experimental);
use MIME::Base64::Perl qw(encode_base64 decode_base64);
use Time::HiRes 'time';
diff --git a/base64/test.v b/base64/test.v
index e025ab26..74b18270 100644
--- a/base64/test.v
+++ b/base64/test.v
@@ -3,11 +3,13 @@ import net
import time
fn notify(msg string) {
- sock := net.dial('127.0.0.1', 9001) or {
+ sock := net.dial_tcp('127.0.0.1:9001') or {
return
}
- sock.write(msg) or { }
- sock.close() or { }
+ defer {
+ sock.close()
+ }
+ sock.write_str(msg) or { }
}
fn main() {
diff --git a/brainfuck/Makefile b/brainfuck/Makefile
index d43a9fce..3aa483a7 100644
--- a/brainfuck/Makefile
+++ b/brainfuck/Makefile
@@ -26,11 +26,11 @@ executables := \
target/bin_c_clang
artifacts := $(executables) \
- fsharp/target/Release/netcoreapp3.1/brainfuck.dll \
+ fsharp/target/Release/net5.0/brainfuck.dll \
target/bf_scala.jar \
target/bf2-kt.jar \
target/bf.exe \
- target/Release/netcoreapp3.1/brainfuck.dll \
+ target/Release/net5.0/brainfuck.dll \
target/bf.class
fast_runners := $(patsubst %,run[%], $(artifacts)) \
@@ -74,12 +74,12 @@ target/bf_scala.jar: bf.scala | target
target/bf.exe: bf.cs | target
$(MCS_BUILD)
-.PHONY: target/Release/netcoreapp3.1/brainfuck.dll
-target/Release/netcoreapp3.1/brainfuck.dll: brainfuck.csproj | target
+.PHONY: target/Release/net5.0/brainfuck.dll
+target/Release/net5.0/brainfuck.dll: brainfuck.csproj | target
$(DOTNET_BUILD)
-.PHONY: fsharp/target/Release/netcoreapp3.1/brainfuck.dll
-fsharp/target/Release/netcoreapp3.1/brainfuck.dll: fsharp/brainfuck.fsproj | target
+.PHONY: fsharp/target/Release/net5.0/brainfuck.dll
+fsharp/target/Release/net5.0/brainfuck.dll: fsharp/brainfuck.fsproj | target
$(DOTNET_BUILD)
target/bf2-kt.jar: bf2.kt | target
@@ -106,10 +106,10 @@ target/bin_nim_clang: bf.nim | target
target/bin_nim_gcc: bf.nim | target
$(NIM_GCC_BUILD)
-target/bin_hs: bf.hs | target
+target/bin_hs: bf.hs | $(hlint)
$(GHC_BUILD)
-target/bin_hs_marray: bf-marray.hs | target
+target/bin_hs_marray: bf-marray.hs | $(hlint)
$(GHC_BUILD)
target/bin_ocaml: bf.ml | target
@@ -164,10 +164,10 @@ run[target/bf_scala.jar]:: run[%]: %
run[target/bf.exe]:: run[%]: %
$(MONO_RUN) $(BF_SRC)
-run[target/Release/netcoreapp3.1/brainfuck.dll]:: run[%]: %
+run[target/Release/net5.0/brainfuck.dll]:: run[%]: %
$(DOTNET_RUN) $(BF_SRC)
-run[fsharp/target/Release/netcoreapp3.1/brainfuck.dll]:: run[%]: %
+run[fsharp/target/Release/net5.0/brainfuck.dll]:: run[%]: %
$(DOTNET_RUN) $(BF_SRC)
run[target/bf2-kt.jar]:: run[%]: %
@@ -208,13 +208,13 @@ run[jruby][bf.rb]:: run[jruby][%]: % | $(rubocop)
.PHONY: lua-deps
lua-deps:
- $(LUAROCKS_LUA) install luasocket
- $(LUAROCKS_LUA) install luaposix
+ $(LUAROCKS_LUA) install luasocket > /dev/null
+ $(LUAROCKS_LUA) install luaposix > /dev/null
.PHONY: luajit-deps
luajit-deps:
- $(LUAROCKS_LUAJIT) install luasocket
- $(LUAROCKS_LUAJIT) install luaposix
+ $(LUAROCKS_LUAJIT) install luasocket > /dev/null
+ $(LUAROCKS_LUAJIT) install luaposix > /dev/null
run[bf.lua]:: run[%]: % | lua-deps
$(LUA_RUN) $(BF_SRC)
diff --git a/brainfuck/bf-marray.hs b/brainfuck/bf-marray.hs
index 8f06854e..eed48276 100644
--- a/brainfuck/bf-marray.hs
+++ b/brainfuck/bf-marray.hs
@@ -1,19 +1,50 @@
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
module Main where
import qualified Data.Array.Base as ArrayBase
import qualified Data.Array.IO as IOUArray
import qualified Data.Array.MArray as MArray
import qualified Data.ByteString.Char8 as C
-import Network.Simple.TCP
-import Data.Char (chr)
-import System.Environment (getArgs)
+import Control.Exception
+import Control.Monad
+import Data.Bits
+import Data.Char
+import Data.Maybe
+import Network.Socket
+import Network.Socket.ByteString
+import System.Environment
+import System.Exit
import System.IO (hFlush, stdout)
import System.Posix (getProcessID)
+import Text.RawString.QQ
data Op = Inc !Int | Move !Int | Print | Loop ![Op] deriving Show
data Tape = Tape { tapeData :: IOUArray.IOUArray Int Int
, tapePos :: !Int
}
+data Printer = Printer { sum1 :: Int
+ , sum2 :: Int
+ , quiet :: Bool
+ }
+
+write :: Printer -> Int -> IO Printer
+write p n = if quiet p
+ then do let s1 = mod (sum1 p + n) 255
+ let s2 = mod (s1 + sum2 p) 255
+ return Printer {
+ sum1=s1,
+ sum2=s2,
+ quiet=True
+ }
+ else do
+ putStr [chr n]
+ hFlush stdout
+ return p
+
+getChecksum :: Printer -> Int
+getChecksum p = (sum2 p `shiftL` 8) .|. sum1 p
current :: Tape -> IO Int
current tape = ArrayBase.unsafeRead (tapeData tape) (tapePos tape)
@@ -30,11 +61,12 @@ move m tape = do
then return curData
else do
el <- MArray.getElems curData
- MArray.newListArray (0, newPos) (el ++ [0 | i <- [len..newPos]])
+ MArray.newListArray (0, newPos)
+ (el ++ replicate (newPos - len + 1) 0)
return $ Tape newData newPos
where
curData = tapeData tape
- newPos = (tapePos tape) + m
+ newPos = tapePos tape + m
parse :: ([Char], [Op]) -> ([Char], [Op])
parse ([], acc) = ([], reverse acc)
@@ -50,41 +82,72 @@ parse (c:cs, acc) =
']' -> (cs, reverse acc)
_ -> parse (cs, acc)
-run :: [Op] -> Tape -> IO Tape
-run [] tape = return tape
-run (op:ops) tape = do
+run :: [Op] -> Tape -> Printer -> IO (Tape, Printer)
+run [] tape p = return (tape, p)
+run (op:ops) tape p = do
case op of
Inc d -> do
inc d tape
- run ops tape
+ run ops tape p
Move m -> do
newTape <- move m tape
- run ops newTape
+ run ops newTape p
Print -> do
x <- current tape
- putStr $ [chr x]
- hFlush stdout
- run ops tape
+ newP <- write p x
+ run ops tape newP
Loop loop ->
- let go tape = do
- x <- current tape
- if x == 0 then run ops tape
- else run loop tape >>= go
- in go tape
+ let go (newTape, newP) = do
+ x <- current newTape
+ if x == 0 then run ops newTape newP
+ else run loop newTape newP >>= go
+ in go (tape, p)
-notify msg = do
- connect "localhost" "9001" $ \(socket, _) -> do
- send socket $ C.pack msg
+notify :: String -> IO ()
+notify msg = withSocketsDo $ do
+ addr <- resolve
+ catch (_notify addr) (\(_ :: IOException) -> return ())
+ where
+ writeMsg s = sendAll s $ C.pack msg
+ resolve = do
+ let hints = defaultHints { addrSocketType = Stream }
+ head <$> getAddrInfo (Just hints) (Just "localhost") (Just "9001")
+ _notify addr = bracket (openSocket addr) close $ \sock -> do
+ connect sock $ addrAddress addr
+ writeMsg sock
+verify :: IO ()
+verify = do
+ let source = [r|++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>\
+ ---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.|]
+ let (_, ops) = parse (source, [])
+ empty <- MArray.newListArray (0, 0) [0]
+ (_, pLeft) <- run ops
+ (Tape empty 0)
+ Printer {sum1=0, sum2=0, quiet=True}
+ let left = getChecksum pLeft
+
+ pRight <- foldM (\p c -> write p $ ord c)
+ (Printer {sum1=0, sum2=0, quiet=True})
+ "Hello World!\n"
+ let right = getChecksum pRight
+ when (left /= right)
+ $ die $ show left ++ " != " ++ show right
+
+main :: IO ()
main = do
+ verify
[filename] <- getArgs
source <- readFile filename
+ quiet_env <- lookupEnv "QUIET"
+ let p = Printer {sum1=0, sum2=0, quiet=isJust quiet_env}
pid <- getProcessID
notify $ "Haskell (MArray)\t" ++ show pid
-
let (_, ops) = parse (source, [])
empty <- MArray.newListArray (0, 0) [0]
- run ops $ Tape empty 0
-
+ (_, newP) <- run ops (Tape empty 0) p
notify "stop"
+
+ when (quiet newP)
+ $ do putStrLn $ "Output checksum: " ++ show (getChecksum newP)
diff --git a/brainfuck/bf.c b/brainfuck/bf.c
index 1678b463..03a79793 100644
--- a/brainfuck/bf.c
+++ b/brainfuck/bf.c
@@ -1,8 +1,9 @@
+#include
+#include
#include
#include
#include
#include
-#include
#ifdef __clang__
# define COMPILER "clang"
@@ -13,279 +14,295 @@
struct op_list;
enum op_type {
- OP_INC,
- OP_MOVE,
- OP_LOOP,
- OP_PRINT
+ OP_INC,
+ OP_MOVE,
+ OP_LOOP,
+ OP_PRINT
};
union op_value {
- int offset;
- struct op_list *list;
+ int offset;
+ struct op_list *list;
};
struct op {
- enum op_type type;
- union op_value value;
+ enum op_type type;
+ union op_value value;
};
struct op_list {
- struct op *ops;
- int cap, len;
+ struct op *ops;
+ int cap, len;
};
struct op op_new(enum op_type type, union op_value value)
{
- struct op op;
+ struct op op;
- op.type = type;
- if (type == OP_LOOP)
- op.value.list = value.list;
- else
- op.value.offset = value.offset;
+ op.type = type;
+ if (type == OP_LOOP)
+ op.value.list = value.list;
+ else
+ op.value.offset = value.offset;
- return op;
+ return op;
}
void op_list_free(struct op_list *list);
void op_free(struct op op)
{
- if (op.type == OP_LOOP) {
- op_list_free(op.value.list);
- free(op.value.list);
- }
-}
-
-void op_list_init(struct op_list *list)
-{
- list->len = 0;
- list->cap = 0;
- list->ops = NULL;
+ if (op.type == OP_LOOP) {
+ op_list_free(op.value.list);
+ free(op.value.list);
+ }
}
void op_list_free(struct op_list *list)
{
- int i;
+ int i;
- for (i = 0; i < list->len; i += 1)
- op_free(list->ops[i]);
+ for (i = 0; i < list->len; i += 1)
+ op_free(list->ops[i]);
- free(list->ops);
+ free(list->ops);
}
void op_list_grow(struct op_list *list)
{
- if (list->ops == NULL) {
- list->cap = 4;
- } else {
- /* double the capacity */
- list->cap <<= 1;
- }
- list->ops = realloc(list->ops, sizeof(struct op) * list->cap);
+ if (list->ops == NULL) {
+ list->cap = 4;
+ } else {
+ /* double the capacity */
+ list->cap <<= 1;
+ }
+ list->ops = realloc(list->ops, sizeof(struct op) * list->cap);
}
int op_list_length(const struct op_list *list)
{
- return list->len;
+ return list->len;
}
struct op op_list_get(const struct op_list *list, int i)
{
- return list->ops[i];
+ return list->ops[i];
}
void op_list_push(struct op_list *list, struct op op)
{
- if (list->len == list->cap)
- op_list_grow(list);
+ if (list->len == list->cap)
+ op_list_grow(list);
- list->ops[list->len++] = op;
+ list->ops[list->len++] = op;
}
struct string_iterator {
- const char *string;
- int pos;
+ const char *string;
+ int pos;
};
-void string_iterator_init(struct string_iterator *it, const char *s)
+char string_iterator_next(struct string_iterator *it)
{
- it->string = s;
- it->pos = 0;
+ return it->string[it->pos++];
}
-char string_iterator_next(struct string_iterator *it)
-{
- return it->string[it->pos++];
+struct printer {
+ int sum1;
+ int sum2;
+ bool quiet;
+};
+
+void print(struct printer *p, int n) {
+ if (p->quiet) {
+ p->sum1 = (p->sum1 + n) % 255;
+ p->sum2 = (p->sum2 + p->sum1) % 255;
+ } else {
+ putc(n, stdout);
+ fflush(stdout);
+ }
+}
+
+int get_checksum(const struct printer *p) {
+ return (p->sum2 << 8) | p->sum1;
}
void parse(struct string_iterator *it, struct op_list *ops)
{
- char c;
- struct op_list *loop_ops;
- union op_value value;
- enum op_type type;
-
- while ((c = string_iterator_next(it))) {
- switch (c) {
- case '+':
- type = OP_INC;
- value.offset = 1;
- break;
- case '-':
- type = OP_INC;
- value.offset = -1;
- break;
- case '>':
- type = OP_MOVE;
- value.offset = 1;
- break;
- case '<':
- type = OP_MOVE;
- value.offset = -1;
- break;
- case '.':
- type = OP_PRINT;
- value.offset = 0;
- break;
- case '[':
- loop_ops = malloc(sizeof(struct op_list));
- op_list_init(loop_ops);
- parse(it, loop_ops);
-
- type = OP_LOOP;
- value.list = loop_ops;
- break;
- case ']':
- return;
- default:
- continue;
- }
-
- op_list_push(ops, op_new(type, value));
- }
+ char c;
+ struct op_list *loop_ops;
+ union op_value value;
+ enum op_type type;
+
+ while ((c = string_iterator_next(it))) {
+ switch (c) {
+ case '+':
+ type = OP_INC;
+ value.offset = 1;
+ break;
+ case '-':
+ type = OP_INC;
+ value.offset = -1;
+ break;
+ case '>':
+ type = OP_MOVE;
+ value.offset = 1;
+ break;
+ case '<':
+ type = OP_MOVE;
+ value.offset = -1;
+ break;
+ case '.':
+ type = OP_PRINT;
+ value.offset = 0;
+ break;
+ case '[':
+ loop_ops = calloc(1, sizeof(struct op_list));
+ parse(it, loop_ops);
+
+ type = OP_LOOP;
+ value.list = loop_ops;
+ break;
+ case ']':
+ return;
+ default:
+ continue;
+ }
+
+ op_list_push(ops, op_new(type, value));
+ }
}
struct tape {
- int *tape;
- int cap, pos;
+ int *tape;
+ int cap, pos;
};
-void tape_init(struct tape *tape)
-{
- tape->pos = 0;
- tape->cap = 1;
- tape->tape = malloc(sizeof(int));
- *tape->tape = 0;
-}
-
-void tape_free(struct tape tape)
-{
- free(tape.tape);
-}
-
char tape_get(const struct tape tape)
{
- return tape.tape[tape.pos];
+ return tape.tape[tape.pos];
}
void tape_grow(struct tape *tape)
{
- int i, new_cap;
+ int i, new_cap;
- new_cap = tape->cap << 1;
- tape->tape = realloc(tape->tape, sizeof(int) * new_cap);
+ new_cap = tape->cap << 1;
+ tape->tape = realloc(tape->tape, sizeof(int) * new_cap);
- for (i = tape->cap; i < new_cap; i += 1)
- tape->tape[i] = 0;
+ for (i = tape->cap; i < new_cap; i += 1)
+ tape->tape[i] = 0;
- tape->cap = new_cap;
+ tape->cap = new_cap;
}
void tape_move(struct tape *tape, int amount)
{
- tape->pos += amount;
+ tape->pos += amount;
- if (tape->pos >= tape->cap)
- tape_grow(tape);
+ if (tape->pos >= tape->cap)
+ tape_grow(tape);
}
void tape_inc(struct tape tape, int amount)
{
- tape.tape[tape.pos] += amount;
+ tape.tape[tape.pos] += amount;
}
-void eval(const struct op_list *ops, struct tape *tape)
-{
- int i, len;
- struct op op;
-
- for (i = 0, len = op_list_length(ops); i < len; i += 1) {
- switch ((op = op_list_get(ops, i)).type) {
- case OP_INC:
- tape_inc(*tape, op.value.offset);
- break;
- case OP_MOVE:
- tape_move(tape, op.value.offset);
- break;
- case OP_LOOP:
- while (tape_get(*tape) > 0)
- eval(op.value.list, tape);
- break;
- case OP_PRINT:
- putc(tape_get(*tape), stdout);
- fflush(stdout);
- break;
- }
- }
+void eval(const struct op_list *ops, struct tape *tape, struct printer *p) {
+ int i, len;
+ struct op op;
+
+ for (i = 0, len = op_list_length(ops); i < len; i += 1) {
+ switch ((op = op_list_get(ops, i)).type) {
+ case OP_INC:
+ tape_inc(*tape, op.value.offset);
+ break;
+ case OP_MOVE:
+ tape_move(tape, op.value.offset);
+ break;
+ case OP_LOOP:
+ while (tape_get(*tape) > 0)
+ eval(op.value.list, tape, p);
+ break;
+ case OP_PRINT:
+ print(p, tape_get(*tape));
+ break;
+ }
+ }
+}
+
+void run(const char* code, struct printer *p) {
+ struct tape tape = {.tape=calloc(1, sizeof(int)), .cap=1, .pos=0};
+ struct op_list ops = {.ops=NULL, .cap=0, .len=0};
+ struct string_iterator it = {.string=code, .pos=0};
+ parse(&it, &ops);
+ eval(&ops, &tape, p);
+ free(tape.tape);
+ op_list_free(&ops);
+}
+
+void verify() {
+ char text[] = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>"
+ "---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.";
+ struct printer p_left = {.sum1=0, .sum2=0, .quiet=true};
+ run(text, &p_left);
+ int left = get_checksum(&p_left);
+
+ struct printer p_right = {.sum1=0, .sum2=0, .quiet=true};
+ char result[] = "Hello World!\n";
+ size_t i = 0;
+ while (result[i] != '\0') {
+ print(&p_right, result[i++]);
+ }
+ int right = get_checksum(&p_right);
+ if (left != right) {
+ fprintf(stderr, "%d != %d", left, right);
+ exit(EXIT_FAILURE);
+ }
}
int main(int argc, char *argv[]) {
- FILE *f;
- int fsize, notify_len;
- const char *filename;
- char *code;
- char notify_msg[32];
- struct op_list ops;
- struct tape tape;
- struct string_iterator it;
-
- if (argc < 2) {
- fprintf(stderr, "Expected filename\n");
- return EXIT_FAILURE;
- }
-
- filename = argv[1];
-
- f = fopen(filename, "r");
- if (f == NULL) {
- perror("bfc: fopen");
- return EXIT_FAILURE;
- }
-
- fseek(f, 0, SEEK_END);
- fsize = ftell(f);
- fseek(f, 0, SEEK_SET);
-
- code = malloc(sizeof(char) * fsize + 1);
- fread(code, 1, fsize, f);
- fclose(f);
- code[fsize] = 0;
-
- notify_len = snprintf(notify_msg, sizeof(notify_msg),
- "C/" COMPILER "\t%d", getpid());
- notify(notify_msg, notify_len);
-
- tape_init(&tape);
- op_list_init(&ops);
- string_iterator_init(&it, code);
- parse(&it, &ops);
-
- eval(&ops, &tape);
-
- free(code);
- tape_free(tape);
- op_list_free(&ops);
-
- notify("stop", 4);
+ FILE *f;
+ int fsize, notify_len;
+ const char *filename;
+ char *code;
+ char notify_msg[32];
+
+ verify();
+ struct printer p = {.sum1=0, .sum2=0, .quiet=getenv("QUIET") != NULL};
+
+ if (argc < 2) {
+ fprintf(stderr, "Expected filename\n");
+ return EXIT_FAILURE;
+ }
+
+ filename = argv[1];
+
+ f = fopen(filename, "r");
+ if (f == NULL) {
+ perror("bfc: fopen");
+ return EXIT_FAILURE;
+ }
+
+ fseek(f, 0, SEEK_END);
+ fsize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ code = malloc(sizeof(char) * fsize + 1);
+ fread(code, 1, fsize, f);
+ fclose(f);
+ code[fsize] = 0;
+
+ notify_len = snprintf(notify_msg, sizeof(notify_msg),
+ "C/" COMPILER "\t%d", getpid());
+ notify(notify_msg, notify_len);
+ run(code, &p);
+ notify("stop", 4);
+
+ free(code);
+
+ if (p.quiet) {
+ printf("Output checksum: %d\n", get_checksum(&p));
+ }
}
diff --git a/brainfuck/bf.cpp b/brainfuck/bf.cpp
index 831042bb..74908e51 100644
--- a/brainfuck/bf.cpp
+++ b/brainfuck/bf.cpp
@@ -1,10 +1,11 @@
-#include
-#include
-#include