Real input to FFTW - c++

When I use FFTW, specifically the plan creation function fftw_plan_dft_r2c_1d(), for purely real input, the only "planner flag" (FFTW's terminology) which works is FFTW_ESTIMATE. Any of the others which I try, viz., FFTW_EXHAUSTIVE, FFTW_MEASURE, and FFTW_PATIENT, all generate an output file with all zeros.
I have tried changing the number of input data items from powers of 2 to otherwise. That makes no difference.
Scilab uses FFTW for its fft() and thus I am able to compare the output from my C++ program with the output from Scilab for the same input data file. When I use FFTW_ESTIMATE the two outputs match.
I have read the FFTW documentation. I cannot determine why the other planner flags do not work.
I am interested in using the FFTW_MEASURE planner flag since once the plan is formulated, I will want to use it repeatedly.
Below is my code. I have not included the fftw3.h file as I have not made any changes to it.
#pragma once
// FFT_05.h
//#include <array>
#include <cmath>
#include <complex>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "fftw3.h"
#define M_PI 3.14159265358979323846
// FFT_05_c.cpp
#include "FFT_05.h"
//*****************************************************************************
int32_t main(int argc, char* argv[]) {
std::fstream data_File;
std::string directory = "C:/Documents/Visual Studio 2022/Projects/";
directory += "FFT_05/Scilab programs/02/";
std::string file_Name = "Time_domain_input.txt";
data_File.open(directory + file_Name, std::ios_base::in | std::ios_base::binary);
double input_Value = 0.0;
int data_Count = 0;
if (data_File.is_open()) {
while (!data_File.eof()) {
data_File >> input_Value;
data_Count++;
}
}
std::cout << data_Count << std::endl;
data_File.seekg(0, std::ios_base::beg);
double* in;
fftw_complex* out;
fftw_plan p;
in = (double*)fftw_malloc(sizeof(double) * data_Count);
int data_Count_Out = (data_Count / 2) + 1;
out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * data_Count_Out);
int i = 0;
while (!data_File.eof()) {
data_File >> input_Value;
in[i++] = input_Value;
}
data_File.close();
//for (int i = 0; i < data_Count; i++) {
// //std::cout << in[i][0] << ", " << in[i][1] << std::endl;
// std::cout << (i + 1) << ". " << in[i] << std::endl;
//}
//std::cout << "\n\n";
// FFTW procedure
p = fftw_plan_dft_r2c_1d(data_Count, in, out, FFTW_ESTIMATE);
if (!p) {
std::cout << "FFTW plan is NULL\n";
exit(1);
}
fftw_execute(p);
fftw_destroy_plan(p);
std::fstream FFT_Data_File;
FFT_Data_File.open(directory + "frequency_Domain_File_Name_c.txt",
std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
for (int i = 0; i < (data_Count_Out - 1); i++) {
FFT_Data_File << out[i][0] << " " << out[i][1] << std::endl;
}
FFT_Data_File << out[(data_Count_Out - 1)][0] << " " << out[(data_Count_Out - 1)][1];
FFT_Data_File.close();
fftw_free(in);
fftw_free(out);
}

Related

PageRank algorithm Runtime Errors on FPGA and GPUs using sycl

I'm having troubles doing experiments on fpga and gpu using sycl.
I'm working online with intel devcloud and I get these 2 runtime errors when performing the executables:
On FPGA:
terminate called after throwing an instance of 'sycl::_V1::runtime_error'
what(): Invalid device program image: size is zero -30 (PI_ERROR_INVALID_VALUE)
on GPU:
terminate called after throwing an instance of 'sycl::_V1::runtime_error'
what(): Native API failed. Native API returns: -1 (PI_ERROR_DEVICE_NOT_FOUND) -1 (PI_ERROR_DEVICE_NOT_FOUND)
Here's the main Codes:
#include <sycl/sycl.hpp>
#include <sycl/ext/intel/fpga_extensions.hpp>
// #include <oneapi/mkl/blas.hpp>
#include <cmath>
#include <chrono>
#include <iostream>
#include <vector>
#include <cmath>
#include "guideline.h"
#include "print_vector.h"
#include "print_time.h"
#include "read_graph.h"
#include "flatVector.h"
using namespace sycl;
int main(int argc, char* argv[]){
// Check Command Line
if(argc < 6){
// NOT ENOUGH PARAMS BY COMMAND LINE -> PROGRAM HALTS
guideline();
}
else{
// Command Line parsing
int device_selected = atoi(argv[1]);
std::string csv_path = argv[2];
double threshold = atof(argv[3]);
double damping = atof(argv[4]);
int verbose;
try{verbose = atoi(argv[5]);}
catch (exception const& e) {verbose = 0;}
device d = device(default_selector());
// Queue
queue q(d);
std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n"; // print del device
// Reading and setup Time Calculation
auto start_setup = std::chrono::steady_clock::now();
// Graph Retrieval by csv file
std::vector<std::vector<int>> graph = Read_graph(csv_path);/*Sparse Matrix Representation with the description of each Edge of the Graph*/
std::vector<int> flatGraph = flatten<int>(graph);
// Calculation of the # Nodes
int numNodes = countNodes(graph);
// Calculation of the Degree of each node
std::vector<int> degreesNodes = getDegrees(graph, numNodes+1);
auto end_setup = std::chrono::steady_clock::now();
// Setup Execution Time print
std::cout << "TIME FOR SETUP" << "\n";
print_time(start_setup, end_setup);
// Check Print
//printVector<int>(degreesNodes);
//Creation of Initial and Final Ranks' vectors of PageRank [R(t); R(t+1)]
std::vector<double> ranks_t(numNodes, (double)(1.0/ (double)(numNodes)));
std::vector<double> ranks_t_plus_one(numNodes, 0.0);
std::vector<double> ranksDifferences(numNodes, 0.0);
// PageRank Execution Time calculation
auto start = std::chrono::steady_clock::now();
buffer<int> bufferEdges(flatGraph.data(),flatGraph.size());
buffer<double> bufferRanks(ranks_t.data(),ranks_t.size());
buffer<int> bufferDegrees(degreesNodes.data(),degreesNodes.size());
buffer<double> bufferRanksNext(ranks_t_plus_one.data(),ranks_t_plus_one.size());
buffer<double> bufferRanksDifferences(ranksDifferences.data(),ranksDifferences.size());
double distance = threshold + 1;
int graph_size = flatGraph.size();
int T = 1;
while (distance > threshold) {
q.submit([&](handler &h){
accessor Edges(bufferEdges,h,read_only);
accessor Ranks(bufferRanks,h,read_only);
accessor Degrees(bufferDegrees,h,read_only);
accessor RanksNext(bufferRanksNext,h,write_only);
accessor RanksDifferences(bufferRanksDifferences,h,write_only);
h.parallel_for(range<1>(numNodes),[=] (id<1> i){
RanksNext[i] = (1.0 - damping) / numNodes;
int index_node_i;
int index_node_j;
for (int j = 0; j<graph_size;j+=2) {
index_node_i = j;
index_node_j = j + 1;
if (Edges[index_node_j] == i) {
RanksNext[i] += damping * Ranks[Edges[index_node_i]] / Degrees[Edges[index_node_i]];
}
}
RanksDifferences[i] = (RanksNext[i] - Ranks[i]) * (RanksNext[i] - Ranks[i]);
});
}).wait();
distance = 0;
for (int i = 0; i < numNodes; i++) {
distance += ranksDifferences[i];
ranks_t[i] = ranks_t_plus_one[i];
ranks_t_plus_one[i] = 0.0;
}
distance = sqrt(distance);
std::cout<< "Time:\t" << T << "\tEuclidian Distance:\t" << distance << std::endl;
T++;
}
auto end = std::chrono::steady_clock::now();
// PageRank Results Printing
if(verbose == 1){
for(int i = 0;i<ranks_t.size();i++){
std::cout<<"Final Vector" << i<< "-th component:\t"<<ranks_t[i]<<std::endl;
}
}
std::cout<<std::endl<<std::endl<<std::endl;
std::cout<<"Final Norm:\t"<<distance<<std::endl;
// PageRank Execution Time Printing
std::cout << "TIME FOR PAGERANK" << "\n";
print_time(start, end);
}
return 0;
}
flatVector.h
#include <iostream>
#include <vector>
template<typename T>
std::vector<T> flatten(const std::vector<std::vector<T>>& nestedVector) {
std::vector<T> flatVector;
for (const auto& subVector : nestedVector) {
for (const auto& element : subVector) {
flatVector.push_back(element);
}
}
return flatVector;
}
guideline.h
#include <iostream>
void guideline(){
std::cout<<"Not enough input parameters!\n\n";
std::cout<<"Usage guide:\n\n";
std::cout<<"First parameter:\tDevice code (as int number)\n";
std::cout<<"\t\t1: CPU\n";
std::cout<<"\t\t2: GPU\n";
std::cout<<"\t\t3: FPGA\n";
std::cout<<"Second parameter:\tCsv path of the dataset\n";
std::cout<<"Available Ones:\n\n";
std::cout<<"\t\t\"datasets/cit-Patents.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/soc-LiveJournal1.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/twitter-2010.csv\""<<std::endl;
std::cout<<"\t\t\"datasets/web-uk-2005-all.csv\""<<std::endl;
std::cout<<"Third parameter:\tThreshold (double value)\n";
std::cout<<"Fourth parameter:\tDamping (double value)\n";
std::cout<<"Fifth parameter:\tVerbose (int value)\n";
std::cout<<"Prints all the ranks of each node\n";
std::cout<<"Watch out! The print is huge\n";
}
printTime.h
#include <iostream>
#include <chrono>
void print_time(std::chrono::time_point<std::chrono::steady_clock> start, std::chrono::time_point<std::chrono::steady_clock> end){
std::cout << "Elapsed time in nanoseconds: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << " ns" << std::endl;
std::cout << "Elapsed time in microseconds: " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << " µs" << std::endl;
std::cout << "Elapsed time in milliseconds: " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;
std::cout << "Elapsed time in seconds: " << std::chrono::duration_cast<std::chrono::seconds>(end - start).count() << " sec" << std::endl;
}
printVector.h
#include <iostream>
#include <vector>
template <typename T>
void printVector(std::vector<T> vector_like_var){
for(int i = 0; i < vector_like_var.size(); i++){
std::cout<< "element " <<i+1 << "of vector:\t" << vector_like_var[i] <<std::endl;
}
}
read_graph.h
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
// #include "print_vector.h"
std::vector<int> getDegrees(const std::vector<std::vector<int>> &graph, int numNodes) {
std::vector<int> degrees(numNodes);
for (auto &edge : graph) {
++degrees[edge[0]];
++degrees[edge[1]];
}
return degrees;
}
std::vector<std::vector<int>> Read_graph(std::string file_name){
// Apertura del file
std::ifstream file(file_name);
if (!file.is_open()) {
std::cerr << "Impossibile aprire il file" << std::endl;
return {};
}
// Lettura del file riga per riga
std::string line;
std::vector<std::vector<int>> graph;
while (getline(file, line)) {
std::stringstream ss(line);
std::string cell;
std::vector<int> edge;
while (getline(ss, cell, ',')) {
edge.push_back(stoi(cell));
}
graph.push_back(edge);
}
file.close();
return graph;
}
int countNodes(std::vector<std::vector<int>> graph){
int numNodes = 0;
for(auto &i : graph){
for(auto &j : i){
numNodes = std::max(numNodes, j);
}
}
return numNodes;
}
I know that it runs on CPU, because I've done experiments and it prints out the ranks.
I tried executing on different devices the experiment, for example by using gen 9 GPUs of intel, but it was no use.

std::stof() rounds numbers, how to avoid

Im trying to get a float value from a file.txt into a string. When I output that value with std::stof(str) it gets rounded. Example, in the text file there's "101471.71", whet i use the std::stof(str) it returns "101472", how to I avoid this?
Here's a part of that code (some parts are in spanish, sorry :p):
double CaptureLine(std::string filepath, int fileline, int linesize)
{
std::fstream file;
std::string n_str, num_n;
int current_line = 0, n_size, filesize = FileSize(filepath);
char ch_n;
double n_float = 0.0;
int n_line = filesize - fileline;
file.open("registros.txt");
if (file.is_open()) {
while (!file.eof()) {
current_line++;
std::getline(file, n_str);
if (current_line == n_line) break;
}
if (current_line < n_line) {
std::cout << "Error" << std::endl;
return 1;
}
file.close();
}
n_size = n_str.length();
for (int i = linesize; i < n_size; i++) {
ch_n = n_str.at(i);
num_n.push_back(ch_n);
}
std::cout << ">>" << num_n << "<<\n";
n_float = std::stof(num_n); //Here's the error
return n_float;
}
The issue probably isn't with std::stof, but is probably with the default precision of 6 in std::cout. You can use std::setprecision to increase that precision and capture all of your digits.
Here's a program that demonstrates:
#include <iostream>
#include <iomanip>
#include <string>
int main() {
std::cout << 101471.71f << "\n";
std::cout << std::stof("101471.71") << "\n";
std::cout << std::setprecision(8) << 101471.71f << "\n";
std::cout << std::stof("101471.71") << "\n";
return 0;
}
Outputs:
101472
101472
101471.71
101471.71
Be aware that std::setprecision sticks to the std::cout stream after it's called. Notice how the above example calls it exactly once but its effect sticks around.

C++ accessing vector of vector got segmentation fault

I created a vector of vector (10*10000) and try to access this vector through member function. but I got a segmentation fault. I don't know what's wrong here...
Here is Simple.h
class Simple
{
private:
std::vector<double> data_row;
std::vector<std::vector<double> > data;
public:
Simple():data_row(10000), data(10, data_row){};
/*initialize data vector*/
int getSampleCounts(std::istream &File);
/*return number of packet samples in this file*/
Result getModel(std::istream &File);
/*return average and variance of simple delta time*/
void splitData (std::istream &File, const int & sample_in_fold);
};
#endif /* SIMPLE_H */
here is Simple.cpp
void Simple::splitData(std::istream& File, const int & sample_in_fold) {
double value = 0.0;
bool isFailed = true;
int label = 0;
while (File >> value) {
// for each value, generate a label
srand(time(NULL));
label = rand() % 10; // generate label between 0 to 9
while (isFailed) {
// segmentation fault in the next line!
std::cout << "current data size is: " << this->data.size() <<endl;
std::vector<double>::size_type sz = this->data[label].size();
if (sz <= sample_in_fold) {
std::cout << "current size is " << sz << "< samples in fold: " << sample_in_fold << endl;
this->data[label].push_back(value);
std::cout << "push_back succeed!" << endl;
isFailed = false;
} else {
std::cout << "label " << label << "if full. Next label. \n";
srand(time(NULL));
label = rand() % 10;
sz = this->data[label].size();
}
}
}
}
and I'm attaching the main file here.
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // for system())
#include <sys/types.h>
#include <dirent.h>
#include <vector>
#include <limits.h> // for PATH_MAX
#include "Complex.h"
#include "Result.h"
#include "Simple.h"
#include <math.h>
using namespace std;
int main(int argc, char ** argv) {
struct dirent *pDirent;
DIR *pDir;
std::string line;
// check for args
if (argc == 1) {
printf("Usage: ./main + folder name. \n");
return 1;
}
pDir = opendir(argv[1]);
if (pDir == NULL) {
printf("Cannot open directory '%s' \n", argv[1]);
return 1;
}
// readdir returns a pointer to the next direcctory entry dirent structure
while ((pDirent = readdir(pDir)) != NULL) {
// get file name and absolute path
char *name = pDirent->d_name;
char buf[PATH_MAX + 1];
realpath(name, buf);
// std::cout << "Current file is: " << (pDirent->d_name) << endl;
if (has_suffix(pDirent->d_name, ".txt")) {
printf("[%s]\n", pDirent->d_name);
//printf("absolute path is %s. \n", buf);
ifstream infile;
// open file with absolute path
infile.open(buf, ios::in);
if (!infile) {
cerr << "Can't open input file " << buf << endl;
exit(1);
}
//processing for simple pattern
if (has_suffix(name, "testfile.txt")) {
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
Result simplerst = simple_obj->getModel(infile);
std::cout << "Number of delta time is " << number << endl;
infile.clear();
infile.seekg(0);
write_to_file(pDirent->d_name, simplerst);
// divide data into k = 10 folds, get number of data in each fold
int sample_in_fold = floor(number / 10);
std::cout << sample_in_fold << std::endl;
simple_obj->splitData(infile, sample_in_fold);
}
} else {
// printf("This is not a txt file. Continue\n");
}
}
closedir(pDir);
return 0;
}
And here is a sample testfile.txt. I only copied part of the original file, for illustration.
10.145906000
10.151063000
10.131083000
10.143461000
10.131745000
10.151285000
10.147493000
10.123198000
10.144975000
10.144484000
10.138129000
10.131634000
10.144311000
10.157710000
10.138047000
10.122754000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
10.154170000
10.139574000
10.140207000
10.149151000
10.164629000
10.106818000
10.142431000
10.137675000
10.204973000
10.140399000
10.142194000
10.138388000
10.141669000
10.138056000
10.138679000
10.141415000
Here is Result.h
#ifndef RESULT_H
#define RESULT_H
typedef struct Result {
double average;
double sigma;
}Result;
and getModel function in Simple.cpp:
Result Simple::getModel(std::istream &File) {
double value = 0.0;
double average = 0.0;
double sum = 0.0;
double counter = 0.0;
double sumsqr = 0.0;
double var = 0.0;
double sigma = 0.0;
while (File >> value) {
++counter;
sum += value;
sumsqr += value * value;
}
average = sum / counter;
var = sumsqr / counter - average * average; //E(x^2) - (E(x))^2
sigma = sqrt(var);
std::cout << "average is " << average << std::endl;
std::cout << "std deviation is " << sigma << std::endl;
File.clear();
File.seekg(0);
Result result = {average, sigma};
return result;
}
One issue right away:
Simple* simple_obj;
int number = simple_obj->getSampleCounts(infile);
simple_obj is an uninitialized pointer, thus your program exhibits undefined behavior at this point.
Why use a pointer anyway? You could have simply done this to avoid the issue:
Simple simple_obj;
simple_obj.getSampleCounts(infile);
Also, this line may not be an issue, but I'll mention it anyway:
Result simplerst = simple_obj->getModel(infile);
We already know that in your original code, simple_obj is bogus, but that's not the issue here. If Result is an object, and that object does not have correct copy semantics, then that assignment will also cause undefined behavior.
You've got a couple of uses of endl without specifying std::endl (they're not the same thing - you always have to type the std:: ). Is endl silently referring to another variable somewhere else?

fixed amount of digits on creating .txt file

I need to create file with specific file name format (on windows). the format is:
Name_nodeNum_frequency.txt
nodeNum is int and frequency is float.
those two variables should be written with fixed digits:
if nodeNum is 8 --> 008
if frequency is 4.88421 --> 4.884
this is the function:
create_file(int nodeNum, double frequency)
{
char buffer [50];
//convert int to string
itoa(nodeNum, buffer, 10);
string sNodeNum = string(buffer);
//not sure about the double
//tried to_string but I got:
// more than instance of overloaded function matches the argument list
string fileName = ("Name_" + sNodeNum + "_" + sfreq + "MHZ");
FILE* pFile = OpenFile(fileName);
}
I tried to use %d, but it seems like I should not do that:
string fileName = ("Delay_" + "%3d" + "_" + sfreq + "MHZ" , sNodeNum);
I will be happy for some guidance.
thanks!
You seem to be mixing C and C++ here. A simple way to do this in C would be:
#include <stdio.h>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
char filename[50];
sprintf(filename, "Delay_%03d_%.3fMHZ.txt", sNodeNum, sfreq);
FILE* pFile = fopen(filename, "w");
return 0;
}
If on the other hand, if you want to use C++, you should make a few changes:
#include <iomanip>
#include <fstream>
#include <sstream>
#include <iostream>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
std::ostringstream ss;
ss << "Delay_" << std::setfill('0') << std::setw(3) << sNodeNum
<< "_" << std::setprecision(4) << sfreq << "MHZ.txt";
std::string filename(ss.str());
std::ofstream fout(filename.c_str());
return 0;
}
Each of these two approaches opens a file for writing, with the name Delay_008_4.884MHZ.txt.
Live demo link
#include <string>
#include <iomanip>
#include <iostream>
int nodeNum = 8;
float frequency = 4.88421f;
std::ostream& out = std::cout; // put your std::ofstream file or std::ostringstream
std::ios::fmtflags flags = out.flags();
out.width(3);
out.fill('0');
out.setf(std::ios::right, std::ios::adjustfield);
out << nodeNum << std::endl;
flags = out.flags(flags);
out.precision(3);
out.setf(std::ios::fixed, std::ios::floatfield);
out << frequency;
out.flags(flags);
Or even simpler:
out << std::setw(3) << std::setfill('0') << std::right << nodeNum << std::endl;
out << std::setprecision(3) << std::fixed << frequency;
Output:
008
4.884

How to display a progress indicator in pure C/C++ (cout/printf)?

I'm writing a console program in C++ to download a large file. I know the file size, and I start a work thread to download it. I want to show a progress indicator to make it look cooler.
How can I display different strings at different times, but at the same position, in cout or printf?
With a fixed width of your output, use something like the following:
float progress = 0.0;
while (progress < 1.0) {
int barWidth = 70;
std::cout << "[";
int pos = barWidth * progress;
for (int i = 0; i < barWidth; ++i) {
if (i < pos) std::cout << "=";
else if (i == pos) std::cout << ">";
else std::cout << " ";
}
std::cout << "] " << int(progress * 100.0) << " %\r";
std::cout.flush();
progress += 0.16; // for demonstration only
}
std::cout << std::endl;
http://ideone.com/Yg8NKj
[> ] 0 %
[===========> ] 15 %
[======================> ] 31 %
[=================================> ] 47 %
[============================================> ] 63 %
[========================================================> ] 80 %
[===================================================================> ] 96 %
Note that this output is shown one line below each other, but in a terminal emulator (I think also in Windows command line) it will be printed on the same line.
At the very end, don't forget to print a newline before printing more stuff.
If you want to remove the bar at the end, you have to overwrite it with spaces, to print something shorter like for example "Done.".
Also, the same can of course be done using printf in C; adapting the code above should be straight-forward.
You can use a "carriage return" (\r) without a line-feed (\n), and hope your console does the right thing.
For a C solution with an adjustable progress bar width, you can use the following:
#define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
#define PBWIDTH 60
void printProgress(double percentage) {
int val = (int) (percentage * 100);
int lpad = (int) (percentage * PBWIDTH);
int rpad = PBWIDTH - lpad;
printf("\r%3d%% [%.*s%*s]", val, lpad, PBSTR, rpad, "");
fflush(stdout);
}
It will output something like this:
75% [|||||||||||||||||||||||||||||||||||||||||| ]
Take a look at boost progress_display
http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display
I think it may do what you need and I believe it is a header only library so nothing to link
You can print a carriage return character (\r) to move the output "cursor" back to the beginning of the current line.
For a more sophisticated approach, take a look at something like ncurses (an API for console text-based interfaces).
I know I am a bit late in answering this question, but I made a simple class that does exactly what you want. (keep in mind that I wrote using namespace std; before this.):
class pBar {
public:
void update(double newProgress) {
currentProgress += newProgress;
amountOfFiller = (int)((currentProgress / neededProgress)*(double)pBarLength);
}
void print() {
currUpdateVal %= pBarUpdater.length();
cout << "\r" //Bring cursor to start of line
<< firstPartOfpBar; //Print out first part of pBar
for (int a = 0; a < amountOfFiller; a++) { //Print out current progress
cout << pBarFiller;
}
cout << pBarUpdater[currUpdateVal];
for (int b = 0; b < pBarLength - amountOfFiller; b++) { //Print out spaces
cout << " ";
}
cout << lastPartOfpBar //Print out last part of progress bar
<< " (" << (int)(100*(currentProgress/neededProgress)) << "%)" //This just prints out the percent
<< flush;
currUpdateVal += 1;
}
std::string firstPartOfpBar = "[", //Change these at will (that is why I made them public)
lastPartOfpBar = "]",
pBarFiller = "|",
pBarUpdater = "/-\\|";
private:
int amountOfFiller,
pBarLength = 50, //I would recommend NOT changing this
currUpdateVal = 0; //Do not change
double currentProgress = 0, //Do not change
neededProgress = 100; //I would recommend NOT changing this
};
An example on how to use:
int main() {
//Setup:
pBar bar;
//Main loop:
for (int i = 0; i < 100; i++) { //This can be any loop, but I just made this as an example
//Update pBar:
bar.update(1); //How much new progress was added (only needed when new progress was added)
//Print pBar:
bar.print(); //This should be called more frequently than it is in this demo (you'll have to see what looks best for your program)
sleep(1);
}
cout << endl;
return 0;
}
Note: I made all of the classes' strings public so the bar's appearance can be easily changed.
Another way could be showing the "Dots" or any character you want .The below code will print progress indicator [sort of loading...]as dots every after 1 sec.
PS : I am using sleep here. Think twice if performance is concern.
#include<iostream>
using namespace std;
int main()
{
int count = 0;
cout << "Will load in 10 Sec " << endl << "Loading ";
for(count;count < 10; ++count){
cout << ". " ;
fflush(stdout);
sleep(1);
}
cout << endl << "Done" <<endl;
return 0;
}
Here is a simple one I made:
#include <iostream>
#include <thread>
#include <chrono>
#include <Windows.h>
using namespace std;
int main() {
// Changing text color (GetStdHandle(-11), colorcode)
SetConsoleTextAttribute(GetStdHandle(-11), 14);
int barl = 20;
cout << "[";
for (int i = 0; i < barl; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << ":";
}
cout << "]";
// Reset color
SetConsoleTextAttribute(GetStdHandle(-11), 7);
}
May be this code will helps you -
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <cmath>
using namespace std;
void show_progress_bar(int time, const std::string &message, char symbol)
{
std::string progress_bar;
const double progress_level = 1.42;
std::cout << message << "\n\n";
for (double percentage = 0; percentage <= 100; percentage += progress_level)
{
progress_bar.insert(0, 1, symbol);
std::cout << "\r [" << std::ceil(percentage) << '%' << "] " << progress_bar;
std::this_thread::sleep_for(std::chrono::milliseconds(time));
}
std::cout << "\n\n";
}
int main()
{
show_progress_bar(100, "progress" , '#');
}
Simple, you can just use string's fill constructor:
#include <iostream> //for `cout`
#include <string> //for the constructor
#include <iomanip> //for `setprecision`
using namespace std;
int main()
{
const int cTotalLength = 10;
float lProgress = 0.3;
cout <<
"\r[" << //'\r' aka carriage return should move printer's cursor back at the beginning of the current line
string(cTotalLength * lProgress, 'X') << //printing filled part
string(cTotalLength * (1 - lProgress), '-') << //printing empty part
"] " <<
setprecision(3) << 100 * lProgress << "%"; //printing percentage
return 0;
}
Which would print:
[XXX-------] 30%
If you need it in pure C
and you would like to be able to customize the size and filler characters at runtime:
#include <stdio.h> //for `printf`
#include <stdlib.h> //for `malloc`
#include <string.h> //for `memset`
int main()
{
const int cTotalLength = 10;
char* lBuffer = malloc((cTotalLength + 1) * sizeof *lBuffer); //array to fit 10 chars + '\0'
lBuffer[cTotalLength] = '\0'; //terminating it
float lProgress = 0.3;
int lFilledLength = lProgress * cTotalLength;
memset(lBuffer, 'X', lFilledLength); //filling filled part
memset(lBuffer + lFilledLength, '-', cTotalLength - lFilledLength); //filling empty part
printf("\r[%s] %.1f%%", lBuffer, lProgress * 100); //same princip as with the CPP method
//or you can combine it to a single line if you want to flex ;)
//printf("\r[%s] %.1f%%", (char*)memset(memset(lBuffer, 'X', lFullLength) + lFullLength, '-', cTotalLength - lFullLength) - lFullLength, lProgress * 100);
free(lBuffer);
return 0;
}
but if you don't need to customize it at runtime:
#include <stdio.h> //for `printf`
#include <stddef.h> //for `size_t`
int main()
{
const char cFilled[] = "XXXXXXXXXX";
const char cEmpty[] = "----------";
float lProgress = 0.3;
size_t lFilledStart = (sizeof cFilled - 1) * (1 - lProgress);
size_t lEmptyStart = (sizeof cFilled - 1) * lProgress;
printf("\r[%s%s] %.1f%%",
cFilled + lFilledStart, //Array of Xs starting at `cTotalLength * (1 - lProgress)` (`cTotalLength * lProgress` characters remaining to EOS)
cEmpty + lEmptyStart, //Array of -s starting at `cTotalLength * lProgress`...
lProgress * 100 //Percentage
);
return 0;
}
I needed to create a progress bar and some of the answers here would cause the bar to blink or display the percentage short of 100% when done. Here is a version that has no loop other than one that simulates cpu work, it only prints when the next progress unit is incremented.
#include <iostream>
#include <iomanip> // for setw, setprecision, setfill
#include <chrono>
#include <thread> // simulate work on cpu
int main()
{
int batch_size = 4000;
int num_bars = 50;
int batch_per_bar = batch_size / num_bars;
int progress = 0;
for (int i = 0; i < batch_size; i++) {
if (i % batch_per_bar == 0) {
std::cout << std::setprecision(3) <<
// fill bar with = up to current progress
'[' << std::setfill('=') << std::setw(progress) << '>'
// fill the rest of the bar with spaces
<< std::setfill(' ') << std::setw(num_bars - progress + 1)
// display bar percentage, \r brings it back to the beginning
<< ']' << std::setw(3) << ((i + 1) * 100 / batch_size) << '%'
<< "\r";
progress++;
}
// simulate work
std::this_thread::sleep_for(std::chrono::nanoseconds(1000000));
}
}