Updated to support and use modern C++ features and added more examples.

This commit is contained in:
Teal Dulcet 2022-07-14 01:33:38 -07:00
parent 37e257c5ee
commit 274f949079
11 changed files with 1123 additions and 380 deletions

View File

@ -27,9 +27,9 @@ jobs:
$CXX --version
- name: Script
run: |
$CXX -Wall -g -fsanitize=address,undefined tables.cpp -o tables
$CXX -Wall -g -Og -fsanitize=address,undefined tables.cpp -o tables
./tables
$CXX -Wall -g -fsanitize=address,undefined graphs.cpp -o graphs
$CXX -Wall -g -Og -fsanitize=address,undefined graphs.cpp -o graphs
./graphs
- name: Cppcheck
run: cppcheck --enable=all .

View File

@ -13,12 +13,12 @@ install:
- sudo apt-get -yqq update
- sudo apt-get -yqq install cppcheck
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
- 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
- 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++ -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
- cppcheck --enable=all .

332
README.md
View File

@ -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.
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.
## Tables
### 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.
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
##### C style char array
```cpp
#include "tables.hpp"
@ -41,7 +50,7 @@ int main()
aoptions.headerrow = true;
aoptions.headercolumn = true;
table(rows, columns, array, NULL, NULL, aoptions);
table(rows, columns, array, nullptr, nullptr, aoptions);
// Deallocate array
@ -49,12 +58,43 @@ int main()
}
```
##### 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;
}
```
Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters), but not newlines and tabs.
![](images/char%20array%20to%20table.png)
#### Output array as table with separate header row and column
##### C style char array
```cpp
#include "tables.hpp"
@ -84,10 +124,43 @@ int main()
}
```
##### 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;
}
```
Output same as example above.
#### Output array as table
##### C style pointer
```cpp
#include "tables.hpp"
@ -102,7 +175,7 @@ int main()
// Allocate and set array
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
table(rows, columns, array);
// Deallocate array
@ -110,10 +183,34 @@ int main()
}
```
##### 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;
}
```
![](images/array%20to%20table.png)
#### Output sorted array as table
##### C style pointer
```cpp
#include <algorithm>
#include "tables.hpp"
@ -124,7 +221,7 @@ int dimensions; // Number of columns
int sortdimension; // Column to sort by
template <typename T>
bool compare(const T *a, const T *b)
bool compare(const T &a, const T &b)
{
if (a[sortdimension] == b[sortdimension])
for (int i = 0; i < dimensions; ++i)
@ -146,9 +243,9 @@ int main()
dimensions = columns;
sortdimension = 0;
sort(array, array + rows, compare<int>);
sort(array, array + rows, compare<int *>);
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
table(rows, columns, array);
// Deallocate array
@ -156,10 +253,52 @@ int main()
}
```
##### 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;
}
```
![](images/sorted%20array%20to%20table.png)
#### Output single function as table
##### C style function pointer
```cpp
#include "tables.hpp"
@ -185,10 +324,37 @@ int main()
}
```
##### 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;
}
```
![](images/function%20to%20table.png)
#### Output multiple functions as table
##### C style function pointer
```cpp
#include <cmath>
#include "tables.hpp"
@ -214,7 +380,38 @@ int main()
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};
function<double(double)> functions[] = {function1, function2};
tableoptions aoptions;
aoptions.headerrow = true;
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;
@ -274,7 +471,7 @@ Default value: `false`
#### 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).
@ -315,15 +512,21 @@ Values:
### 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.
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).
#### Output array as plot
#### Output single array as plot
##### C style pointer
```cpp
#include "graphs.hpp"
@ -346,7 +549,7 @@ int main()
// 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
@ -354,12 +557,45 @@ int main()
}
```
##### 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;
}
```
If `xmin` and `xmax` are both `0`, they will be set to the respective minimum and maximum values of x in the array. If `ymin` and `ymax` are both `0`, they will be set to the respective minimum and maximum values of y in the array.
![](images/array%20to%20plot.png)
Use `graph()` to plot multiple arrays, which can be of different sizes.
#### Output single function as graph
##### C style function pointer
```cpp
#include "graphs.hpp"
@ -380,7 +616,33 @@ int main()
long double ymin = -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;
}
@ -390,6 +652,8 @@ int main()
#### Output multiple functions as graph
##### C style function pointer
```cpp
#include "graphs.hpp"
@ -418,9 +682,40 @@ int main()
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};
function<double(double)> functions[] = {function1, function2};
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions, graphdefaultoptions);
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;
}
@ -452,7 +747,7 @@ Requires `border` and `axislabel` to be `true`.
#### 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).
@ -543,5 +838,4 @@ Both:
* Port to other languages (C, Java, Rust, etc.)
C++:
* Handle formatted text in the tables
* Support plotting multiple arrays of different sizes
* Support tables with the `wchar_t`, `char16_t` and `char32_t` C data types and the `wstring`, `u16string` and `u32string` C++ data types.

View File

@ -1,40 +1,42 @@
// 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
#include <cctype>
#include <array>
#include <vector>
#include "graphs.hpp"
using namespace std;
long double afunction(long double x)
constexpr long double afunction(long double x)
{
return x + 1;
}
long double function1(long double x)
constexpr long double function1(long double x)
{
return 2 * x;
}
long double function2(long double x)
constexpr long double function2(long double x)
{
return pow(x, 2);
}
long double function3(long double x)
constexpr long double function3(long double x)
{
return sin(x);
}
long double function4(long double x)
constexpr long double function4(long double x)
{
return cos(x);
}
long double function5(long double x)
constexpr long double function5(long double x)
{
return tan(x);
}
@ -52,7 +54,7 @@ int main()
const size_t rows = 10;
const size_t columns = 2;
// Output array as plot
// Output single array as plot
cout << "\nOutput array as plot\n\n";
{
long double **array;
@ -62,18 +64,18 @@ int main()
for (unsigned int i = 0; i < rows; ++i)
for (unsigned int j = 0; j < columns; ++j)
array[i][j] = i + j; //rand();
array[i][j] = i + j; // rand();
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, rows, array, aoptions);
}
if (array != NULL)
if (array != nullptr)
{
for (unsigned int i = 0; i < rows; ++i)
delete[] array[i];
@ -81,12 +83,57 @@ int main()
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
cout << "\nOutput single function as graph\n\n";
{
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;
@ -96,11 +143,26 @@ int main()
// Output multiple functions as graph
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;
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;
@ -113,28 +175,30 @@ int main()
const long double ymin = -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;
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;
graph(height, width, xmin, xmax, ymin, ymax, 3, functions, aoptions);
}
/*aoptions.style = 2;
/* aoptions.style = 2;
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);
usleep(200000);
}*/
} */
}
return 0;

View File

@ -4,25 +4,29 @@
#include <sstream>
#include <cstring>
#include <cmath>
#include <limits>
#include <cfloat>
#include <iomanip>
#include <cwchar>
#include <clocale>
#include <cstdlib>
#include <algorithm>
#include <array>
#include <vector>
#include <iterator>
#include <numeric>
#include <sys/ioctl.h>
#include <unistd.h>
using namespace std;
const char *const styles[][11] = {
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
{"", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
{"", "", "", "", "", "", "", "", "", "", ""}, //Light
{"", "", "", "", "", "", "", "", "", "", ""}, //Heavy
{"", "", "", "", "", "", "", "", "", "", ""}, //Double
{"", "", "", "", "", "", "", "", "", "", ""}, //Light Dashed
{"", "", "", "", "", "", "", "", "", "", ""} //Heavy Dashed
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
{"", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
{"", "", "", "", "", "", "", "", "", "", ""}, // Light
{"", "", "", "", "", "", "", "", "", "", ""}, // Heavy
{"", "", "", "", "", "", "", "", "", "", ""}, // Double
{"", "", "", "", "", "", "", "", "", "", ""}, // Light Dashed
{"", "", "", "", "", "", "", "", "", "", ""} // Heavy Dashed
};
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//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
{
bool border;
bool axislabel;
bool axisunitslabel;
char *title;
unsigned int style;
unsigned int color;
graphoptions(void);
~graphoptions(void);
bool border = true;
bool axislabel = true;
bool axisunitslabel = true;
const char *title = nullptr;
unsigned int style = 2;
unsigned int color = 2;
};
graphoptions::graphoptions(void)
{
border = true;
axislabel = true;
axisunitslabel = true;
style = 2;
color = 2;
title = NULL;
}
graphoptions::~graphoptions(void)
{
}
const graphoptions graphdefaultoptions;
const graphoptions defaultoptions;
// Number of columns needed to represent the string
// Adapted from: https://stackoverflow.com/a/31124065
@ -76,8 +64,8 @@ int strcol(const char *const str)
cout << "Control character: " << (int)str[i] << "\n";
}
length = mbstowcs(NULL, str, 0);
if (length == (size_t)-1)
length = mbstowcs(nullptr, str, 0);
if (length == static_cast<size_t>(-1))
{
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
exit(1);
@ -86,9 +74,9 @@ int strcol(const char *const str)
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;
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
@ -102,7 +90,7 @@ int strcol(const char *const str)
exit(1);
}
if (wcstring != NULL)
if (wcstring != nullptr)
delete[] wcstring;
return width;
@ -168,7 +156,7 @@ size_t outputlabel(const long double label, ostringstream &strm)
long double intpart = 0;
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)
{
@ -224,9 +212,9 @@ size_t outputlabel(const long double label, ostringstream &strm)
}
// 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;
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 unsigned int style = aoptions.style;
if (style >= (sizeof styles / sizeof styles[0]))
if (style >= size(styles))
return 1;
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, "");
if (title != NULL and title[0] != '\0')
if (title != nullptr and title[0] != '\0')
cout << wrap(title, w.ws_col) << "\n";
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)
{
bool output = false;
long double label;
long double label = 0;
int adivisor = divisor;
if (i < yaxis)
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)
{
@ -340,7 +328,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
if (i < yaxis)
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)
{
@ -368,7 +356,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
if (j < xaxis)
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)
{
@ -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)
{
long double label;
long double label = 0;
int adivisor = divisor;
if (j < xaxis)
{
@ -497,19 +485,24 @@ int graph(const size_t height, const size_t width, const long double xmin, const
return 0;
}
// Convert array to graph and output
// Convert one or more arrays 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 **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;
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;
}
const unsigned int color = aoptions.color;
if (color >= (sizeof colors / sizeof colors[0]))
if (color >= size(colors))
return 1;
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)
{
xmin = numeric_limits<T>::max();
xmax = numeric_limits<T>::min();
for (unsigned int i = 0; i < rows; ++i)
{
if (array[i][0] < xmin)
xmin = array[i][0];
if (array[i][0] > xmax)
xmax = array[i][0];
}
const auto compare = [](const auto &a, const auto &b)
{ return a[0] < b[0]; };
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto &current, const auto &array)
{ 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];
xmax = result.second[0];
}
if (ymin == 0 and ymax == 0)
{
ymin = numeric_limits<T>::max();
ymax = numeric_limits<T>::min();
for (unsigned int i = 0; i < rows; ++i)
{
if (array[i][1] < ymin)
ymin = array[i][1];
if (array[i][1] > ymax)
ymax = array[i][1];
}
const auto compare = [](const auto &a, const auto &b)
{ return a[1] < b[1]; };
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto &current, const auto &array)
{ 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];
ymax = result.second[1];
}
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 yaxis = ymax * yscl;
unsigned short **aarray;
aarray = new unsigned short *[width];
for (unsigned int i = 0; i < width; ++i)
aarray[i] = new unsigned short[height];
vector<vector<unsigned short>> aarray(width, vector<unsigned short>(height, 0));
for (unsigned int i = 0; i < width; ++i)
for (unsigned int j = 0; j < height; ++j)
aarray[i][j] = 0;
for (unsigned int j = 0; j < size(arrays); ++j)
{
auto array = arrays[j];
const unsigned int color = (j % (size(colors) - 2)) + 3;
for (unsigned int i = 0; i < rows; ++i)
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;
aarray[x][y] = color + 1;
}
}
int code = graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
if (aarray != NULL)
if (aarray[x][y])
{
for (unsigned int i = 0; i < width; ++i)
delete[] aarray[i];
delete[] aarray;
if (aarray[x][y] != color)
aarray[x][y] = 1;
}
else
aarray[x][y] = color;
}
}
}
return code;
return graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
}
// 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 T &aarray, const graphoptions &aoptions = defaultoptions)
{
const std::array<T, 1> aaarray = {aarray};
return graphs(height, width, xmin, xmax, ymin, ymax, aaarray, aoptions);
}
// 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
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;
if (color >= (sizeof colors / sizeof colors[0]))
if (color >= size(colors))
return 1;
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 yaxis = ymax * yscl;
unsigned short **array;
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;
vector<vector<unsigned short>> array(width, vector<unsigned short>(height, 0));
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)
{
@ -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);
if (array != NULL)
{
for (unsigned int i = 0; i < width; ++i)
delete[] array[i];
delete[] array;
}
return code;
return graph(height, width, xmin, xmax, ymin, ymax, array, 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)
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[])
(T) = {afunction};
std::function<T(T)> afunctions[] = {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);
}

View File

@ -2,20 +2,20 @@
### 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.
Run with: `python3 test.py`.
#### Output char array as table
#### Output str array as table
```py
import tables
# 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.
@ -42,9 +42,9 @@ Output same as example above.
```py
import tables
# Set array
# Set array, can be any sequence data type
tables.array(array, None, None)
tables.array(array)
```
![](../images/array%20to%20table.png)
@ -60,7 +60,7 @@ sortdimension = 0 # Column to sort by
array = sorted(array, key=lambda x: x[sortdimension])
tables.array(array, None, None)
tables.array(array)
```
![](../images/sorted%20array%20to%20table.png)
@ -82,6 +82,22 @@ tables.function(xmin, xmax, xscl, afunction, headerrow=True)
![](../images/function%20to%20table.png)
#### 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
```py
@ -105,6 +121,23 @@ tables.functions(xmin, xmax, xscl, functions, headerrow=True)
![](../images/multiple%20functions%20to%20table.png)
#### 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
#### Header row
@ -182,7 +215,7 @@ Values:
### 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.
@ -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).
#### Output array as plot
#### Output single array as plot
```py
import graphs
@ -203,7 +236,7 @@ xmax = 20
ymin = -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)
```
@ -212,6 +245,8 @@ If `xmin` and `xmax` are both `0`, they will be set to the respective minimum an
![](../images/array%20to%20plot.png)
Use `graphs.arrays()` to plot multiple arrays, which can be of different sizes.
#### Output single function as graph
```py
@ -233,6 +268,26 @@ graphs.function(height, width, xmin, xmax, ymin, ymax, afunction)
![](../images/function%20to%20graph.png)
#### 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
```py
@ -260,6 +315,27 @@ graphs.functions(height, width, xmin, xmax, ymin, ymax, functions)
![](../images/multiple%20functions%20to%20graph.png)
#### 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
#### Border/Axis

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546
@ -113,7 +113,7 @@ def outputlabel(label: float) -> Tuple[int, str]:
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"""
if not array:
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
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):
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
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:
strm += styles[style][7]
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
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:
strm += styles[style][3]
output = True
@ -314,7 +314,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
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"""
if not aarrays:
return 1
@ -328,6 +328,12 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
w = shutil.get_terminal_size()
if height == 0:
height = w.lines * 4
if width == 0:
width = w.columns * 2
aheight = height // 4
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)]
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:
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)
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"""
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"""
if color < 0 or color >= len(colors):
return 1
if len(afunctions) == 0:
if not afunctions:
return 1
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:
width = w.columns * 2
aheight = height / 4
awidth = width / 2
aheight = height // 4
awidth = width // 2
if aheight > w.lines:
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)
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"""
return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546
@ -39,7 +39,7 @@ def strcol(str: str) -> int:
# 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"""
if not array:
return 1
@ -158,7 +158,7 @@ def table(array: List[List[str]], headerrow: bool=False, headercolumn: bool=Fals
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"""
if not aarray:
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)
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"""
if len(afunctions) == 0:
if not afunctions:
return 1
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)
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"""
return functions(xmin, xmax, xscl, [afunction], headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Teal Dulcet, CS546
@ -78,11 +78,16 @@ for k in range(len(tables.styles)):
print("\nOutput single function as table\n")
for k in range(len(tables.styles)):
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")
for k in range(len(tables.styles)):
tables.functions(xmin, xmax, xscl, [
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
width = 160
@ -92,20 +97,26 @@ xmax = 20
ymin = -20
ymax = 20
print("\nOutput array as plot\n")
array = [[i + j for j in range(2)] for i in range(10)]
print("\nOutput single array as plot\n")
array = [range(i, i + 2) for i in range(10)]
for k in range(len(graphs.styles)):
graphs.array(height, width, xmin, xmax, ymin, ymax, array, style=k)
print("\nOutput single function as graph\n")
for k in range(len(graphs.styles)):
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")
for k in range(len(graphs.styles)):
graphs.functions(height, width, xmin, xmax, ymin,
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)):
graphs.functions(height, width, -(2 * math.pi), 2 *
math.pi, -4, 4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)
graphs.functions(height, width, -(2 * math.pi), 2 * math.pi, -4,
4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)

View File

@ -1,27 +1,29 @@
// 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
#include <cctype>
#include <cmath>
#include <algorithm>
#include <array>
#include <vector>
#include "tables.hpp"
using namespace std;
long double afunction(long double x)
constexpr long double afunction(long double x)
{
return x + 1;
}
long double function1(long double x)
constexpr long double function1(long double x)
{
return 2 * x;
}
long double function2(long double x)
constexpr long double function2(long double x)
{
return pow(x, 2);
}
@ -32,8 +34,8 @@ int sortdimension = 0;
/* template <typename T>
int compare(const void *pa, const void *pb)
{
const T *a = *(const T **)pa;
const T *b = *(const T **)pb;
const T a = *(const T *)pa;
const T b = *(const T *)pb;
if (a[sortdimension] == b[sortdimension])
{
@ -58,7 +60,7 @@ int compare(const void *pa, const void *pb)
} */
template <typename T>
bool compare(const T *a, const T *b)
bool compare(const T &a, const T &b)
{
if (a[sortdimension] == b[sortdimension])
for (int i = 0; i < dimensions; ++i)
@ -77,6 +79,9 @@ int main()
const long double xmax = 10;
const long double xscl = 2; // 80 / (xmax - xmin);
string *headerrow = nullptr;
string *headercolumn = nullptr;
// Output array as table
cout << "\nOutput array as table\n\n";
{
@ -91,14 +96,14 @@ int main()
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;
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)
delete[] array[i];
@ -106,6 +111,38 @@ int main()
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;
array = new long double *[rows];
@ -118,14 +155,14 @@ int main()
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;
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)
delete[] array[i];
@ -133,6 +170,38 @@ int main()
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
cout << "\nOutput char array as table\n\n";
{
@ -146,12 +215,32 @@ int main()
tableoptions aoptions;
aoptions.headerrow = 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;
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
@ -172,12 +261,142 @@ int main()
tableoptions aoptions;
aoptions.headerrow = 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;
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;
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;
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)
delete[] array[i];
@ -223,19 +443,19 @@ int main()
dimensions = columns;
sortdimension = 0;
// qsort(array, rows, sizeof(array[0]), compare<int>);
sort(array, array + rows, compare<int>);
// qsort(array, rows, sizeof(array[0]), compare<int *>);
sort(array, array + rows, compare<int *>);
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;
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)
delete[] array[i];
@ -243,13 +463,71 @@ int main()
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
cout << "\nOutput single function as table\n\n";
{
tableoptions aoptions;
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;
@ -259,12 +537,30 @@ int main()
// Output multiple functions as table
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;
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;

View File

@ -7,60 +7,49 @@
#include <cwchar>
#include <clocale>
#include <cstdlib>
#include <vector>
#include <iterator>
#include <sys/ioctl.h>
#include <unistd.h>
#include <regex>
using namespace std;
const char *const styles[][11] = {
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
{"", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
{"", "", "", "", "", "", "", "", "", "", ""}, //Light
{"", "", "", "", "", "", "", "", "", "", ""}, //Heavy
{"", "", "", "", "", "", "", "", "", "", ""}, //Double
{"", "", "", "", "", "", "", "", "", "", ""}, //Light Dashed
{"", "", "", "", "", "", "", "", "", "", ""} //Heavy Dashed
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
{"", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
{"", "", "", "", "", "", "", "", "", "", ""}, // Light
{"", "", "", "", "", "", "", "", "", "", ""}, // Heavy
{"", "", "", "", "", "", "", "", "", "", ""}, // Double
{"", "", "", "", "", "", "", "", "", "", ""}, // Light Dashed
{"", "", "", "", "", "", "", "", "", "", ""} // Heavy Dashed
};
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
regex ansi(R"(\x1B\[(?:[0-9]+(?:;[0-9]+)*)?m)");
struct tableoptions
{
bool headerrow;
bool headercolumn;
bool tableborder;
bool cellborder;
unsigned int padding;
ios_base &(*alignment)(ios_base &);
bool boolalpha;
char *title;
unsigned int style;
tableoptions(void);
~tableoptions(void);
bool headerrow = false;
bool headercolumn = false;
bool tableborder = true;
bool cellborder = false;
unsigned int padding = 1;
ios_base &(*alignment)(ios_base &) = left;
bool boolalpha = false;
const char *title = nullptr;
unsigned int style = 2;
};
tableoptions::tableoptions(void)
{
headerrow = false;
headercolumn = false;
tableborder = true;
cellborder = false;
padding = 1;
alignment = left;
boolalpha = false;
title = NULL;
style = 2;
}
tableoptions::~tableoptions(void)
{
}
const tableoptions tabledefaultoptions;
const tableoptions defaultoptions;
// Number of columns needed to represent the string
// 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);
for (size_t i = 0; i < length; ++i)
if (iscntrl(str[i]))
@ -69,8 +58,8 @@ int strcol(const char *const str)
cout << "Control character: " << (int)str[i] << "\n";
}
length = mbstowcs(NULL, str, 0);
if (length == (size_t)-1)
length = mbstowcs(nullptr, str, 0);
if (length == static_cast<size_t>(-1))
{
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
exit(1);
@ -79,9 +68,9 @@ int strcol(const char *const str)
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;
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
@ -95,7 +84,7 @@ int strcol(const char *const str)
exit(1);
}
if (wcstring != NULL)
if (wcstring != nullptr)
delete[] wcstring;
return width;
@ -154,9 +143,10 @@ string wrap(const char *const str, const size_t line_length)
}
// 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;
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 unsigned int style = aoptions.style;
if (style >= (sizeof styles / sizeof styles[0]))
if (style >= size(styles))
return 1;
const size_t rows = array.size();
const size_t columns = array[0].size();
int columnwidth[columns];
for (unsigned int j = 0; j < columns; ++j)
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)
{
int cellwidth = strcol(array[i][j]);
int cellwidth = strcol(array[i][j].c_str());
if (cellwidth > columnwidth[j])
columnwidth[j] = cellwidth;
}
@ -204,7 +197,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
return 1;
}
if (title != NULL and title[0] != '\0')
if (title != nullptr and title[0] != '\0')
cout << wrap(title, w.ws_col) << "\n";
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))
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))
{
const int apadding = (difference / 2);
for (unsigned int k = 0; k < padding + apadding; ++k)
cout << " ";
cout << string(padding + apadding, ' ');
cout << "\e[1m" << array[i][j] << "\e[22m";
for (unsigned int k = 0; k < padding + (difference - apadding); ++k)
cout << " ";
cout << string(padding + (difference - apadding), ' ');
}
else
{
for (unsigned int k = 0; k < padding; ++k)
cout << " ";
cout << string(padding, ' ');
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 << " ";
cout << string(padding, ' ');
}
}
@ -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)
cout << styles[style][0];
else if (i < (rows - 1) and headercolumn)
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
cout << " ";
cout << string((2 * padding) + columnwidth[j], ' ');
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
template <typename T>
int table(size_t rows, size_t columns, const T &array, const char *const headerrow[], const char *const headercolumn[], const tableoptions &aoptions)
template <typename T1, typename T2>
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 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;
if (headercolumn != NULL)
if (headercolumn != nullptr)
++columns;
char ***aarray;
aarray = new char **[rows];
for (unsigned int i = 0; i < rows; ++i)
aarray[i] = new char *[columns];
vector<vector<string>> aaarray(rows, vector<string>(columns));
if (headerrow != NULL)
if (headerrow != nullptr)
{
for (unsigned int j = 0; j < columns; ++j)
{
aarray[i][j] = new char[strlen(headerrow[j]) + 1];
strcpy(aarray[i][j], headerrow[j]);
aaarray[i][j] = headerrow[j];
}
++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)
{
if (headercolumn != NULL)
if (headercolumn != nullptr)
{
unsigned int ii = i;
if (headerrow != NULL)
if (headerrow != nullptr)
--ii;
aarray[i][j] = new char[strlen(headercolumn[ii]) + 1];
strcpy(aarray[i][j], headercolumn[ii]);
aaarray[i][j] = headercolumn[ii];
++j;
}
@ -379,10 +375,8 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
if (aoptions.boolalpha)
strm << boolalpha;
strm << array[ii][jj];
string str = strm.str();
aarray[i][j] = new char[str.length() + 1];
strcpy(aarray[i][j], str.c_str());
strm << aarray[ii][jj];
aaarray[i][j] = strm.str();
++jj;
}
@ -391,26 +385,48 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
++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 j = 0; j < columns; ++j)
delete[] aarray[i][j];
vector<string> aaheaderrow(rows + 1);
copy(headerrow, headerrow + rows + 1, aaheaderrow.begin());
aheaderrow = aaheaderrow.data();
delete[] aarray[i];
vector<string> aaheadercolumn(columns);
copy(headercolumn, headercolumn + columns, aaheadercolumn.begin());
aheadercolumn = aaheadercolumn.data();
}
delete[] aarray;
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
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)
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 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)
{
if (j < (length - 1) or numfunctions == 1)
{
headerrow[j] = new char[strlen(aheaderrow[j]) + 1];
strcpy(headerrow[j], aheaderrow[j]);
headerrow[j] = aheaderrow[j];
}
else
{
ostringstream strm;
strm << aheaderrow[length - 1] << j - length + 2;
string str = strm.str();
headerrow[j] = new char[str.length() + 1];
strcpy(headerrow[j], str.c_str());
headerrow[j] = strm.str();
}
}
char **headercolumn = NULL;
// headercolumn = new char *[rows + 1];
string *headercolumn = nullptr;
// headercolumn = new string[rows + 1];
// for (unsigned int i = 0; i < rows + 1; ++i)
// {
// ostringstream strm;
// strm << i + 1;
// string str = strm.str();
// headercolumn[i] = new char[str.length() + 1];
// strcpy(headercolumn[i], str.c_str());
// headercolumn[i] = strm.str();
// }
T **array;
array = new T *[rows];
for (unsigned int i = 0; i < rows; ++i)
array[i] = new T[columns];
vector<vector<T>> aarray(rows, vector<T>(columns));
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)
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;
}
// if (headercolumn != NULL)
// if (headercolumn != nullptr)
// {
// for (unsigned int i = 0; i < rows + 1; ++i)
// delete[] headercolumn[i];
// 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
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[])
(T) = {afunction};
std::function<T(T)> afunctions[] = {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);
}