mirror of
https://github.com/tdulcet/Table-and-Graph-Libs.git
synced 2025-05-05 21:41:12 +08:00
Updated to support and use modern C++ features and added more examples.
This commit is contained in:
parent
37e257c5ee
commit
274f949079
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -27,9 +27,9 @@ jobs:
|
|||||||
$CXX --version
|
$CXX --version
|
||||||
- name: Script
|
- name: Script
|
||||||
run: |
|
run: |
|
||||||
$CXX -Wall -g -fsanitize=address,undefined tables.cpp -o tables
|
$CXX -Wall -g -Og -fsanitize=address,undefined tables.cpp -o tables
|
||||||
./tables
|
./tables
|
||||||
$CXX -Wall -g -fsanitize=address,undefined graphs.cpp -o graphs
|
$CXX -Wall -g -Og -fsanitize=address,undefined graphs.cpp -o graphs
|
||||||
./graphs
|
./graphs
|
||||||
- name: Cppcheck
|
- name: Cppcheck
|
||||||
run: cppcheck --enable=all .
|
run: cppcheck --enable=all .
|
||||||
|
@ -13,12 +13,12 @@ install:
|
|||||||
- sudo apt-get -yqq update
|
- sudo apt-get -yqq update
|
||||||
- sudo apt-get -yqq install cppcheck
|
- sudo apt-get -yqq install cppcheck
|
||||||
script:
|
script:
|
||||||
- g++ -Wall -g -fsanitize=address,undefined tables.cpp -o gcc_tables
|
- g++ -Wall -g -Og -fsanitize=address,undefined tables.cpp -o gcc_tables
|
||||||
- ./gcc_tables
|
- ./gcc_tables
|
||||||
- g++ -Wall -g -fsanitize=address,undefined graphs.cpp -o gcc_graphs
|
- g++ -Wall -g -Og -fsanitize=address,undefined graphs.cpp -o gcc_graphs
|
||||||
- ./gcc_graphs
|
- ./gcc_graphs
|
||||||
- clang++ -Wall -g -fsanitize=address,undefined,integer tables.cpp -o clang_tables
|
- clang++ -Wall -g -Og -fsanitize=address,undefined,integer tables.cpp -o clang_tables
|
||||||
- ./clang_tables
|
- ./clang_tables
|
||||||
- clang++ -Wall -g -fsanitize=address,undefined,integer graphs.cpp -o clang_graphs
|
- clang++ -Wall -g -Og -fsanitize=address,undefined,integer graphs.cpp -o clang_graphs
|
||||||
- ./clang_graphs
|
- ./clang_graphs
|
||||||
- cppcheck --enable=all .
|
- cppcheck --enable=all .
|
||||||
|
380
README.md
380
README.md
@ -9,20 +9,29 @@ Copyright © 2018 Teal Dulcet
|
|||||||
|
|
||||||
These header only libraries use [box-drawing](https://en.wikipedia.org/wiki/Box-drawing_character#Unicode), [Braille](https://en.wikipedia.org/wiki/Braille_Patterns), [fraction](https://en.wikipedia.org/wiki/Number_Forms) and other Unicode characters and [terminal colors and formatting](https://misc.flogisoft.com/bash/tip_colors_and_formatting) to output tables and graphs/plots to the console. All the tables and graphs are created with a single (one) function call and they do not require any special data structures.
|
These header only libraries use [box-drawing](https://en.wikipedia.org/wiki/Box-drawing_character#Unicode), [Braille](https://en.wikipedia.org/wiki/Braille_Patterns), [fraction](https://en.wikipedia.org/wiki/Number_Forms) and other Unicode characters and [terminal colors and formatting](https://misc.flogisoft.com/bash/tip_colors_and_formatting) to output tables and graphs/plots to the console. All the tables and graphs are created with a single (one) function call and they do not require any special data structures.
|
||||||
|
|
||||||
|
See the [python](python) directory for Python ports of the libraries.
|
||||||
|
|
||||||
❤️ Please visit [tealdulcet.com](https://www.tealdulcet.com/) to support these libraries and my other software development.
|
❤️ Please visit [tealdulcet.com](https://www.tealdulcet.com/) to support these libraries and my other software development.
|
||||||
|
|
||||||
## Tables
|
## Tables
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
Requires support for C++17. See the [tables.hpp](tables.hpp) file for full usage information.
|
||||||
|
|
||||||
Complete versions of all of the examples below and more can be found in the [tables.cpp](tables.cpp) file.
|
Complete versions of all of the examples below and more can be found in the [tables.cpp](tables.cpp) file.
|
||||||
|
|
||||||
Compile with: `g++ -Wall -g -O3 tables.cpp -o tables`.
|
Compile with:
|
||||||
|
|
||||||
Run with: `./tables`.
|
GCC: `g++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`\
|
||||||
|
Clang: `clang++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`
|
||||||
|
|
||||||
|
Run with: `./tables`
|
||||||
|
|
||||||
#### Output char array as table
|
#### Output char array as table
|
||||||
|
|
||||||
|
##### C style char array
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
@ -36,15 +45,44 @@ int main()
|
|||||||
char ***array;
|
char ***array;
|
||||||
|
|
||||||
// Allocate and set array
|
// Allocate and set array
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
aoptions.headercolumn = true;
|
aoptions.headercolumn = true;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||||
|
|
||||||
// Deallocate array
|
// Deallocate array
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ string array
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t rows = 5;
|
||||||
|
size_t columns = 5;
|
||||||
|
|
||||||
|
vector<vector<string>> array(rows, vector<string>(columns));
|
||||||
|
|
||||||
|
// Set array
|
||||||
|
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
|
||||||
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -55,6 +93,8 @@ Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_
|
|||||||
|
|
||||||
#### Output array as table with separate header row and column
|
#### Output array as table with separate header row and column
|
||||||
|
|
||||||
|
##### C style char array
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
@ -64,14 +104,14 @@ int main()
|
|||||||
{
|
{
|
||||||
size_t rows = 4;
|
size_t rows = 4;
|
||||||
size_t columns = 4;
|
size_t columns = 4;
|
||||||
|
|
||||||
const char* headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
const char* headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||||
const char* headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
const char* headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||||
|
|
||||||
char ***array;
|
char ***array;
|
||||||
|
|
||||||
// Allocate and set array
|
// Allocate and set array
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
aoptions.headercolumn = true;
|
aoptions.headercolumn = true;
|
||||||
@ -79,7 +119,38 @@ int main()
|
|||||||
table(rows, columns, array, headerrow, headercolumn, aoptions);
|
table(rows, columns, array, headerrow, headercolumn, aoptions);
|
||||||
|
|
||||||
// Deallocate array
|
// Deallocate array
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ string array
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t rows = 5;
|
||||||
|
size_t columns = 5;
|
||||||
|
|
||||||
|
string headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||||
|
string headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||||
|
|
||||||
|
vector<vector<string>> array(rows, vector<string>(columns));
|
||||||
|
|
||||||
|
// Set array
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
// or with C++20:
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||||
|
|
||||||
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -88,6 +159,8 @@ Output same as example above.
|
|||||||
|
|
||||||
#### Output array as table
|
#### Output array as table
|
||||||
|
|
||||||
|
##### C style pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
@ -102,10 +175,32 @@ int main()
|
|||||||
|
|
||||||
// Allocate and set array
|
// Allocate and set array
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
|
table(rows, columns, array);
|
||||||
|
|
||||||
// Deallocate array
|
// Deallocate array
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ array/vector
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t rows = 5;
|
||||||
|
size_t columns = 5;
|
||||||
|
|
||||||
|
vector<vector<double>> array(rows, vector<double>(columns)); // array can be any data type
|
||||||
|
|
||||||
|
// Set array
|
||||||
|
|
||||||
|
table(array);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -114,6 +209,8 @@ int main()
|
|||||||
|
|
||||||
#### Output sorted array as table
|
#### Output sorted array as table
|
||||||
|
|
||||||
|
##### C style pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
@ -124,7 +221,7 @@ int dimensions; // Number of columns
|
|||||||
int sortdimension; // Column to sort by
|
int sortdimension; // Column to sort by
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool compare(const T *a, const T *b)
|
bool compare(const T &a, const T &b)
|
||||||
{
|
{
|
||||||
if (a[sortdimension] == b[sortdimension])
|
if (a[sortdimension] == b[sortdimension])
|
||||||
for (int i = 0; i < dimensions; ++i)
|
for (int i = 0; i < dimensions; ++i)
|
||||||
@ -142,16 +239,56 @@ int main()
|
|||||||
int **array; // array can be any data type
|
int **array; // array can be any data type
|
||||||
|
|
||||||
// Allocate and set array
|
// Allocate and set array
|
||||||
|
|
||||||
dimensions = columns;
|
dimensions = columns;
|
||||||
sortdimension = 0;
|
sortdimension = 0;
|
||||||
|
|
||||||
sort(array, array + rows, compare<int>);
|
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
|
sort(array, array + rows, compare<int *>);
|
||||||
|
|
||||||
|
table(rows, columns, array);
|
||||||
|
|
||||||
// Deallocate array
|
// Deallocate array
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ array/vector
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <algorithm>
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int sortdimension; // Column to sort by
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool compare(const T &a, const T &b)
|
||||||
|
{
|
||||||
|
if (a[sortdimension] == b[sortdimension])
|
||||||
|
for (int i = 0; i < size(a); ++i)
|
||||||
|
if (sortdimension != i and a[i] != b[i])
|
||||||
|
return a[i] < b[i];
|
||||||
|
|
||||||
|
return a[sortdimension] < b[sortdimension];
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t rows = 5;
|
||||||
|
size_t columns = 5;
|
||||||
|
|
||||||
|
vector<vector<int>> array(rows, vector<int>(columns)); // array can be any data type
|
||||||
|
|
||||||
|
// Set array
|
||||||
|
|
||||||
|
sortdimension = 0;
|
||||||
|
|
||||||
|
sort(array.begin(), array.end(), compare<vector<int>>);
|
||||||
|
|
||||||
|
table(array);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -160,6 +297,8 @@ int main()
|
|||||||
|
|
||||||
#### Output single function as table
|
#### Output single function as table
|
||||||
|
|
||||||
|
##### C style function pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
@ -175,12 +314,37 @@ int main()
|
|||||||
double xmin = -10;
|
double xmin = -10;
|
||||||
double xmax = 10;
|
double xmax = 10;
|
||||||
double xscl = 2;
|
double xscl = 2;
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
|
|
||||||
table(xmin, xmax, xscl, afunction, aoptions);
|
table(xmin, xmax, xscl, afunction, aoptions);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ lambda function
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
double xmin = -10;
|
||||||
|
double xmax = 10;
|
||||||
|
double xscl = 2;
|
||||||
|
|
||||||
|
function<double(double)> afunction = [](auto x)
|
||||||
|
{ return x + 1; };
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
|
||||||
|
table(xmin, xmax, xscl, afunction, aoptions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -189,6 +353,8 @@ int main()
|
|||||||
|
|
||||||
#### Output multiple functions as table
|
#### Output multiple functions as table
|
||||||
|
|
||||||
|
##### C style function pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
@ -210,17 +376,48 @@ int main()
|
|||||||
double xmin = -10;
|
double xmin = -10;
|
||||||
double xmax = 10;
|
double xmax = 10;
|
||||||
double xscl = 2;
|
double xscl = 2;
|
||||||
|
|
||||||
size_t numfunctions = 2;
|
size_t numfunctions = 2;
|
||||||
|
|
||||||
// Function parameter and return value can be any data type, as long as they are the same
|
// Function parameter and return value can be any data type, as long as they are the same
|
||||||
double (*functions[])(double) = {function1, function2};
|
function<double(double)> functions[] = {function1, function2};
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
|
|
||||||
table(xmin, xmax, xscl, numfunctions, functions, aoptions);
|
table(xmin, xmax, xscl, numfunctions, functions, aoptions);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ lambda function
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <cmath>
|
||||||
|
#include "tables.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
double xmin = -10;
|
||||||
|
double xmax = 10;
|
||||||
|
double xscl = 2;
|
||||||
|
|
||||||
|
size_t numfunctions = 2;
|
||||||
|
|
||||||
|
// Function parameter and return value can be any data type, as long as they are the same
|
||||||
|
function<double(double)> functions[] = {[](auto x)
|
||||||
|
{ return 2 * x; },
|
||||||
|
[](auto x)
|
||||||
|
{ return pow(x, 2); }};
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
|
||||||
|
table(xmin, xmax, xscl, numfunctions, functions, aoptions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -274,7 +471,7 @@ Default value: `false`
|
|||||||
#### Title
|
#### Title
|
||||||
|
|
||||||
Option: `title`\
|
Option: `title`\
|
||||||
Default value: `NULL`
|
Default value: `nullptr`
|
||||||
|
|
||||||
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
||||||
|
|
||||||
@ -315,15 +512,21 @@ Values:
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
Requires support for C++17. See the [graphs.hpp](graphs.hpp) file for full usage information.
|
||||||
|
|
||||||
Complete versions of all of the examples below and more can be found in the [graphs.cpp](graphs.cpp) file.
|
Complete versions of all of the examples below and more can be found in the [graphs.cpp](graphs.cpp) file.
|
||||||
|
|
||||||
Compile with: `g++ -Wall -g -O3 graphs.cpp -o graphs`.
|
Compile with:
|
||||||
|
GCC: `g++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`\
|
||||||
|
Clang: `clang++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`
|
||||||
|
|
||||||
Run with: `./graphs`.
|
Run with: `./graphs`
|
||||||
|
|
||||||
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
||||||
|
|
||||||
#### Output array as plot
|
#### Output single array as plot
|
||||||
|
|
||||||
|
##### C style pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "graphs.hpp"
|
#include "graphs.hpp"
|
||||||
@ -346,10 +549,39 @@ int main()
|
|||||||
|
|
||||||
// Allocate and set array
|
// Allocate and set array
|
||||||
|
|
||||||
graph(height, width, xmin, xmax, ymin, ymax, rows, array, graphdefaultoptions);
|
graph(height, width, xmin, xmax, ymin, ymax, rows, array);
|
||||||
|
|
||||||
// Deallocate array
|
// Deallocate array
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ array/vector
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "graphs.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t height = 160;
|
||||||
|
size_t width = 160;
|
||||||
|
|
||||||
|
long double xmin = -20;
|
||||||
|
long double xmax = 20;
|
||||||
|
long double ymin = -20;
|
||||||
|
long double ymax = 20;
|
||||||
|
|
||||||
|
size_t rows = 10;
|
||||||
|
|
||||||
|
vector<vector<double>> array(rows, vector<double>(2)); // array can be any data type, but must have exactly two columns
|
||||||
|
|
||||||
|
// Set array
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, array);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -358,8 +590,12 @@ If `xmin` and `xmax` are both `0`, they will be set to the respective minimum an
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Use `graph()` to plot multiple arrays, which can be of different sizes.
|
||||||
|
|
||||||
#### Output single function as graph
|
#### Output single function as graph
|
||||||
|
|
||||||
|
##### C style function pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "graphs.hpp"
|
#include "graphs.hpp"
|
||||||
|
|
||||||
@ -380,8 +616,34 @@ int main()
|
|||||||
long double ymin = -20;
|
long double ymin = -20;
|
||||||
long double ymax = 20;
|
long double ymax = 20;
|
||||||
|
|
||||||
graph(height, width, xmin, xmax, ymin, ymax, afunction, graphdefaultoptions);
|
graph(height, width, xmin, xmax, ymin, ymax, afunction);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ lambda function
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "graphs.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t height = 160;
|
||||||
|
size_t width = 160;
|
||||||
|
|
||||||
|
long double xmin = -20;
|
||||||
|
long double xmax = 20;
|
||||||
|
long double ymin = -20;
|
||||||
|
long double ymax = 20;
|
||||||
|
|
||||||
|
function<double(double)> afunction = [](auto x)
|
||||||
|
{ return x + 1; };
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, afunction);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -390,6 +652,8 @@ int main()
|
|||||||
|
|
||||||
#### Output multiple functions as graph
|
#### Output multiple functions as graph
|
||||||
|
|
||||||
|
##### C style function pointer
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
#include "graphs.hpp"
|
#include "graphs.hpp"
|
||||||
|
|
||||||
@ -414,14 +678,45 @@ int main()
|
|||||||
long double xmax = 20;
|
long double xmax = 20;
|
||||||
long double ymin = -20;
|
long double ymin = -20;
|
||||||
long double ymax = 20;
|
long double ymax = 20;
|
||||||
|
|
||||||
size_t numfunctions = 2;
|
|
||||||
|
|
||||||
// Function parameter and return value can be any data type, as long as they are the same
|
|
||||||
double (*functions[])(double) = {function1, function2};
|
|
||||||
|
|
||||||
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions, graphdefaultoptions);
|
size_t numfunctions = 2;
|
||||||
|
|
||||||
|
// Function parameter and return value can be any data type, as long as they are the same
|
||||||
|
function<double(double)> functions[] = {function1, function2};
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### C++ lambda function
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "graphs.hpp"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
size_t height = 160;
|
||||||
|
size_t width = 160;
|
||||||
|
|
||||||
|
long double xmin = -20;
|
||||||
|
long double xmax = 20;
|
||||||
|
long double ymin = -20;
|
||||||
|
long double ymax = 20;
|
||||||
|
|
||||||
|
size_t numfunctions = 2;
|
||||||
|
|
||||||
|
// Function parameter and return value can be any data type, as long as they are the same
|
||||||
|
function<double(double)> functions[] = {[](auto x)
|
||||||
|
{ return 2 * x; },
|
||||||
|
[](auto x)
|
||||||
|
{ return pow(x, 2); }};
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -452,7 +747,7 @@ Requires `border` and `axislabel` to be `true`.
|
|||||||
#### Title
|
#### Title
|
||||||
|
|
||||||
Option: `title`\
|
Option: `title`\
|
||||||
Default value: `NULL`
|
Default value: `nullptr`
|
||||||
|
|
||||||
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
||||||
|
|
||||||
@ -543,5 +838,4 @@ Both:
|
|||||||
* Port to other languages (C, Java, Rust, etc.)
|
* Port to other languages (C, Java, Rust, etc.)
|
||||||
|
|
||||||
C++:
|
C++:
|
||||||
* Handle formatted text in the tables
|
* Support tables with the `wchar_t`, `char16_t` and `char32_t` C data types and the `wstring`, `u16string` and `u32string` C++ data types.
|
||||||
* Support plotting multiple arrays of different sizes
|
|
||||||
|
106
graphs.cpp
106
graphs.cpp
@ -1,40 +1,42 @@
|
|||||||
// Teal Dulcet, CS546
|
// Teal Dulcet, CS546
|
||||||
|
|
||||||
// Compile: g++ -Wall -g -O3 graphs.cpp -o graphs
|
// Compile: g++ -Wall -g -O3 -std=c++17 graphs.cpp -o graphs
|
||||||
|
|
||||||
// Run: ./graphs
|
// Run: ./graphs
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
#include "graphs.hpp"
|
#include "graphs.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
long double afunction(long double x)
|
constexpr long double afunction(long double x)
|
||||||
{
|
{
|
||||||
return x + 1;
|
return x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function1(long double x)
|
constexpr long double function1(long double x)
|
||||||
{
|
{
|
||||||
return 2 * x;
|
return 2 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function2(long double x)
|
constexpr long double function2(long double x)
|
||||||
{
|
{
|
||||||
return pow(x, 2);
|
return pow(x, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function3(long double x)
|
constexpr long double function3(long double x)
|
||||||
{
|
{
|
||||||
return sin(x);
|
return sin(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function4(long double x)
|
constexpr long double function4(long double x)
|
||||||
{
|
{
|
||||||
return cos(x);
|
return cos(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function5(long double x)
|
constexpr long double function5(long double x)
|
||||||
{
|
{
|
||||||
return tan(x);
|
return tan(x);
|
||||||
}
|
}
|
||||||
@ -52,7 +54,7 @@ int main()
|
|||||||
const size_t rows = 10;
|
const size_t rows = 10;
|
||||||
const size_t columns = 2;
|
const size_t columns = 2;
|
||||||
|
|
||||||
// Output array as plot
|
// Output single array as plot
|
||||||
cout << "\nOutput array as plot\n\n";
|
cout << "\nOutput array as plot\n\n";
|
||||||
{
|
{
|
||||||
long double **array;
|
long double **array;
|
||||||
@ -62,18 +64,18 @@ int main()
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
array[i][j] = i + j; //rand();
|
array[i][j] = i + j; // rand();
|
||||||
|
|
||||||
graphoptions aoptions;
|
graphoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
graph(height, width, xmin, xmax, ymin, ymax, rows, array, aoptions);
|
graph(height, width, xmin, xmax, ymin, ymax, rows, array, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array != NULL)
|
if (array != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
delete[] array[i];
|
delete[] array[i];
|
||||||
@ -81,12 +83,57 @@ int main()
|
|||||||
delete[] array;
|
delete[] array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
array<array<long double, columns>, rows> aarray;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
aarray[i][j] = i + j; // rand();
|
||||||
|
|
||||||
|
graphoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vector<vector<long double>> array(rows, vector<long double>(columns));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
array[i][j] = i + j; // rand();
|
||||||
|
|
||||||
|
graphoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Output single function as graph
|
// Output single function as graph
|
||||||
cout << "\nOutput single function as graph\n\n";
|
cout << "\nOutput single function as graph\n\n";
|
||||||
{
|
{
|
||||||
graphoptions aoptions;
|
graphoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, afunction, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
function<long double(long double)> afunction = [](auto x)
|
||||||
|
{ return x + 1; };
|
||||||
|
|
||||||
|
graphoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
@ -96,11 +143,26 @@ int main()
|
|||||||
// Output multiple functions as graph
|
// Output multiple functions as graph
|
||||||
cout << "\nOutput multiple functions as graph\n\n";
|
cout << "\nOutput multiple functions as graph\n\n";
|
||||||
{
|
{
|
||||||
long double (*functions[])(long double) = {function1, function2};
|
function<long double(long double)> functions[] = {function1, function2};
|
||||||
|
|
||||||
graphoptions aoptions;
|
graphoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
graph(height, width, xmin, xmax, ymin, ymax, 2, functions, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
function<long double(long double)> functions[] = {[](auto x)
|
||||||
|
{ return 2 * x; },
|
||||||
|
[](auto x)
|
||||||
|
{ return pow(x, 2); }};
|
||||||
|
|
||||||
|
graphoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
@ -113,28 +175,30 @@ int main()
|
|||||||
const long double ymin = -4;
|
const long double ymin = -4;
|
||||||
const long double ymax = 4;
|
const long double ymax = 4;
|
||||||
|
|
||||||
long double (*functions[])(long double) = {function3, function4, function5};
|
function<long double(long double)> functions[] = {function3, function4, function5};
|
||||||
|
|
||||||
graphoptions aoptions;
|
graphoptions aoptions;
|
||||||
aoptions.axisunitslabel = false;
|
aoptions.axisunitslabel = false;
|
||||||
|
// graphoptions aoptions{.axisunitslabel = false};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
graph(height, width, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
graph(height, width, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*aoptions.style = 2;
|
/* aoptions.style = 2;
|
||||||
|
|
||||||
for (unsigned int k = 10; k < 300; ++k)
|
for (unsigned int k = 10; k < 300; ++k)
|
||||||
{
|
{
|
||||||
cout << "\e[1;1H" << "\e[2J";
|
cout << "\e[1;1H"
|
||||||
|
<< "\e[2J";
|
||||||
|
|
||||||
graph(k, k, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
graph(k, k, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
||||||
|
|
||||||
usleep(200000);
|
usleep(200000);
|
||||||
}*/
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
235
graphs.hpp
235
graphs.hpp
@ -4,25 +4,29 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <limits>
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
#include <numeric>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const char *const styles[][11] = {
|
const char *const styles[][11] = {
|
||||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
|
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
|
||||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
|
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
|
||||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light
|
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light
|
||||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, //Heavy
|
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, // Heavy
|
||||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, //Double
|
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, // Double
|
||||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light Dashed
|
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light Dashed
|
||||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} //Heavy Dashed
|
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} // Heavy Dashed
|
||||||
};
|
};
|
||||||
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
||||||
|
|
||||||
@ -38,31 +42,15 @@ const long double fractionvalues[] = {1.0L / 4.0L, 1.0L / 2.0L, 3.0L / 4.0L, 1.0
|
|||||||
|
|
||||||
struct graphoptions
|
struct graphoptions
|
||||||
{
|
{
|
||||||
bool border;
|
bool border = true;
|
||||||
bool axislabel;
|
bool axislabel = true;
|
||||||
bool axisunitslabel;
|
bool axisunitslabel = true;
|
||||||
char *title;
|
const char *title = nullptr;
|
||||||
unsigned int style;
|
unsigned int style = 2;
|
||||||
unsigned int color;
|
unsigned int color = 2;
|
||||||
graphoptions(void);
|
|
||||||
~graphoptions(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
graphoptions::graphoptions(void)
|
const graphoptions defaultoptions;
|
||||||
{
|
|
||||||
border = true;
|
|
||||||
axislabel = true;
|
|
||||||
axisunitslabel = true;
|
|
||||||
style = 2;
|
|
||||||
color = 2;
|
|
||||||
title = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
graphoptions::~graphoptions(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const graphoptions graphdefaultoptions;
|
|
||||||
|
|
||||||
// Number of columns needed to represent the string
|
// Number of columns needed to represent the string
|
||||||
// Adapted from: https://stackoverflow.com/a/31124065
|
// Adapted from: https://stackoverflow.com/a/31124065
|
||||||
@ -76,8 +64,8 @@ int strcol(const char *const str)
|
|||||||
cout << "Control character: " << (int)str[i] << "\n";
|
cout << "Control character: " << (int)str[i] << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
length = mbstowcs(NULL, str, 0);
|
length = mbstowcs(nullptr, str, 0);
|
||||||
if (length == (size_t)-1)
|
if (length == static_cast<size_t>(-1))
|
||||||
{
|
{
|
||||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -86,9 +74,9 @@ int strcol(const char *const str)
|
|||||||
|
|
||||||
wchar_t *wcstring = new wchar_t[length];
|
wchar_t *wcstring = new wchar_t[length];
|
||||||
|
|
||||||
if (mbstowcs(wcstring, str, length) == (size_t)-1)
|
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||||
{
|
{
|
||||||
if (wcstring != NULL)
|
if (wcstring != nullptr)
|
||||||
delete[] wcstring;
|
delete[] wcstring;
|
||||||
|
|
||||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||||
@ -102,7 +90,7 @@ int strcol(const char *const str)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wcstring != NULL)
|
if (wcstring != nullptr)
|
||||||
delete[] wcstring;
|
delete[] wcstring;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
@ -168,7 +156,7 @@ size_t outputlabel(const long double label, ostringstream &strm)
|
|||||||
long double intpart = 0;
|
long double intpart = 0;
|
||||||
long double fractionpart = abs(modf(label, &intpart));
|
long double fractionpart = abs(modf(label, &intpart));
|
||||||
|
|
||||||
for (unsigned int i = 0; i < (sizeof fractions / sizeof fractions[0]) and !output; ++i)
|
for (unsigned int i = 0; i < size(fractions) and !output; ++i)
|
||||||
{
|
{
|
||||||
if (abs(fractionpart - fractionvalues[i]) < DBL_EPSILON)
|
if (abs(fractionpart - fractionvalues[i]) < DBL_EPSILON)
|
||||||
{
|
{
|
||||||
@ -224,9 +212,9 @@ size_t outputlabel(const long double label, ostringstream &strm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Output graph
|
// Output graph
|
||||||
int graph(const size_t height, const size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, unsigned short **array, const graphoptions &aoptions)
|
int graph(const size_t height, const size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const vector<vector<unsigned short>> &array, const graphoptions &aoptions)
|
||||||
{
|
{
|
||||||
if (array == NULL)
|
if (!size(array))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const bool border = aoptions.border;
|
const bool border = aoptions.border;
|
||||||
@ -235,7 +223,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
const char *const title = aoptions.title;
|
const char *const title = aoptions.title;
|
||||||
const unsigned int style = aoptions.style;
|
const unsigned int style = aoptions.style;
|
||||||
|
|
||||||
if (style >= (sizeof styles / sizeof styles[0]))
|
if (style >= size(styles))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
@ -282,7 +270,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
|
|
||||||
setlocale(LC_CTYPE, "");
|
setlocale(LC_CTYPE, "");
|
||||||
|
|
||||||
if (title != NULL and title[0] != '\0')
|
if (title != nullptr and title[0] != '\0')
|
||||||
cout << wrap(title, w.ws_col) << "\n";
|
cout << wrap(title, w.ws_col) << "\n";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < height; i += 4)
|
for (unsigned int i = 0; i < height; i += 4)
|
||||||
@ -296,12 +284,12 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
if (border and axislabel and axisunitslabel)
|
if (border and axislabel and axisunitslabel)
|
||||||
{
|
{
|
||||||
bool output = false;
|
bool output = false;
|
||||||
long double label;
|
long double label = 0;
|
||||||
int adivisor = divisor;
|
int adivisor = divisor;
|
||||||
if (i < yaxis)
|
if (i < yaxis)
|
||||||
adivisor = -adivisor;
|
adivisor = -adivisor;
|
||||||
|
|
||||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or !axislabel) and !output; k += adivisor)
|
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and !output; k += adivisor)
|
||||||
{
|
{
|
||||||
if (i <= k and (i + 4) > k)
|
if (i <= k and (i + 4) > k)
|
||||||
{
|
{
|
||||||
@ -340,7 +328,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
if (i < yaxis)
|
if (i < yaxis)
|
||||||
adivisor = -adivisor;
|
adivisor = -adivisor;
|
||||||
|
|
||||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or !axislabel) and !output; k += adivisor)
|
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and !output; k += adivisor)
|
||||||
{
|
{
|
||||||
if (i <= k and (i + 4) > k)
|
if (i <= k and (i + 4) > k)
|
||||||
{
|
{
|
||||||
@ -368,7 +356,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
if (j < xaxis)
|
if (j < xaxis)
|
||||||
adivisor = -adivisor;
|
adivisor = -adivisor;
|
||||||
|
|
||||||
for (long double k = xaxis + adivisor; ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and (j < (width - 4) or !axislabel) and !output; k += adivisor)
|
for (long double k = xaxis + adivisor; ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and j < (width - 4) and !output; k += adivisor)
|
||||||
{
|
{
|
||||||
if (j <= k and (j + 2) > k)
|
if (j <= k and (j + 2) > k)
|
||||||
{
|
{
|
||||||
@ -400,7 +388,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
}
|
}
|
||||||
else if (yaxislabel and axislabel and axisunitslabel)
|
else if (yaxislabel and axislabel and axisunitslabel)
|
||||||
{
|
{
|
||||||
long double label;
|
long double label = 0;
|
||||||
int adivisor = divisor;
|
int adivisor = divisor;
|
||||||
if (j < xaxis)
|
if (j < xaxis)
|
||||||
{
|
{
|
||||||
@ -497,19 +485,24 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert array to graph and output
|
// Convert one or more arrays to graph and output
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T **array, const graphoptions &aoptions)
|
int graphs(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &arrays, const graphoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
if (rows == 0)
|
if (!size(arrays))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (array == NULL)
|
if (!all_of(begin(arrays), end(arrays), [](const auto &array)
|
||||||
|
{ return all_of(begin(array), end(array), [](const auto &x)
|
||||||
|
{ return size(x) == 2; }); }))
|
||||||
|
{
|
||||||
|
cerr << "Error: The arrays must have two columns.";
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
const unsigned int color = aoptions.color;
|
const unsigned int color = aoptions.color;
|
||||||
|
|
||||||
if (color >= (sizeof colors / sizeof colors[0]))
|
if (color >= size(colors))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
struct winsize w;
|
struct winsize w;
|
||||||
@ -538,32 +531,22 @@ int graph(size_t height, size_t width, long double xmin, long double xmax, long
|
|||||||
|
|
||||||
if (xmin == 0 and xmax == 0)
|
if (xmin == 0 and xmax == 0)
|
||||||
{
|
{
|
||||||
xmin = numeric_limits<T>::max();
|
const auto compare = [](const auto &a, const auto &b)
|
||||||
xmax = numeric_limits<T>::min();
|
{ return a[0] < b[0]; };
|
||||||
|
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
{ const auto minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||||
{
|
xmin = result.first[0];
|
||||||
if (array[i][0] < xmin)
|
xmax = result.second[0];
|
||||||
xmin = array[i][0];
|
|
||||||
|
|
||||||
if (array[i][0] > xmax)
|
|
||||||
xmax = array[i][0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ymin == 0 and ymax == 0)
|
if (ymin == 0 and ymax == 0)
|
||||||
{
|
{
|
||||||
ymin = numeric_limits<T>::max();
|
const auto compare = [](const auto &a, const auto &b)
|
||||||
ymax = numeric_limits<T>::min();
|
{ return a[1] < b[1]; };
|
||||||
|
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
{ const auto minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||||
{
|
ymin = result.first[1];
|
||||||
if (array[i][1] < ymin)
|
ymax = result.second[1];
|
||||||
ymin = array[i][1];
|
|
||||||
|
|
||||||
if (array[i][1] > ymax)
|
|
||||||
ymax = array[i][1];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmin >= xmax)
|
if (xmin >= xmax)
|
||||||
@ -583,46 +566,65 @@ int graph(size_t height, size_t width, long double xmin, long double xmax, long
|
|||||||
const long double xaxis = width - (xmax * xscl);
|
const long double xaxis = width - (xmax * xscl);
|
||||||
const long double yaxis = ymax * yscl;
|
const long double yaxis = ymax * yscl;
|
||||||
|
|
||||||
unsigned short **aarray;
|
vector<vector<unsigned short>> aarray(width, vector<unsigned short>(height, 0));
|
||||||
aarray = new unsigned short *[width];
|
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
|
||||||
aarray[i] = new unsigned short[height];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
for (unsigned int j = 0; j < size(arrays); ++j)
|
||||||
for (unsigned int j = 0; j < height; ++j)
|
|
||||||
aarray[i][j] = 0;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
|
||||||
{
|
{
|
||||||
if (array[i][0] >= xmin and array[i][0] < xmax and array[i][1] >= ymin and array[i][1] < ymax)
|
auto array = arrays[j];
|
||||||
{
|
const unsigned int color = (j % (size(colors) - 2)) + 3;
|
||||||
const long long x = (array[i][0] * xscl) + xaxis;
|
|
||||||
const long long y = (yaxis - (array[i][1] * yscl)) - 1;
|
|
||||||
|
|
||||||
aarray[x][y] = color + 1;
|
for (unsigned int i = 0; i < size(array); ++i)
|
||||||
|
{
|
||||||
|
if (array[i][0] >= xmin and array[i][0] < xmax and array[i][1] >= ymin and array[i][1] < ymax)
|
||||||
|
{
|
||||||
|
const long long x = (array[i][0] * xscl) + xaxis;
|
||||||
|
const long long y = (yaxis - (array[i][1] * yscl)) - 1;
|
||||||
|
|
||||||
|
if (aarray[x][y])
|
||||||
|
{
|
||||||
|
if (aarray[x][y] != color)
|
||||||
|
aarray[x][y] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
aarray[x][y] = color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
return graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
||||||
|
}
|
||||||
|
|
||||||
if (aarray != NULL)
|
// Convert single array to graph and output
|
||||||
{
|
template <typename T>
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &aarray, const graphoptions &aoptions = defaultoptions)
|
||||||
delete[] aarray[i];
|
{
|
||||||
|
const std::array<T, 1> aaarray = {aarray};
|
||||||
|
|
||||||
delete[] aarray;
|
return graphs(height, width, xmin, xmax, ymin, ymax, aaarray, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
// Convert single array to graph and output
|
||||||
|
template <typename T>
|
||||||
|
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T **aarray, const graphoptions &aoptions = defaultoptions)
|
||||||
|
{
|
||||||
|
if (rows == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
const size_t columns = 2;
|
||||||
|
vector<std::array<T, columns>> aaarray(rows);
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
copy(aarray[i], aarray[i] + columns, aaarray[i].begin());
|
||||||
|
|
||||||
|
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert one or more functions to graph and output
|
// Convert one or more functions to graph and output
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const size_t numfunctions, T (*functions[])(T), const graphoptions &aoptions)
|
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const size_t numfunctions, function<T(T)> functions[], const graphoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
const unsigned int color = aoptions.color;
|
const unsigned int color = aoptions.color;
|
||||||
|
|
||||||
if (color >= (sizeof colors / sizeof colors[0]))
|
if (color >= size(colors))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (numfunctions == 0)
|
if (numfunctions == 0)
|
||||||
@ -671,18 +673,11 @@ int graph(size_t height, size_t width, const long double xmin, const long double
|
|||||||
const long double xaxis = width - (xmax * xscl);
|
const long double xaxis = width - (xmax * xscl);
|
||||||
const long double yaxis = ymax * yscl;
|
const long double yaxis = ymax * yscl;
|
||||||
|
|
||||||
unsigned short **array;
|
vector<vector<unsigned short>> array(width, vector<unsigned short>(height, 0));
|
||||||
array = new unsigned short *[width];
|
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
|
||||||
array[i] = new unsigned short[height];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
|
||||||
for (unsigned int j = 0; j < height; ++j)
|
|
||||||
array[i][j] = 0;
|
|
||||||
|
|
||||||
for (unsigned int j = 0; j < numfunctions; ++j)
|
for (unsigned int j = 0; j < numfunctions; ++j)
|
||||||
{
|
{
|
||||||
unsigned short acolor = numfunctions == 1 ? color + 1 : (j % ((sizeof colors / sizeof colors[0]) - 2)) + 3;
|
unsigned short acolor = numfunctions == 1 ? color + 1 : (j % (size(colors) - 2)) + 3;
|
||||||
|
|
||||||
for (long double i = 0; i < rows; i += 0.5)
|
for (long double i = 0; i < rows; i += 0.5)
|
||||||
{
|
{
|
||||||
@ -705,25 +700,23 @@ int graph(size_t height, size_t width, const long double xmin, const long double
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
return graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
||||||
|
|
||||||
if (array != NULL)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < width; ++i)
|
|
||||||
delete[] array[i];
|
|
||||||
|
|
||||||
delete[] array;
|
|
||||||
}
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert single function to function array and output
|
// Convert single function to function array and output
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, T afunction(T), const graphoptions &aoptions)
|
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const function<T(T)> &afunction, const graphoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
T(*functions[])
|
std::function<T(T)> afunctions[] = {afunction};
|
||||||
(T) = {afunction};
|
|
||||||
|
|
||||||
return graph(height, width, xmin, xmax, ymin, ymax, 1, functions, aoptions);
|
return graph(height, width, xmin, xmax, ymin, ymax, 1, afunctions, aoptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert single function to function array and output
|
||||||
|
template <typename T>
|
||||||
|
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, T afunction(T), const graphoptions &aoptions = defaultoptions)
|
||||||
|
{
|
||||||
|
std::function<T(T)> afunctions[] = {afunction};
|
||||||
|
|
||||||
|
return graph(height, width, xmin, xmax, ymin, ymax, 1, afunctions, aoptions);
|
||||||
}
|
}
|
||||||
|
@ -2,20 +2,20 @@
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`.
|
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [tables.py](tables.py) file for full usage information.
|
||||||
|
|
||||||
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
||||||
|
|
||||||
Run with: `python3 test.py`.
|
Run with: `python3 test.py`.
|
||||||
|
|
||||||
#### Output char array as table
|
#### Output str array as table
|
||||||
|
|
||||||
```py
|
```py
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
# Set array
|
# Set array
|
||||||
|
|
||||||
tables.array(array, None, None, headerrow=True, headercolumn=True)
|
tables.array(array, headerrow=True, headercolumn=True)
|
||||||
```
|
```
|
||||||
|
|
||||||
Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters), but not newlines and tabs.
|
Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters), but not newlines and tabs.
|
||||||
@ -42,9 +42,9 @@ Output same as example above.
|
|||||||
```py
|
```py
|
||||||
import tables
|
import tables
|
||||||
|
|
||||||
# Set array
|
# Set array, can be any sequence data type
|
||||||
|
|
||||||
tables.array(array, None, None)
|
tables.array(array)
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
@ -60,7 +60,7 @@ sortdimension = 0 # Column to sort by
|
|||||||
|
|
||||||
array = sorted(array, key=lambda x: x[sortdimension])
|
array = sorted(array, key=lambda x: x[sortdimension])
|
||||||
|
|
||||||
tables.array(array, None, None)
|
tables.array(array)
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
@ -82,6 +82,22 @@ tables.function(xmin, xmax, xscl, afunction, headerrow=True)
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Output lambda function as table
|
||||||
|
|
||||||
|
```py
|
||||||
|
import tables
|
||||||
|
|
||||||
|
xmin = -10
|
||||||
|
xmax = 10
|
||||||
|
xscl = 2
|
||||||
|
|
||||||
|
afunction = lambda x: x + 1
|
||||||
|
|
||||||
|
tables.function(xmin, xmax, xscl, afunction, headerrow=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output same as example above.
|
||||||
|
|
||||||
#### Output multiple functions as table
|
#### Output multiple functions as table
|
||||||
|
|
||||||
```py
|
```py
|
||||||
@ -105,6 +121,23 @@ tables.functions(xmin, xmax, xscl, functions, headerrow=True)
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Output multiple lambda functions as table
|
||||||
|
|
||||||
|
```py
|
||||||
|
import tables
|
||||||
|
|
||||||
|
xmin = -10
|
||||||
|
xmax = 10
|
||||||
|
xscl = 2
|
||||||
|
|
||||||
|
# Function parameter and return value can be any data type, as long as they are the same
|
||||||
|
functions = [lambda x: 2 * x, lambda x: x ** 2]
|
||||||
|
|
||||||
|
tables.functions(xmin, xmax, xscl, functions, headerrow=True)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output same as example above.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
#### Header row
|
#### Header row
|
||||||
@ -182,7 +215,7 @@ Values:
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`.
|
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [graphs.py](graphs.py) file for full usage information.
|
||||||
|
|
||||||
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
||||||
|
|
||||||
@ -190,7 +223,7 @@ Run with: `python3 test.py`.
|
|||||||
|
|
||||||
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
||||||
|
|
||||||
#### Output array as plot
|
#### Output single array as plot
|
||||||
|
|
||||||
```py
|
```py
|
||||||
import graphs
|
import graphs
|
||||||
@ -203,7 +236,7 @@ xmax = 20
|
|||||||
ymin = -20
|
ymin = -20
|
||||||
ymax = 20
|
ymax = 20
|
||||||
|
|
||||||
# Set array
|
# Set array, can be any sequence data type, but must have exactly two columns
|
||||||
|
|
||||||
graphs.array(height, width, xmin, xmax, ymin, ymax, array)
|
graphs.array(height, width, xmin, xmax, ymin, ymax, array)
|
||||||
```
|
```
|
||||||
@ -212,6 +245,8 @@ If `xmin` and `xmax` are both `0`, they will be set to the respective minimum an
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
Use `graphs.arrays()` to plot multiple arrays, which can be of different sizes.
|
||||||
|
|
||||||
#### Output single function as graph
|
#### Output single function as graph
|
||||||
|
|
||||||
```py
|
```py
|
||||||
@ -233,6 +268,26 @@ graphs.function(height, width, xmin, xmax, ymin, ymax, afunction)
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Output lambda function as graph
|
||||||
|
|
||||||
|
```py
|
||||||
|
import graphs
|
||||||
|
|
||||||
|
height = 160
|
||||||
|
width = 160
|
||||||
|
|
||||||
|
xmin = -20
|
||||||
|
xmax = 20
|
||||||
|
ymin = -20
|
||||||
|
ymax = 20
|
||||||
|
|
||||||
|
afunction = lambda x: x + 1
|
||||||
|
|
||||||
|
graphs.function(height, width, xmin, xmax, ymin, ymax, afunction)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output same as example above.
|
||||||
|
|
||||||
#### Output multiple functions as graph
|
#### Output multiple functions as graph
|
||||||
|
|
||||||
```py
|
```py
|
||||||
@ -260,6 +315,27 @@ graphs.functions(height, width, xmin, xmax, ymin, ymax, functions)
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Output multiple lambda functions as graph
|
||||||
|
|
||||||
|
```py
|
||||||
|
import graphs
|
||||||
|
|
||||||
|
height = 160
|
||||||
|
width = 160
|
||||||
|
|
||||||
|
xmin = -20
|
||||||
|
xmax = 20
|
||||||
|
ymin = -20
|
||||||
|
ymax = 20
|
||||||
|
|
||||||
|
# Function parameter and return value can be any data type, as long as they are the same
|
||||||
|
functions = [lambda x: 2 * x, lambda x: x ** 2]
|
||||||
|
|
||||||
|
graphs.functions(height, width, xmin, xmax, ymin, ymax, functions)
|
||||||
|
```
|
||||||
|
|
||||||
|
Output same as example above.
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
|
|
||||||
#### Border/Axis
|
#### Border/Axis
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Teal Dulcet, CS546
|
# Teal Dulcet, CS546
|
||||||
@ -113,7 +113,7 @@ def outputlabel(label: float) -> Tuple[int, str]:
|
|||||||
return length, strm
|
return length, strm
|
||||||
|
|
||||||
|
|
||||||
def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, title: Optional[str]=None) -> int:
|
def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, title: Optional[str] = None) -> int:
|
||||||
"""Output graph"""
|
"""Output graph"""
|
||||||
if not array:
|
if not array:
|
||||||
return 1
|
return 1
|
||||||
@ -175,7 +175,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
adivisor = -divisor if i < yaxis else divisor
|
adivisor = -divisor if i < yaxis else divisor
|
||||||
|
|
||||||
k = yaxis + adivisor
|
k = yaxis + adivisor
|
||||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or not axislabel) and not output:
|
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and not output:
|
||||||
if (i <= k and (i + 4) > k):
|
if (i <= k and (i + 4) > k):
|
||||||
label = ymax - (k / yscl)
|
label = ymax - (k / yscl)
|
||||||
|
|
||||||
@ -202,7 +202,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
adivisor = -divisor if i < yaxis else divisor
|
adivisor = -divisor if i < yaxis else divisor
|
||||||
|
|
||||||
k = yaxis + adivisor
|
k = yaxis + adivisor
|
||||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or not axislabel) and not output:
|
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and not output:
|
||||||
if i <= k and (i + 4) > k:
|
if i <= k and (i + 4) > k:
|
||||||
strm += styles[style][7]
|
strm += styles[style][7]
|
||||||
output = True
|
output = True
|
||||||
@ -220,7 +220,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
adivisor = -divisor if j < xaxis else divisor
|
adivisor = -divisor if j < xaxis else divisor
|
||||||
|
|
||||||
k = xaxis + adivisor
|
k = xaxis + adivisor
|
||||||
while ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and (j < (width - 4) or not axislabel) and not output:
|
while ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and j < (width - 4) and not output:
|
||||||
if j <= k and (j + 2) > k:
|
if j <= k and (j + 2) > k:
|
||||||
strm += styles[style][3]
|
strm += styles[style][3]
|
||||||
output = True
|
output = True
|
||||||
@ -314,7 +314,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||||
"""Convert one or more arrays to graph and output"""
|
"""Convert one or more arrays to graph and output"""
|
||||||
if not aarrays:
|
if not aarrays:
|
||||||
return 1
|
return 1
|
||||||
@ -328,6 +328,12 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
|
|
||||||
w = shutil.get_terminal_size()
|
w = shutil.get_terminal_size()
|
||||||
|
|
||||||
|
if height == 0:
|
||||||
|
height = w.lines * 4
|
||||||
|
|
||||||
|
if width == 0:
|
||||||
|
width = w.columns * 2
|
||||||
|
|
||||||
aheight = height // 4
|
aheight = height // 4
|
||||||
awidth = width // 2
|
awidth = width // 2
|
||||||
|
|
||||||
@ -365,7 +371,8 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
aaarray = [[0 for j in range(height)] for i in range(width)]
|
aaarray = [[0 for j in range(height)] for i in range(width)]
|
||||||
|
|
||||||
for j, aarray in enumerate(aarrays):
|
for j, aarray in enumerate(aarrays):
|
||||||
acolor = color + 1 if len(aarrays) == 1 else (j % (len(colors) - 2)) + 3
|
acolor = color + 1 if len(aarrays) == 1 else (j %
|
||||||
|
(len(colors) - 2)) + 3
|
||||||
|
|
||||||
for i in aarray:
|
for i in aarray:
|
||||||
if i[0] >= xmin and i[0] < xmax and i[1] >= ymin and i[1] < ymax:
|
if i[0] >= xmin and i[0] < xmax and i[1] >= ymin and i[1] < ymax:
|
||||||
@ -381,17 +388,17 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
|||||||
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
||||||
|
|
||||||
|
|
||||||
def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||||
"""Convert single array to graph and output"""
|
"""Convert single array to graph and output"""
|
||||||
return arrays(height, width, xmin, xmax, ymin, ymax, [aarray], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
return arrays(height, width, xmin, xmax, ymin, ymax, [aarray], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
||||||
|
|
||||||
|
|
||||||
def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||||
"""Convert one or more functions to graph and output"""
|
"""Convert one or more functions to graph and output"""
|
||||||
if color < 0 or color >= len(colors):
|
if color < 0 or color >= len(colors):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if len(afunctions) == 0:
|
if not afunctions:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
w = shutil.get_terminal_size()
|
w = shutil.get_terminal_size()
|
||||||
@ -402,8 +409,8 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
|||||||
if width == 0:
|
if width == 0:
|
||||||
width = w.columns * 2
|
width = w.columns * 2
|
||||||
|
|
||||||
aheight = height / 4
|
aheight = height // 4
|
||||||
awidth = width / 2
|
awidth = width // 2
|
||||||
|
|
||||||
if aheight > w.lines:
|
if aheight > w.lines:
|
||||||
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format(
|
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format(
|
||||||
@ -453,6 +460,6 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
|||||||
return graph(height, width, xmin, xmax, ymin, ymax, array, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
return graph(height, width, xmin, xmax, ymin, ymax, array, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
||||||
|
|
||||||
|
|
||||||
def function(height, width, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
def function(height, width, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||||
"""Convert single function to function array and output"""
|
"""Convert single function to function array and output"""
|
||||||
return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Teal Dulcet, CS546
|
# Teal Dulcet, CS546
|
||||||
@ -39,7 +39,7 @@ def strcol(str: str) -> int:
|
|||||||
# return len(str)
|
# return len(str)
|
||||||
|
|
||||||
|
|
||||||
def table(array: List[List[str]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||||
"""Output char array as table"""
|
"""Output char array as table"""
|
||||||
if not array:
|
if not array:
|
||||||
return 1
|
return 1
|
||||||
@ -158,7 +158,7 @@ def table(array: List[List[str]], headerrow: bool=False, headercolumn: bool=Fals
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]], aheadercolumn: Optional[Sequence[Any]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]] = None, aheadercolumn: Optional[Sequence[Any]] = None, headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||||
"""Convert array to char array and output as table"""
|
"""Convert array to char array and output as table"""
|
||||||
if not aarray:
|
if not aarray:
|
||||||
return 1
|
return 1
|
||||||
@ -220,9 +220,9 @@ def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]],
|
|||||||
return table(aaarray, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
return table(aaarray, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||||
|
|
||||||
|
|
||||||
def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||||
"""Convert one or more functions to array and output as table"""
|
"""Convert one or more functions to array and output as table"""
|
||||||
if len(afunctions) == 0:
|
if not afunctions:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if xmin >= xmax:
|
if xmin >= xmax:
|
||||||
@ -258,6 +258,6 @@ def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callab
|
|||||||
return array(aarray, aheaderrow, None, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
return array(aarray, aheaderrow, None, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||||
|
|
||||||
|
|
||||||
def function(xmin: float, xmax: float, xscl: float, afunction: Callable[[float], float], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
def function(xmin: float, xmax: float, xscl: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||||
"""Convert single function to array and output as table"""
|
"""Convert single function to array and output as table"""
|
||||||
return functions(xmin, xmax, xscl, [afunction], headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
return functions(xmin, xmax, xscl, [afunction], headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Teal Dulcet, CS546
|
# Teal Dulcet, CS546
|
||||||
@ -78,11 +78,16 @@ for k in range(len(tables.styles)):
|
|||||||
print("\nOutput single function as table\n")
|
print("\nOutput single function as table\n")
|
||||||
for k in range(len(tables.styles)):
|
for k in range(len(tables.styles)):
|
||||||
tables.function(xmin, xmax, xscl, afunction, headerrow=True, style=k)
|
tables.function(xmin, xmax, xscl, afunction, headerrow=True, style=k)
|
||||||
|
for k in range(len(tables.styles)):
|
||||||
|
tables.function(xmin, xmax, xscl, lambda x: x + 1, headerrow=True, style=k)
|
||||||
|
|
||||||
print("\nOutput multiple functions as table\n")
|
print("\nOutput multiple functions as table\n")
|
||||||
for k in range(len(tables.styles)):
|
for k in range(len(tables.styles)):
|
||||||
tables.functions(xmin, xmax, xscl, [
|
tables.functions(xmin, xmax, xscl, [
|
||||||
function1, function2], headerrow=True, style=k)
|
function1, function2], headerrow=True, style=k)
|
||||||
|
for k in range(len(tables.styles)):
|
||||||
|
tables.functions(xmin, xmax, xscl, [
|
||||||
|
lambda x: 2 * x, lambda x: x ** 2], headerrow=True, style=k)
|
||||||
|
|
||||||
height = 160
|
height = 160
|
||||||
width = 160
|
width = 160
|
||||||
@ -92,20 +97,26 @@ xmax = 20
|
|||||||
ymin = -20
|
ymin = -20
|
||||||
ymax = 20
|
ymax = 20
|
||||||
|
|
||||||
print("\nOutput array as plot\n")
|
print("\nOutput single array as plot\n")
|
||||||
array = [[i + j for j in range(2)] for i in range(10)]
|
array = [range(i, i + 2) for i in range(10)]
|
||||||
for k in range(len(graphs.styles)):
|
for k in range(len(graphs.styles)):
|
||||||
graphs.array(height, width, xmin, xmax, ymin, ymax, array, style=k)
|
graphs.array(height, width, xmin, xmax, ymin, ymax, array, style=k)
|
||||||
|
|
||||||
print("\nOutput single function as graph\n")
|
print("\nOutput single function as graph\n")
|
||||||
for k in range(len(graphs.styles)):
|
for k in range(len(graphs.styles)):
|
||||||
graphs.function(height, width, xmin, xmax, ymin, ymax, afunction, style=k)
|
graphs.function(height, width, xmin, xmax, ymin, ymax, afunction, style=k)
|
||||||
|
for k in range(len(graphs.styles)):
|
||||||
|
graphs.function(height, width, xmin, xmax, ymin,
|
||||||
|
ymax, lambda x: x + 1, style=k)
|
||||||
|
|
||||||
print("\nOutput multiple functions as graph\n")
|
print("\nOutput multiple functions as graph\n")
|
||||||
for k in range(len(graphs.styles)):
|
for k in range(len(graphs.styles)):
|
||||||
graphs.functions(height, width, xmin, xmax, ymin,
|
graphs.functions(height, width, xmin, xmax, ymin,
|
||||||
ymax, [function1, function2], style=k)
|
ymax, [function1, function2], style=k)
|
||||||
|
for k in range(len(graphs.styles)):
|
||||||
|
graphs.functions(height, width, xmin, xmax, ymin, ymax, [
|
||||||
|
lambda x: 2 * x, lambda x: x ** 2], style=k)
|
||||||
|
|
||||||
for k in range(len(graphs.styles)):
|
for k in range(len(graphs.styles)):
|
||||||
graphs.functions(height, width, -(2 * math.pi), 2 *
|
graphs.functions(height, width, -(2 * math.pi), 2 * math.pi, -4,
|
||||||
math.pi, -4, 4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)
|
4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)
|
||||||
|
352
tables.cpp
352
tables.cpp
@ -1,27 +1,29 @@
|
|||||||
// Teal Dulcet, CS546
|
// Teal Dulcet, CS546
|
||||||
|
|
||||||
// Compile: g++ -Wall -g -O3 tables.cpp -o tables
|
// Compile: g++ -Wall -g -O3 -std=c++17 tables.cpp -o tables
|
||||||
|
|
||||||
// Run: ./tables
|
// Run: ./tables
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
#include "tables.hpp"
|
#include "tables.hpp"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
long double afunction(long double x)
|
constexpr long double afunction(long double x)
|
||||||
{
|
{
|
||||||
return x + 1;
|
return x + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function1(long double x)
|
constexpr long double function1(long double x)
|
||||||
{
|
{
|
||||||
return 2 * x;
|
return 2 * x;
|
||||||
}
|
}
|
||||||
|
|
||||||
long double function2(long double x)
|
constexpr long double function2(long double x)
|
||||||
{
|
{
|
||||||
return pow(x, 2);
|
return pow(x, 2);
|
||||||
}
|
}
|
||||||
@ -32,8 +34,8 @@ int sortdimension = 0;
|
|||||||
/* template <typename T>
|
/* template <typename T>
|
||||||
int compare(const void *pa, const void *pb)
|
int compare(const void *pa, const void *pb)
|
||||||
{
|
{
|
||||||
const T *a = *(const T **)pa;
|
const T a = *(const T *)pa;
|
||||||
const T *b = *(const T **)pb;
|
const T b = *(const T *)pb;
|
||||||
|
|
||||||
if (a[sortdimension] == b[sortdimension])
|
if (a[sortdimension] == b[sortdimension])
|
||||||
{
|
{
|
||||||
@ -58,7 +60,7 @@ int compare(const void *pa, const void *pb)
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool compare(const T *a, const T *b)
|
bool compare(const T &a, const T &b)
|
||||||
{
|
{
|
||||||
if (a[sortdimension] == b[sortdimension])
|
if (a[sortdimension] == b[sortdimension])
|
||||||
for (int i = 0; i < dimensions; ++i)
|
for (int i = 0; i < dimensions; ++i)
|
||||||
@ -77,6 +79,9 @@ int main()
|
|||||||
const long double xmax = 10;
|
const long double xmax = 10;
|
||||||
const long double xscl = 2; // 80 / (xmax - xmin);
|
const long double xscl = 2; // 80 / (xmax - xmin);
|
||||||
|
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
// Output array as table
|
// Output array as table
|
||||||
cout << "\nOutput array as table\n\n";
|
cout << "\nOutput array as table\n\n";
|
||||||
{
|
{
|
||||||
@ -91,14 +96,14 @@ int main()
|
|||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array != NULL)
|
if (array != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
delete[] array[i];
|
delete[] array[i];
|
||||||
@ -106,6 +111,38 @@ int main()
|
|||||||
delete[] array;
|
delete[] array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
array<array<long long, columns>, rows> aarray;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
aarray[i][j] = rand();
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vector<vector<long long>> array(rows, vector<long long>(columns));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
array[i][j] = rand();
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
{
|
{
|
||||||
long double **array;
|
long double **array;
|
||||||
array = new long double *[rows];
|
array = new long double *[rows];
|
||||||
@ -118,14 +155,14 @@ int main()
|
|||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array != NULL)
|
if (array != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
delete[] array[i];
|
delete[] array[i];
|
||||||
@ -133,6 +170,38 @@ int main()
|
|||||||
delete[] array;
|
delete[] array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
array<array<long double, columns>, rows> aarray;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
aarray[i][j] = static_cast<long double>(rand()) / static_cast<long double>(RAND_MAX);
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vector<vector<long double>> array(rows, vector<long double>(columns));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
array[i][j] = static_cast<long double>(rand()) / static_cast<long double>(RAND_MAX);
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Output char array as table
|
// Output char array as table
|
||||||
cout << "\nOutput char array as table\n\n";
|
cout << "\nOutput char array as table\n\n";
|
||||||
{
|
{
|
||||||
@ -146,12 +215,32 @@ int main()
|
|||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
aoptions.headercolumn = true;
|
aoptions.headercolumn = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const array<array<string, columns>, rows> aarray = {{{"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"},
|
||||||
|
{"Header column 2", "Data 1", "Data 2", "Data 3", "Data 4"},
|
||||||
|
{"Header column 3", "Data 5", "Data 6", "Data 7", "Data 8"},
|
||||||
|
{"Header column 4", "Data 9", "Data 10", "Data 11", "Data 12"},
|
||||||
|
{"Header column 5", "Data 13", "Data 14", "Data 15", "Data 16"}}};
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Output array as table with separate header row and column
|
// Output array as table with separate header row and column
|
||||||
@ -172,12 +261,142 @@ int main()
|
|||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
aoptions.headercolumn = true;
|
aoptions.headercolumn = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, headerrow, headercolumn, aoptions);
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const size_t rows = 4;
|
||||||
|
const size_t columns = 4;
|
||||||
|
|
||||||
|
const array<array<string, columns>, rows> aarray = {{{"Data 1", "Data 2", "Data 3", "Data 4"},
|
||||||
|
{"Data 5", "Data 6", "Data 7", "Data 8"},
|
||||||
|
{"Data 9", "Data 10", "Data 11", "Data 12"},
|
||||||
|
{"Data 13", "Data 14", "Data 15", "Data 16"}}};
|
||||||
|
|
||||||
|
const string headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||||
|
const string headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||||
|
|
||||||
|
vector<string> aheaderrow(headerrow, headerrow + (rows + 1) - 1);
|
||||||
|
vector<string> aheadercolumn(headerrow, headerrow + 1);
|
||||||
|
aheadercolumn.insert(aheadercolumn.end(), headercolumn, headercolumn + columns - 1);
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
aoptions.cellborder = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true, .cellborder = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .headercolumn = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = aheaderrow.data();
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.headerrow = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = aheadercolumn.data();
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.headercolumn = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.cellborder = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.cellborder = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.tableborder = false;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.tableborder = false, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.tableborder = false;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.tableborder = false, .headerrow = true, .headercolumn = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = aheaderrow.data();
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.tableborder = false;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.tableborder = false, .headerrow = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = aheadercolumn.data();
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.tableborder = false;
|
||||||
|
aoptions.headercolumn = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.tableborder = false, .headercolumn = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string *headerrow = nullptr;
|
||||||
|
string *headercolumn = nullptr;
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.tableborder = false;
|
||||||
|
aoptions.cellborder = true;
|
||||||
|
aoptions.style = k;
|
||||||
|
// tableoptions aoptions{.tableborder = false, .cellborder = true, .style = k};
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -192,15 +411,16 @@ int main()
|
|||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.boolalpha = true;
|
aoptions.boolalpha = true;
|
||||||
|
// tableoptions aoptions{.boolalpha = true};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array != NULL)
|
if (array != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
delete[] array[i];
|
delete[] array[i];
|
||||||
@ -223,19 +443,19 @@ int main()
|
|||||||
dimensions = columns;
|
dimensions = columns;
|
||||||
sortdimension = 0;
|
sortdimension = 0;
|
||||||
|
|
||||||
// qsort(array, rows, sizeof(array[0]), compare<int>);
|
// qsort(array, rows, sizeof(array[0]), compare<int *>);
|
||||||
sort(array, array + rows, compare<int>);
|
sort(array, array + rows, compare<int *>);
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
table(rows, columns, array, NULL, NULL, aoptions);
|
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array != NULL)
|
if (array != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
delete[] array[i];
|
delete[] array[i];
|
||||||
@ -243,13 +463,71 @@ int main()
|
|||||||
delete[] array;
|
delete[] array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
array<array<int, columns>, rows> aarray;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
aarray[i][j] = rand();
|
||||||
|
|
||||||
|
dimensions = columns;
|
||||||
|
sortdimension = 0;
|
||||||
|
|
||||||
|
sort(aarray.begin(), aarray.end(), compare<array<int, columns>>);
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
vector<vector<int>> array(rows, vector<int>(columns));
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
|
array[i][j] = rand();
|
||||||
|
|
||||||
|
dimensions = columns;
|
||||||
|
sortdimension = 0;
|
||||||
|
|
||||||
|
sort(array.begin(), array.end(), compare<vector<int>>);
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(array, headerrow, headercolumn, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Output single function as table
|
// Output single function as table
|
||||||
cout << "\nOutput single function as table\n\n";
|
cout << "\nOutput single function as table\n\n";
|
||||||
{
|
{
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(xmin, xmax, xscl, afunction, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
function<long double(long double)> afunction = [](auto x)
|
||||||
|
{ return x + 1; };
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true};
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
@ -259,12 +537,30 @@ int main()
|
|||||||
// Output multiple functions as table
|
// Output multiple functions as table
|
||||||
cout << "\nOutput multiple functions as table\n\n";
|
cout << "\nOutput multiple functions as table\n\n";
|
||||||
{
|
{
|
||||||
long double (*functions[])(long double) = {function1, function2};
|
function<long double(long double)> functions[] = {function1, function2};
|
||||||
|
|
||||||
tableoptions aoptions;
|
tableoptions aoptions;
|
||||||
aoptions.headerrow = true;
|
aoptions.headerrow = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true};
|
||||||
|
|
||||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
|
{
|
||||||
|
aoptions.style = k;
|
||||||
|
|
||||||
|
table(xmin, xmax, xscl, 2, functions, aoptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
function<long double(long double)> functions[] = {[](auto x)
|
||||||
|
{ return 2 * x; },
|
||||||
|
[](auto x)
|
||||||
|
{ return pow(x, 2); }};
|
||||||
|
|
||||||
|
tableoptions aoptions;
|
||||||
|
aoptions.headerrow = true;
|
||||||
|
// tableoptions aoptions{.headerrow = true};
|
||||||
|
|
||||||
|
for (unsigned int k = 0; k < size(styles); ++k)
|
||||||
{
|
{
|
||||||
aoptions.style = k;
|
aoptions.style = k;
|
||||||
|
|
||||||
|
258
tables.hpp
258
tables.hpp
@ -7,60 +7,49 @@
|
|||||||
#include <cwchar>
|
#include <cwchar>
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const char *const styles[][11] = {
|
const char *const styles[][11] = {
|
||||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
|
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
|
||||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
|
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
|
||||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light
|
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light
|
||||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, //Heavy
|
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, // Heavy
|
||||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, //Double
|
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, // Double
|
||||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light Dashed
|
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light Dashed
|
||||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} //Heavy Dashed
|
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} // Heavy Dashed
|
||||||
};
|
};
|
||||||
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
||||||
|
|
||||||
|
regex ansi(R"(\x1B\[(?:[0-9]+(?:;[0-9]+)*)?m)");
|
||||||
|
|
||||||
struct tableoptions
|
struct tableoptions
|
||||||
{
|
{
|
||||||
bool headerrow;
|
bool headerrow = false;
|
||||||
bool headercolumn;
|
bool headercolumn = false;
|
||||||
bool tableborder;
|
bool tableborder = true;
|
||||||
bool cellborder;
|
bool cellborder = false;
|
||||||
unsigned int padding;
|
unsigned int padding = 1;
|
||||||
ios_base &(*alignment)(ios_base &);
|
ios_base &(*alignment)(ios_base &) = left;
|
||||||
bool boolalpha;
|
bool boolalpha = false;
|
||||||
char *title;
|
const char *title = nullptr;
|
||||||
unsigned int style;
|
unsigned int style = 2;
|
||||||
tableoptions(void);
|
|
||||||
~tableoptions(void);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
tableoptions::tableoptions(void)
|
const tableoptions defaultoptions;
|
||||||
{
|
|
||||||
headerrow = false;
|
|
||||||
headercolumn = false;
|
|
||||||
tableborder = true;
|
|
||||||
cellborder = false;
|
|
||||||
padding = 1;
|
|
||||||
alignment = left;
|
|
||||||
boolalpha = false;
|
|
||||||
title = NULL;
|
|
||||||
style = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
tableoptions::~tableoptions(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableoptions tabledefaultoptions;
|
|
||||||
|
|
||||||
// Number of columns needed to represent the string
|
// Number of columns needed to represent the string
|
||||||
// Adapted from: https://stackoverflow.com/a/31124065
|
// Adapted from: https://stackoverflow.com/a/31124065
|
||||||
int strcol(const char *const str)
|
int strcol(const char *str)
|
||||||
{
|
{
|
||||||
|
const string astr = regex_replace(str, ansi, "");
|
||||||
|
str = astr.c_str();
|
||||||
|
|
||||||
size_t length = strlen(str);
|
size_t length = strlen(str);
|
||||||
for (size_t i = 0; i < length; ++i)
|
for (size_t i = 0; i < length; ++i)
|
||||||
if (iscntrl(str[i]))
|
if (iscntrl(str[i]))
|
||||||
@ -69,8 +58,8 @@ int strcol(const char *const str)
|
|||||||
cout << "Control character: " << (int)str[i] << "\n";
|
cout << "Control character: " << (int)str[i] << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
length = mbstowcs(NULL, str, 0);
|
length = mbstowcs(nullptr, str, 0);
|
||||||
if (length == (size_t)-1)
|
if (length == static_cast<size_t>(-1))
|
||||||
{
|
{
|
||||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -79,9 +68,9 @@ int strcol(const char *const str)
|
|||||||
|
|
||||||
wchar_t *wcstring = new wchar_t[length];
|
wchar_t *wcstring = new wchar_t[length];
|
||||||
|
|
||||||
if (mbstowcs(wcstring, str, length) == (size_t)-1)
|
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||||
{
|
{
|
||||||
if (wcstring != NULL)
|
if (wcstring != nullptr)
|
||||||
delete[] wcstring;
|
delete[] wcstring;
|
||||||
|
|
||||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||||
@ -95,7 +84,7 @@ int strcol(const char *const str)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wcstring != NULL)
|
if (wcstring != nullptr)
|
||||||
delete[] wcstring;
|
delete[] wcstring;
|
||||||
|
|
||||||
return width;
|
return width;
|
||||||
@ -154,9 +143,10 @@ string wrap(const char *const str, const size_t line_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Output char array as table
|
// Output char array as table
|
||||||
int table(const size_t rows, const size_t columns, char ***array, const tableoptions &aoptions)
|
template <typename T>
|
||||||
|
int table(const vector<vector<basic_string<T>>> &array, const tableoptions &aoptions)
|
||||||
{
|
{
|
||||||
if (array == NULL)
|
if (!size(array))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
const bool headerrow = aoptions.headerrow;
|
const bool headerrow = aoptions.headerrow;
|
||||||
@ -167,9 +157,12 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
const char *const title = aoptions.title;
|
const char *const title = aoptions.title;
|
||||||
const unsigned int style = aoptions.style;
|
const unsigned int style = aoptions.style;
|
||||||
|
|
||||||
if (style >= (sizeof styles / sizeof styles[0]))
|
if (style >= size(styles))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
const size_t rows = array.size();
|
||||||
|
const size_t columns = array[0].size();
|
||||||
|
|
||||||
int columnwidth[columns];
|
int columnwidth[columns];
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
columnwidth[j] = 0;
|
columnwidth[j] = 0;
|
||||||
@ -182,7 +175,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
{
|
{
|
||||||
int cellwidth = strcol(array[i][j]);
|
int cellwidth = strcol(array[i][j].c_str());
|
||||||
if (cellwidth > columnwidth[j])
|
if (cellwidth > columnwidth[j])
|
||||||
columnwidth[j] = cellwidth;
|
columnwidth[j] = cellwidth;
|
||||||
}
|
}
|
||||||
@ -204,7 +197,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (title != NULL and title[0] != '\0')
|
if (title != nullptr and title[0] != '\0')
|
||||||
cout << wrap(title, w.ws_col) << "\n";
|
cout << wrap(title, w.ws_col) << "\n";
|
||||||
|
|
||||||
if (tableborder)
|
if (tableborder)
|
||||||
@ -234,29 +227,25 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
else if (tableborder or (i > 0 and j > 0 and headerrow) or (j > 1 and headercolumn))
|
else if (tableborder or (i > 0 and j > 0 and headerrow) or (j > 1 and headercolumn))
|
||||||
cout << " ";
|
cout << " ";
|
||||||
|
|
||||||
const int difference = columnwidth[j] - strcol(array[i][j]);
|
const int difference = columnwidth[j] - strcol(array[i][j].c_str());
|
||||||
|
|
||||||
if ((i == 0 and headerrow) or (j == 0 and headercolumn))
|
if ((i == 0 and headerrow) or (j == 0 and headercolumn))
|
||||||
{
|
{
|
||||||
const int apadding = (difference / 2);
|
const int apadding = (difference / 2);
|
||||||
|
|
||||||
for (unsigned int k = 0; k < padding + apadding; ++k)
|
cout << string(padding + apadding, ' ');
|
||||||
cout << " ";
|
|
||||||
|
|
||||||
cout << "\e[1m" << array[i][j] << "\e[22m";
|
cout << "\e[1m" << array[i][j] << "\e[22m";
|
||||||
|
|
||||||
for (unsigned int k = 0; k < padding + (difference - apadding); ++k)
|
cout << string(padding + (difference - apadding), ' ');
|
||||||
cout << " ";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (unsigned int k = 0; k < padding; ++k)
|
cout << string(padding, ' ');
|
||||||
cout << " ";
|
|
||||||
|
|
||||||
cout << aoptions.alignment << setw(difference + strlen(array[i][j])) << array[i][j];
|
cout << aoptions.alignment << setw(difference + array[i][j].length()) << array[i][j];
|
||||||
|
|
||||||
for (unsigned int k = 0; k < padding; ++k)
|
cout << string(padding, ' ');
|
||||||
cout << " ";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,8 +270,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
||||||
cout << styles[style][0];
|
cout << styles[style][0];
|
||||||
else if (i < (rows - 1) and headercolumn)
|
else if (i < (rows - 1) and headercolumn)
|
||||||
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
cout << string((2 * padding) + columnwidth[j], ' ');
|
||||||
cout << " ";
|
|
||||||
|
|
||||||
if (j == (columns - 1))
|
if (j == (columns - 1))
|
||||||
{
|
{
|
||||||
@ -329,29 +317,38 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert array to char array and output as table
|
// Convert array to char array and output as table
|
||||||
template <typename T>
|
template <typename T1, typename T2>
|
||||||
int table(size_t rows, size_t columns, const T &array, const char *const headerrow[], const char *const headercolumn[], const tableoptions &aoptions)
|
int table(const T1 &aarray, T2 headerrow[] = nullptr, T2 headercolumn[] = nullptr, const tableoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
|
if (!size(aarray))
|
||||||
|
return 1;
|
||||||
|
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
|
|
||||||
if (headerrow != NULL)
|
size_t rows = size(aarray);
|
||||||
|
size_t columns = size(aarray[0]);
|
||||||
|
|
||||||
|
if (!all_of(begin(aarray), end(aarray), [columns](auto &x)
|
||||||
|
{ return size(x) == columns; }))
|
||||||
|
{
|
||||||
|
cerr << "Error: The rows of the array must have the same number of columns.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headerrow != nullptr)
|
||||||
++rows;
|
++rows;
|
||||||
|
|
||||||
if (headercolumn != NULL)
|
if (headercolumn != nullptr)
|
||||||
++columns;
|
++columns;
|
||||||
|
|
||||||
char ***aarray;
|
vector<vector<string>> aaarray(rows, vector<string>(columns));
|
||||||
aarray = new char **[rows];
|
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
|
||||||
aarray[i] = new char *[columns];
|
|
||||||
|
|
||||||
if (headerrow != NULL)
|
if (headerrow != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
{
|
{
|
||||||
aarray[i][j] = new char[strlen(headerrow[j]) + 1];
|
aaarray[i][j] = headerrow[j];
|
||||||
strcpy(aarray[i][j], headerrow[j]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
@ -359,15 +356,14 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
|||||||
|
|
||||||
for (unsigned int ii = 0; i < rows; ++i)
|
for (unsigned int ii = 0; i < rows; ++i)
|
||||||
{
|
{
|
||||||
if (headercolumn != NULL)
|
if (headercolumn != nullptr)
|
||||||
{
|
{
|
||||||
unsigned int ii = i;
|
unsigned int ii = i;
|
||||||
|
|
||||||
if (headerrow != NULL)
|
if (headerrow != nullptr)
|
||||||
--ii;
|
--ii;
|
||||||
|
|
||||||
aarray[i][j] = new char[strlen(headercolumn[ii]) + 1];
|
aaarray[i][j] = headercolumn[ii];
|
||||||
strcpy(aarray[i][j], headercolumn[ii]);
|
|
||||||
|
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
@ -379,10 +375,8 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
|||||||
if (aoptions.boolalpha)
|
if (aoptions.boolalpha)
|
||||||
strm << boolalpha;
|
strm << boolalpha;
|
||||||
|
|
||||||
strm << array[ii][jj];
|
strm << aarray[ii][jj];
|
||||||
string str = strm.str();
|
aaarray[i][j] = strm.str();
|
||||||
aarray[i][j] = new char[str.length() + 1];
|
|
||||||
strcpy(aarray[i][j], str.c_str());
|
|
||||||
|
|
||||||
++jj;
|
++jj;
|
||||||
}
|
}
|
||||||
@ -391,26 +385,48 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
|||||||
++ii;
|
++ii;
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = table(rows, columns, aarray, aoptions);
|
return table(aaarray, aoptions);
|
||||||
|
}
|
||||||
|
|
||||||
if (aarray != NULL)
|
template <typename T>
|
||||||
|
int table(const size_t rows, const size_t columns, T **aarray, const char *const headerrow[] = nullptr, const char *const headercolumn[] = nullptr, const tableoptions &aoptions = defaultoptions)
|
||||||
|
{
|
||||||
|
vector<vector<T>> aaarray(rows, vector<T>(columns));
|
||||||
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
|
copy(aarray[i], aarray[i] + columns, aaarray[i].begin());
|
||||||
|
|
||||||
|
string *aheaderrow = nullptr;
|
||||||
|
string *aheadercolumn = nullptr;
|
||||||
|
|
||||||
|
if (headerrow and headercolumn)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
vector<string> aaheaderrow(rows + 1);
|
||||||
{
|
copy(headerrow, headerrow + rows + 1, aaheaderrow.begin());
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
aheaderrow = aaheaderrow.data();
|
||||||
delete[] aarray[i][j];
|
|
||||||
|
|
||||||
delete[] aarray[i];
|
vector<string> aaheadercolumn(columns);
|
||||||
}
|
copy(headercolumn, headercolumn + columns, aaheadercolumn.begin());
|
||||||
delete[] aarray;
|
aheadercolumn = aaheadercolumn.data();
|
||||||
|
}
|
||||||
|
else if (headerrow)
|
||||||
|
{
|
||||||
|
vector<string> aaheaderrow(rows);
|
||||||
|
copy(headerrow, headerrow + rows, aaheaderrow.begin());
|
||||||
|
aheaderrow = aaheaderrow.data();
|
||||||
|
}
|
||||||
|
else if (headercolumn)
|
||||||
|
{
|
||||||
|
vector<string> aaheadercolumn(columns);
|
||||||
|
copy(headercolumn, headercolumn + columns, aaheadercolumn.begin());
|
||||||
|
aheadercolumn = aaheadercolumn.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
return code;
|
return table(aaarray, aheaderrow, aheadercolumn, aoptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert one or more functions to array and output as table
|
// Convert one or more functions to array and output as table
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int table(const long double xmin, const long double xmax, const long double xscl, const size_t numfunctions, T (*functions[])(T), const tableoptions &aoptions)
|
int table(const long double xmin, const long double xmax, const long double xscl, const size_t numfunctions, function<T(T)> functions[], const tableoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
if (numfunctions == 0)
|
if (numfunctions == 0)
|
||||||
return 1;
|
return 1;
|
||||||
@ -433,75 +449,53 @@ int table(const long double xmin, const long double xmax, const long double xscl
|
|||||||
const char *const aheaderrow[] = {"x", "y"};
|
const char *const aheaderrow[] = {"x", "y"};
|
||||||
// const char* const aheaderrow[] = {"", "x", "y"};
|
// const char* const aheaderrow[] = {"", "x", "y"};
|
||||||
|
|
||||||
const size_t length = (sizeof aheaderrow / sizeof aheaderrow[0]);
|
const size_t length = size(aheaderrow);
|
||||||
|
|
||||||
char **headerrow = new char *[columns];
|
string *headerrow = new string[columns];
|
||||||
|
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
for (unsigned int j = 0; j < columns; ++j)
|
||||||
{
|
{
|
||||||
if (j < (length - 1) or numfunctions == 1)
|
if (j < (length - 1) or numfunctions == 1)
|
||||||
{
|
{
|
||||||
headerrow[j] = new char[strlen(aheaderrow[j]) + 1];
|
headerrow[j] = aheaderrow[j];
|
||||||
strcpy(headerrow[j], aheaderrow[j]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ostringstream strm;
|
ostringstream strm;
|
||||||
strm << aheaderrow[length - 1] << j - length + 2;
|
strm << aheaderrow[length - 1] << j - length + 2;
|
||||||
string str = strm.str();
|
headerrow[j] = strm.str();
|
||||||
headerrow[j] = new char[str.length() + 1];
|
|
||||||
strcpy(headerrow[j], str.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char **headercolumn = NULL;
|
string *headercolumn = nullptr;
|
||||||
// headercolumn = new char *[rows + 1];
|
// headercolumn = new string[rows + 1];
|
||||||
|
|
||||||
// for (unsigned int i = 0; i < rows + 1; ++i)
|
// for (unsigned int i = 0; i < rows + 1; ++i)
|
||||||
// {
|
// {
|
||||||
// ostringstream strm;
|
// ostringstream strm;
|
||||||
// strm << i + 1;
|
// strm << i + 1;
|
||||||
// string str = strm.str();
|
// headercolumn[i] = strm.str();
|
||||||
// headercolumn[i] = new char[str.length() + 1];
|
|
||||||
// strcpy(headercolumn[i], str.c_str());
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
T **array;
|
vector<vector<T>> aarray(rows, vector<T>(columns));
|
||||||
array = new T *[rows];
|
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
|
||||||
array[i] = new T[columns];
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
for (unsigned int i = 0; i < rows; ++i)
|
||||||
{
|
{
|
||||||
array[i][0] = (i / xscl) + xmin;
|
aarray[i][0] = (i / xscl) + xmin;
|
||||||
|
|
||||||
for (unsigned int j = 0; j < numfunctions; ++j)
|
for (unsigned int j = 0; j < numfunctions; ++j)
|
||||||
array[i][j + 1] = (functions[j])(array[i][0]);
|
aarray[i][j + 1] = (functions[j])(aarray[i][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int code = table(rows, columns, array, headerrow, headercolumn, aoptions);
|
int code = table(aarray, headerrow, headercolumn, aoptions);
|
||||||
|
|
||||||
if (array != NULL)
|
if (headerrow != nullptr)
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < rows; ++i)
|
|
||||||
delete[] array[i];
|
|
||||||
|
|
||||||
delete[] array;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headerrow != NULL)
|
|
||||||
{
|
|
||||||
for (unsigned int j = 0; j < columns; ++j)
|
|
||||||
delete[] headerrow[j];
|
|
||||||
|
|
||||||
delete[] headerrow;
|
delete[] headerrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (headercolumn != NULL)
|
// if (headercolumn != nullptr)
|
||||||
// {
|
// {
|
||||||
// for (unsigned int i = 0; i < rows + 1; ++i)
|
|
||||||
// delete[] headercolumn[i];
|
|
||||||
|
|
||||||
// delete[] headercolumn;
|
// delete[] headercolumn;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -510,10 +504,18 @@ int table(const long double xmin, const long double xmax, const long double xscl
|
|||||||
|
|
||||||
// Convert single function to array and output as table
|
// Convert single function to array and output as table
|
||||||
template <typename T>
|
template <typename T>
|
||||||
int table(const long double xmin, const long double xmax, const long double xscl, T afunction(T), const tableoptions &aoptions)
|
int table(const long double xmin, const long double xmax, const long double xscl, const function<T(T)> &afunction, const tableoptions &aoptions = defaultoptions)
|
||||||
{
|
{
|
||||||
T(*functions[])
|
std::function<T(T)> afunctions[] = {afunction};
|
||||||
(T) = {afunction};
|
|
||||||
|
|
||||||
return table(xmin, xmax, xscl, 1, functions, aoptions);
|
return table(xmin, xmax, xscl, 1, afunctions, aoptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert single function to array and output as table
|
||||||
|
template <typename T>
|
||||||
|
int table(const long double xmin, const long double xmax, const long double xscl, T afunction(T), const tableoptions &aoptions = defaultoptions)
|
||||||
|
{
|
||||||
|
std::function<T(T)> afunctions[] = {afunction};
|
||||||
|
|
||||||
|
return table(xmin, xmax, xscl, 1, afunctions, aoptions);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user