Add plots and concat test
This commit is contained in:
parent
a28db7bc32
commit
2be5cd88bc
1
dub.sdl
1
dub.sdl
|
@ -5,6 +5,7 @@ copyright "Copyright © 2019, Les De Ridder"
|
||||||
license "NCSA"
|
license "NCSA"
|
||||||
dependency "emsi_containers" version="~>0.7.0"
|
dependency "emsi_containers" version="~>0.7.0"
|
||||||
dependency "collections" version="~>0.1.0"
|
dependency "collections" version="~>0.1.0"
|
||||||
|
dependency "matplotlib-d" path="matplotlib-d"
|
||||||
|
|
||||||
-- :/
|
-- :/
|
||||||
importPaths "/home/lesderid/repos/d/druntime/src"
|
importPaths "/home/lesderid/repos/d/druntime/src"
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
"versions": {
|
"versions": {
|
||||||
"collections": "0.1.0",
|
"collections": "0.1.0",
|
||||||
"emsi_containers": "0.7.0",
|
"emsi_containers": "0.7.0",
|
||||||
"mir-algorithm": "3.5.0-alpha09",
|
"matplotlib-d": {"path":"matplotlib-d"},
|
||||||
"mir-core": "0.3.5",
|
|
||||||
"stdx-allocator": "2.77.5"
|
"stdx-allocator": "2.77.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
.dub
|
||||||
|
docs.json
|
||||||
|
__dummy.html
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
__test__*__
|
||||||
|
*~
|
||||||
|
views/
|
||||||
|
build/
|
||||||
|
README.html
|
||||||
|
*.png
|
|
@ -0,0 +1,17 @@
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
language: d
|
||||||
|
|
||||||
|
d:
|
||||||
|
- ldc2
|
||||||
|
- dmd
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install python-tk; fi
|
||||||
|
- sudo pip install matplotlib
|
||||||
|
|
||||||
|
|
||||||
|
script:
|
||||||
|
- dub test --compiler=${DC}
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016-2019 koji-kojiro
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,91 @@
|
||||||
|
# matplotlib-d
|
||||||
|
|
||||||
|
[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)
|
||||||
|
[![Build Status](https://travis-ci.org/koji-kojiro/matplotlib-d.svg?branch=master)](https://travis-ci.org/koji-kojiro/matplotlib-d)
|
||||||
|
[![Dub version](https://img.shields.io/dub/v/matplotlib-d.svg)](https://code.dlang.org/packages/matplotlib-d)
|
||||||
|
[![Dub download](https://img.shields.io/dub/dt/matplotlib-d.svg)](https://code.dlang.org/packages/matplotlib-d)
|
||||||
|
|
||||||
|
2D Plotting library for D using python and matplotlib.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- Python
|
||||||
|
- matplotlib
|
||||||
|
|
||||||
|
`matplotlib-d` uses `python3` by default, thus if you want to use `python2`, set `$MATPLOTLIB_D_PYTHON` to `python2`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
### Installation
|
||||||
|
To use this package, put the following dependency into your project's dependencies section:
|
||||||
|
|
||||||
|
dub.json: `"matplotlib-d": "~>0.1.4"`
|
||||||
|
dub.sdl: `dependency "matplotlib-d" version="~>0.1.4"`
|
||||||
|
|
||||||
|
|
||||||
|
For small applications or scripts, add following sentence to the head of your script.
|
||||||
|
```d
|
||||||
|
#!/usr/bin/env dub
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "name_of_your_application"
|
||||||
|
dependency "matplotlib-d" version="~>0.1.4"
|
||||||
|
+/
|
||||||
|
```
|
||||||
|
And excute with `dub run --single`.
|
||||||
|
For more details, please refer to [the documentation of dub](https://code.dlang.org/getting_started).
|
||||||
|
|
||||||
|
### Syntax
|
||||||
|
Most pyplot functions are available.
|
||||||
|
For more details for each functions, please refer to the [documantation of pyplot](http://matplotlib.org/api/pyplot_summary.html).
|
||||||
|
Describe Python keyword arguments as an associative array with string of keyword name as key.
|
||||||
|
|
||||||
|
- The Python way:
|
||||||
|
*function(arg1, arg2..., keyword1=kwarg1, keyword2=kwarg2...)*
|
||||||
|
- The D way:
|
||||||
|
*function(arg1, arg2..., ["keyword1": kwarg1], ["keyword2": kwarg2])*
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Simple example:
|
||||||
|
```d
|
||||||
|
import std.math;
|
||||||
|
import std.range;
|
||||||
|
import std.algorithm;
|
||||||
|
import plt = matplotlibd.pyplot;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
auto x = iota(0, 2.05, 0.05).map!(x => x * PI);
|
||||||
|
auto y = x.map!(sin);
|
||||||
|
|
||||||
|
plt.plot(x, y, "r-", ["label": "$y=sin(x)$"]);
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
plt.legend();
|
||||||
|
plt.savefig("simple.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
![Simple example](./examples/simple.png)
|
||||||
|
|
||||||
|
Color plot example:
|
||||||
|
|
||||||
|
```d
|
||||||
|
import std.range;
|
||||||
|
import plt = matplotlibd.pyplot;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
const n = 100;
|
||||||
|
auto x = iota(n);
|
||||||
|
auto y = x[];
|
||||||
|
double[n][n] z;
|
||||||
|
|
||||||
|
foreach (i; 0..n)
|
||||||
|
foreach (j; 0..n)
|
||||||
|
z[i][j] = i + j;
|
||||||
|
|
||||||
|
plt.contourf(x, y, z, 64, ["cmap": "hsv"]);
|
||||||
|
plt.colorbar();
|
||||||
|
plt.savefig("color.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
![Color plot example](./examples/color.png)
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"name": "matplotlib-d",
|
||||||
|
"authors": ["koji-kojiro"],
|
||||||
|
"description": "2D Plotting library for D using python and matplotlib",
|
||||||
|
"copyright": "Copyright © 2016-2019, koji-kojiro",
|
||||||
|
"license": "MIT",
|
||||||
|
"targetName": "matplotlibd",
|
||||||
|
"targetType": "staticLibrary",
|
||||||
|
"targetPath": "build",
|
||||||
|
"workingDirectory": "build",
|
||||||
|
"preBuildCommands": ["python3 $PACKAGE_DIR/python/prebuild.py $PACKAGE_DIR"]
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
.dub
|
||||||
|
docs.json
|
||||||
|
__dummy.html
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
__test__*__
|
||||||
|
examples
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "examples",
|
||||||
|
"dependencies": {
|
||||||
|
"matplotlib-d": {"version": "~master", "path": "../"}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
import std.math;
|
||||||
|
import std.range;
|
||||||
|
import std.random;
|
||||||
|
import std.algorithm;
|
||||||
|
import plt = matplotlibd.pyplot;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
simple();
|
||||||
|
color();
|
||||||
|
polar();
|
||||||
|
subplots();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bad() {
|
||||||
|
plt.plot("hoge");
|
||||||
|
plt.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void simple() {
|
||||||
|
auto x = iota(0, 2.05, 0.05).map!(x => x * PI);
|
||||||
|
auto y = x.map!(sin);
|
||||||
|
|
||||||
|
plt.plot(x, y, "r-", ["label": "$y=sin(x)$"]);
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
plt.legend();
|
||||||
|
plt.savefig("simple.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void color() {
|
||||||
|
const n = 100;
|
||||||
|
auto x = iota(n);
|
||||||
|
auto y = x[];
|
||||||
|
double[n][n] z;
|
||||||
|
|
||||||
|
foreach (i; 0..n)
|
||||||
|
foreach (j; 0..n)
|
||||||
|
z[i][j] = i + j;
|
||||||
|
plt.contourf(x, y, z, 64, ["cmap": "hsv"]);
|
||||||
|
plt.colorbar();
|
||||||
|
plt.savefig("color.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void subplots() {
|
||||||
|
auto x = iota(0, 2 * PI + 0.05, 0.05);
|
||||||
|
|
||||||
|
plt.subplot(221);
|
||||||
|
plt.plot(x, x.map!(sin));
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
|
||||||
|
plt.subplot(222);
|
||||||
|
plt.plot(x, x.map!(cos));
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
|
||||||
|
plt.subplot(223);
|
||||||
|
plt.plot(x, x.map!(i => sin(i) * exp(-0.4 * i)));
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
|
||||||
|
plt.subplot(224);
|
||||||
|
plt.plot(x, x.map!(i => cos(i) * exp(-0.4 * i)));
|
||||||
|
plt.xlim(0, 2 * PI);
|
||||||
|
plt.ylim(-1, 1);
|
||||||
|
|
||||||
|
plt.savefig("subplots.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void polar() {
|
||||||
|
|
||||||
|
auto r = iota(0, 1.001, 0.001);
|
||||||
|
auto theta = r.map!(i => i * 32 * PI);
|
||||||
|
auto area = r.map!(i => i * 2000);
|
||||||
|
|
||||||
|
plt.subplot(111, ["projection": "polar"]);
|
||||||
|
plt.scatter(theta, r, ["c": r], ["s": area], ["cmap": "hsv"], ["alpha": 0.25]);
|
||||||
|
plt.savefig("polar.png");
|
||||||
|
plt.clear();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
||||||
|
def extract_function_names(module):
|
||||||
|
'''
|
||||||
|
extract function names from attributes of 'module'.
|
||||||
|
'''
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
|
mod = import_module(module.__name__)
|
||||||
|
attr_list = dir(mod)
|
||||||
|
scope = locals()
|
||||||
|
|
||||||
|
def iscallable(name):
|
||||||
|
ignore_decorators = ['dedent','deprecated','silent_list', 'warn_deprecated']
|
||||||
|
return eval('callable(mod.{})'.format(name), scope) and name not in ignore_decorators
|
||||||
|
|
||||||
|
return filter(iscallable, attr_list)
|
||||||
|
|
||||||
|
|
||||||
|
def gen_pyplot_functions(dub_root):
|
||||||
|
'''
|
||||||
|
generate 'pyplot_functions.txt' for matplotlibd.pyplot.
|
||||||
|
'''
|
||||||
|
import matplotlib.pyplot
|
||||||
|
from string import ascii_lowercase
|
||||||
|
|
||||||
|
functions = filter(lambda i: i[0] != '_' or i[0] in ascii_lowercase,
|
||||||
|
extract_function_names(matplotlib.pyplot))
|
||||||
|
|
||||||
|
with open(dub_root + "/views/pyplot_functions.txt", "w") as f:
|
||||||
|
f.write("\n".join(functions))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from sys import argv
|
||||||
|
gen_pyplot_functions(argv[1])
|
|
@ -0,0 +1,26 @@
|
||||||
|
module matplotlibd.core.pycall;
|
||||||
|
|
||||||
|
|
||||||
|
void call(string py_script) {
|
||||||
|
import std.process: environment, pipeProcess, wait, Redirect;
|
||||||
|
|
||||||
|
auto py_path = environment.get("MATPLOTLIB_D_PYTHON", "python3");
|
||||||
|
auto pipes = pipeProcess(py_path, Redirect.stdin | Redirect.stderr);
|
||||||
|
|
||||||
|
pipes.stdin.writeln(py_script);
|
||||||
|
pipes.stdin.writeln("exit()");
|
||||||
|
pipes.stdin.close();
|
||||||
|
|
||||||
|
auto result = wait(pipes.pid);
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
string error;
|
||||||
|
foreach (line; pipes.stderr.byLine)
|
||||||
|
error ~= line ~ "\n";
|
||||||
|
throw new Exception("\n\nERROR occurred in Python:\n" ~ error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
call("print(\"Passing!\")\n");
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
module matplotlibd.core.translate;
|
||||||
|
|
||||||
|
alias immutable bool PyBool;
|
||||||
|
alias immutable (void*) PyNone;
|
||||||
|
|
||||||
|
PyBool False = false;
|
||||||
|
PyBool True = true;
|
||||||
|
PyNone None = null;
|
||||||
|
|
||||||
|
|
||||||
|
string d2py(T)(T v) {
|
||||||
|
import std.format: format;
|
||||||
|
static if (is(typeof(v) : PyNone))
|
||||||
|
return "None";
|
||||||
|
|
||||||
|
else static if (is(typeof(v) : bool))
|
||||||
|
return v ? "True" : "False";
|
||||||
|
|
||||||
|
else static if (is(typeof(v) : string))
|
||||||
|
return format("\"%s\"", v);
|
||||||
|
|
||||||
|
else
|
||||||
|
return format("%s", v);
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import std.range: iota;
|
||||||
|
assert(d2py(None) == "None");
|
||||||
|
assert(d2py(null) == "None");
|
||||||
|
assert(d2py(True) == "True");
|
||||||
|
assert(d2py(true) == "True");
|
||||||
|
assert(d2py(False) == "False");
|
||||||
|
assert(d2py(false) == "False");
|
||||||
|
assert(d2py("Hello!") == "\"Hello!\"");
|
||||||
|
assert(d2py(5.iota) == "[0, 1, 2, 3, 4]");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string parseArgs(Args)(Args args) {
|
||||||
|
static if (is(typeof(args.keys) : string[])) {
|
||||||
|
string parsed;
|
||||||
|
foreach(key; args.byKey)
|
||||||
|
parsed ~= key ~ "=" ~ d2py(args[key]) ~ ",";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
string parsed = d2py(args) ~ ",";
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import std.range: iota;
|
||||||
|
assert(parseArgs(5) == "5,");
|
||||||
|
assert(parseArgs(5.iota) == "[0, 1, 2, 3, 4],");
|
||||||
|
assert(parseArgs(["test": 5]) == "test=5,");
|
||||||
|
assert(parseArgs(["test": "test"]) == "test=\"test\",");
|
||||||
|
assert(parseArgs(["test": 5.iota]) == "test=[0, 1, 2, 3, 4],");
|
||||||
|
assert(parseArgs(["test": false]) == "test=False,");
|
||||||
|
assert(parseArgs(["test": False]) == "test=False,");
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
module matplotlibd.pyplot;
|
||||||
|
import matplotlibd.core.pycall;
|
||||||
|
import matplotlibd.core.translate;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string py_script = "import matplotlib.pyplot as plt\n";
|
||||||
|
|
||||||
|
immutable string plt_funcs = (){
|
||||||
|
import std.string: splitLines;
|
||||||
|
|
||||||
|
string[] method_names = import("pyplot_functions.txt").splitLines;
|
||||||
|
string plt_funcs;
|
||||||
|
|
||||||
|
foreach(name; method_names) {
|
||||||
|
plt_funcs ~=
|
||||||
|
"void " ~ name ~ "(T...)(T a)" ~
|
||||||
|
"{import std.format: format;" ~
|
||||||
|
"string p;if(a.length>0){foreach(i;a){p~=parseArgs(i);}" ~
|
||||||
|
"p = p[0..$-1];}py_script~=format(\"plt."~ name ~ "(%s)\n\",p);";
|
||||||
|
|
||||||
|
if (name == "show" || name == "savefig")
|
||||||
|
plt_funcs ~= "call(py_script);}\n";
|
||||||
|
else
|
||||||
|
plt_funcs ~= "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return plt_funcs;
|
||||||
|
}();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
import matplotlibd.core.translate: False, True, None;
|
||||||
|
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
py_script = "import matplotlib.pyplot as plt\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin(plt_funcs);
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
import std.string;
|
||||||
|
auto script = py_script ~ "plt.plot([1, 2],[2, 4],\"r-\",lw=2)\n";
|
||||||
|
plot([1, 2], [2, 4], "r-", ["lw": 2]);
|
||||||
|
assert(script == py_script);
|
||||||
|
clear();
|
||||||
|
assert(py_script == "import matplotlib.pyplot as plt\n");
|
||||||
|
}
|
75
source/app.d
75
source/app.d
|
@ -3,32 +3,38 @@ import util : make, rcarray, StdArray, StdxArray, EMSIArray;
|
||||||
import std.stdio : stderr, writeln;
|
import std.stdio : stderr, writeln;
|
||||||
import std.datetime : Duration;
|
import std.datetime : Duration;
|
||||||
|
|
||||||
void testInsert(Container, int times = 100)()
|
import std.meta : AliasSeq;
|
||||||
|
|
||||||
|
alias tests = AliasSeq!(testInsert, testInsertDelete, testConcat);
|
||||||
|
alias containers = AliasSeq!(int[], StdArray!int, EMSIArray!int, rcarray!int, StdxArray!int);
|
||||||
|
enum times = 100000;
|
||||||
|
|
||||||
|
void testInsert(Container, size_t size = 100)()
|
||||||
{
|
{
|
||||||
auto container = make!Container();
|
auto container = make!Container();
|
||||||
|
|
||||||
//debug stderr.writeln("Testing inserts on ", typeof(container).stringof);
|
//debug stderr.writeln("Testing inserts on ", typeof(container).stringof);
|
||||||
|
|
||||||
foreach (i; 0 .. times)
|
foreach (i; 0 .. size)
|
||||||
{
|
{
|
||||||
container ~= 42;
|
container ~= 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(container.length == times && container[times - 1] == 42);
|
assert(container.length == size && container[size - 1] == 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testInsertDelete(Container, int times = 100)()
|
void testInsertDelete(Container, size_t size = 100)()
|
||||||
{
|
{
|
||||||
auto container = make!Container();
|
auto container = make!Container();
|
||||||
|
|
||||||
//debug stderr.writeln("Testing inserts+deletes on ", typeof(container).stringof);
|
//debug stderr.writeln("Testing inserts+deletes on ", typeof(container).stringof);
|
||||||
|
|
||||||
foreach (i; 0 .. times)
|
foreach (i; 0 .. size)
|
||||||
{
|
{
|
||||||
container ~= 42;
|
container ~= 42;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (i; 0 .. times)
|
foreach (i; 0 .. size)
|
||||||
{
|
{
|
||||||
static if (is(Container : StdxArray!U, U))
|
static if (is(Container : StdxArray!U, U))
|
||||||
{
|
{
|
||||||
|
@ -47,24 +53,33 @@ void testInsertDelete(Container, int times = 100)()
|
||||||
assert(container.length == 0);
|
assert(container.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testConcat(Container, int times = 100)()
|
void testConcat(Container, size_t size = 100)()
|
||||||
{
|
{
|
||||||
|
auto a = make!Container();
|
||||||
|
auto b = make!Container();
|
||||||
|
|
||||||
|
foreach (i; 0 .. size / 2)
|
||||||
|
{
|
||||||
|
a ~= 1;
|
||||||
|
b ~= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto c = a ~ b;
|
||||||
|
|
||||||
|
assert(c.length == size);
|
||||||
}
|
}
|
||||||
|
|
||||||
import std.meta : AliasSeq;
|
auto testContainers(Containers...)()
|
||||||
alias tests = AliasSeq!(testInsert, testInsertDelete, testConcat);
|
|
||||||
|
|
||||||
auto testContainers(Containers...)(int times = 100000)
|
|
||||||
{
|
{
|
||||||
import std.datetime.stopwatch : benchmark;
|
import std.datetime.stopwatch : benchmark;
|
||||||
import std.meta : staticMap;
|
import std.meta : staticMap;
|
||||||
|
import std.array : array;
|
||||||
|
|
||||||
Duration[][string] results;
|
Duration[][string] results;
|
||||||
|
|
||||||
static foreach (test; tests)
|
static foreach (test; tests)
|
||||||
{
|
{
|
||||||
results[test.stringof] = benchmark!(staticMap!(test, Containers))(times);
|
results[test.stringof] = benchmark!(staticMap!(test, Containers))(times).array;
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
@ -84,12 +99,40 @@ void printResults(Containers...)(Duration[][string] results)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void plotResults(Containers...)(Duration[][string] results)
|
||||||
|
{
|
||||||
|
import plt = matplotlibd.pyplot;
|
||||||
|
|
||||||
|
auto i = 0;
|
||||||
|
foreach (test, testResults; results)
|
||||||
|
{
|
||||||
|
import std.range : iota;
|
||||||
|
import std.algorithm : map;
|
||||||
|
import std.array : array;
|
||||||
|
import std.conv : to;
|
||||||
|
|
||||||
|
auto title = test ~ " (" ~ times.to!string ~ " runs)";
|
||||||
|
auto x = iota(testResults.length);
|
||||||
|
auto height = testResults.map!(d => d.total!"msecs").array;
|
||||||
|
|
||||||
|
string[] names;
|
||||||
|
foreach (Container; Containers)
|
||||||
|
{
|
||||||
|
names ~= Container.stringof;
|
||||||
|
}
|
||||||
|
|
||||||
|
plt.subplot(results.length, 1, ++i);
|
||||||
|
plt.bar(x, height);
|
||||||
|
plt.xticks(x, names);
|
||||||
|
plt.ylabel("Time (ms)");
|
||||||
|
plt.title(title);
|
||||||
|
}
|
||||||
|
plt.show();
|
||||||
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
import std.meta : AliasSeq;
|
|
||||||
|
|
||||||
alias containers = AliasSeq!(int[], StdArray!int, StdxArray!int, EMSIArray!int, rcarray!int);
|
|
||||||
|
|
||||||
auto results = testContainers!containers;
|
auto results = testContainers!containers;
|
||||||
results.printResults!containers;
|
results.printResults!containers;
|
||||||
|
results.plotResults!containers;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue