Processing dark text images for tesseract ocr - ocr

I have noticed that whenever I use dark background images for tesseract I am getting a segmentation fault. I was trying to extract symbols using this code
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>
#include <iostream>
#include <map>
#include <bits/stdc++.h>
using namespace std;
int main()
{
char *outText;
map<pair<char*,char*>,float> matrix;
set<char> allChars;
tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
// Initialize tesseract-ocr with English, without specifying tessdata path
if (api->Init(NULL, "eng")) {
fprintf(stderr, "Could not initialize tesseract.\n");
exit(1);
}
int a[256][256];
for(int i=0;i<256;i++){
for(int j=0;j<256;j++){
a[i][j]=0;
}
}
// Open input image with leptonica library
string images[] = {List of images};
for (int ii=0;ii<7;ii++){
Pix *image = pixRead((const char*) images[ii].c_str());
cout << images[ii] << endl;
api->Init(NULL, "eng");
api->SetImage(image);
string valid_set = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890~`!##$%^&*()_-+=,./<>/:;'[]{}|";
api->SetVariable("tessedit_char_whitelist", valid_set.c_str());
api->SetVariable("save_blob_choices", "T");
//api->SetRectangle(37, 128,648, 523);
//api->SetRectangle(30, 86, 590, 100);
//api->SetRectangle(30,100,430,30);
api->Recognize(NULL);
tesseract::ResultIterator* ri = api->GetIterator();
tesseract::PageIteratorLevel level = tesseract::RIL_SYMBOL;
if(ri != 0) {
do {
const char* symbol = ri->GetUTF8Text(level);
//cout << symbol << endl;
if(ri!=0){
float conf = ri->Confidence(level);
}
//cout << "err" << endl;
if(symbol != 0) {
//printf("symbol %s, conf: %f", symbol, conf);
bool indent = false;
tesseract::ChoiceIterator ci(*ri);
do {
const char* choice = ci.GetUTF8Text();
if (indent) //printf("\t\t ");
// printf("\t- ");
//cout << symbol<<" Look up "<<choice << endl;
matrix[make_pair(strdup(symbol), strdup(choice))]=ci.Confidence();
//printf("%s conf: %f\n", choice, ci.Confidence());
indent = true;
} while(ci.Next());
}
//printf("---------------------------------------------\n");
delete[] symbol;
} while((ri->Next(level)));
}
int count = 0;
for(map<pair<char*,char*>,float>::iterator it = matrix.begin();it!=matrix.end();it++){
allChars.insert((strdup)(it->first.first)[0]);
allChars.insert((strdup)(it->first.second)[0]);
//cout<<it->first.first<<" "<<it->first.second<<endl;
//cout << (strdup)(it->first.first)[0]<<" "<<(strdup)(it->first.second)[0]<<endl;
a[(strdup)(it->first.first)[0]][(strdup)(it->first.second)[0]]+=it->second;
count++;
}
// cout << count << endl;
for(set<char>::iterator it = allChars.begin();it!=allChars.end();it++){
//cout << *it << endl;
}
for(int i=0;i<256;i++){
for(int j=0;j<256;j++){
if(a[i][j]!=0){
///cout << i << " " <<j<<endl;
//cout << a[i][j]<<endl;
}
//cout << a[i][j] << endl;
}
}
api->End();
pixDestroy(&image);
}
return 0;
}`
Specifically in the code where
float conf = ri->Confidence(level);
So what can be the solution to this problem? Should we train with more dark images?
Edit:
Sample Image

Related

Parse elements from json array using boost

here is the json I want to parse:
{"jsonrpc":"2.0","method":"subscription","params":{"channel":"book.BTC-PERPETUAL.raw","data":{"type":"change","timestamp":1635513739435,"prev_change_id":6807100702,"instrument_name":"BTC-PERPETUAL","change_id":6807100703,"bids":[["new",60772.0,50.0], "demo"],"asks":[]}}}
and here is my code to get the values from a child:
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
std::cout << "\njsonrpc: " << pt.get<std::string>("jsonrpc") << std::endl;
std::cout << "\nmethod: " << pt.get<std::string>("method") << std::endl;
std::cout << "\nparams: " << pt.get<std::string>("params") << std::endl;
std::cout << "\nparams.channel: " << pt.get<std::string>("params.channel") << std::endl;
std::cout << "\nparams.data: " << pt.get<std::string>("params.data") << std::endl;
std::cout << "\nparams.data.timestamp: " << pt.get<std::string>("params.data.timestamp") << std::endl;
std::cout << "\nparams.data.instrument_name: " << pt.get<std::string>("params.data.instrument_name") << std::endl;
but when I tried to parse the array values like ("params.data.bids") it return nothing
I need help in parsing an array
You should use a JSON Library:
Live On Compiler Explorer
#include <boost/json.hpp>
#include <boost/json/src.hpp> // header-only for Compiler Explorer
#include <iostream>
namespace json = boost::json;
int main() {
auto req = json::parse(R"({
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "book.BTC-PERPETUAL.raw",
"data": {
"type": "change",
"timestamp": 1635513739435,
"prev_change_id": 6807100702,
"instrument_name": "BTC-PERPETUAL",
"change_id": 6807100703,
"bids": [
["new", 60772.0, 50.0], "demo"],
"asks": []
}
}
})") .as_object();
auto& params = req["params"].as_object();
auto& data = params["data"].as_object();
std::cout << "jsonrpc: " << req["jsonrpc"].as_string() << "\n";
std::cout << "methdo: " << req["method"].as_string() << "\n";
std::cout << "params.channel: " << params["channel"].as_string() << "\n";
std::cout << "params.data: " << params["data"] << "\n";
std::cout << "params.data.timestamp: " << data["timestamp"] << "\n";
std::cout << "params.data.instrument_name: " << data["instrument_name"] << "\n";
}
Prints
jsonrpc: "2.0"
methdo: "subscription"
params.channel: "book.BTC-PERPETUAL.raw"
params.data: {"type":"change","timestamp":1635513739435,"prev_change_id":6807100702,"instrument_name":"BTC-PERPETUAL","change_id":6807100703,"bids":[["new",6.0772E4,5E1],"demo"],"asks":[]}
params.data.timestamp: 1635513739435
params.data.instrument_name: "BTC-PERPETUAL"
bid: ["new",6.0772E4,5E1]
bid: "demo"
Adding the asks/bids:
for (auto& bid : data["bids"].as_array()) {
std::cout << "bid: " << bid << "\n";
}
for (auto& ask : data["asks"].as_array()) {
std::cout << "ask: " << ask << "\n";
}
Prints
bid: ["new",6.0772E4,5E1]
bid: "demo"
Alternative / Bonus
You can also use value_to conversion to your own types:
struct request {
std::string jsonrpc, method;
struct params_t {
std::string channel;
struct data_t {
std::string type;
size_t timestamp, prev_change_id, change_id;
std::string instrument_name;
std::vector<json::value> bids, asks;
} data;
} params;
};
See it Live
Or flattened:
struct request {
using values = std::vector<json::value>;
std::string jsonrpc, method, channel, type, instrument_name;
size_t timestamp, prev_change_id, change_id;
values bids, asks;
friend request tag_invoke(json::value_to_tag<request>, json::value const& v)
{
auto& params = v.at("params");
auto& data = params.at("data");
return request{
value_to<std::string>(v.at("jsonrpc")),
value_to<std::string>(v.at("method")),
value_to<std::string>(params.at("channel")),
value_to<std::string>(data.at("type")),
value_to<std::string>(data.at("instrument_name")),
value_to<size_t>(data.at("timestamp")),
value_to<size_t>(data.at("prev_change_id")),
value_to<size_t>(data.at("change_id")),
value_to<values>(data.at("bids")),
value_to<values>(data.at("asks")),
};
}
};
See it Live As Well
#include <boost/json.hpp>
#include <boost/json/src.hpp> // header-only for Compiler Explorer
#include <iostream>
namespace json = boost::json;
struct request {
using values = std::vector<json::value>;
std::string jsonrpc, method, channel, type, instrument_name;
size_t timestamp, prev_change_id, change_id;
values bids, asks;
friend request tag_invoke(json::value_to_tag<request>, json::value const& v)
{
auto& params = v.at("params");
auto& data = params.at("data");
return request{
value_to<std::string>(v.at("jsonrpc")),
value_to<std::string>(v.at("method")),
value_to<std::string>(params.at("channel")),
value_to<std::string>(data.at("type")),
value_to<std::string>(data.at("instrument_name")),
value_to<size_t>(data.at("timestamp")),
value_to<size_t>(data.at("prev_change_id")),
value_to<size_t>(data.at("change_id")),
value_to<values>(data.at("bids")),
value_to<values>(data.at("asks")),
};
}
};
int main() {
auto req = value_to<request>(json::parse(R"({
"jsonrpc": "2.0",
"method": "subscription",
"params": {
"channel": "book.BTC-PERPETUAL.raw",
"data": {
"type": "change",
"timestamp": 1635513739435,
"prev_change_id": 6807100702,
"instrument_name": "BTC-PERPETUAL",
"change_id": 6807100703,
"bids": [
["new", 60772.0, 50.0], "demo"],
"asks": []
}
}
})"));
std::cout << "jsonrpc: " << req.jsonrpc << "\n";
std::cout << "methdo: " << req.method << "\n";
std::cout << "params.channel: " << req.channel << "\n";
std::cout << "data.timestamp: " << req.timestamp << "\n";
std::cout << "data.instrument_name: " << req.instrument_name << "\n";
for (auto& bid : req.bids) std::cout << "bid: " << bid << "\n";
for (auto& ask : req.asks) std::cout << "ask: " << ask << "\n";
}

HashVerificationFilter: message hash or MAC not valid Error on modified GCM AE code

I am referring to sample code on Crypto++ wiki at CCM Mode. I have done few modifications for testing purposes and now it is throwing:
terminate called after throwing an instance of 'HashVerificationFilter::HashVerificationFailed'
what(): HashVerificationFilter: message hash or MAC not valid
Aborted (core dumped)
I have seen 'message hash or MAC not valid' exception after decryption. But I would like to pass byte array instead of string, so I think I have to use sizeof() operator instead of size(). The code is below.
When pass key and iv, sizeof function is giving their sizes as 8 instead 16 bytes.
Is the error because of AuthenticatedDecryptionFilter::DEFAULT_FLAGS?
Here is the code:
#include <iostream>
#include <cstdio>
//#include "libcryptoWrapperGCM.h"
using std::cout;
using std::endl;
using std::cerr;
#include <string>
#include <stdint.h>
using std::string;
#include "hex.h"
using CryptoPP::HexEncoder;
using CryptoPP::HexDecoder;
#include "osrng.h"
using CryptoPP::AutoSeededRandomPool;
#include "cryptlib.h"
using CryptoPP::BufferedTransformation;
using CryptoPP::AuthenticatedSymmetricCipher;
#include "filters.h"
using CryptoPP::Redirector;
using CryptoPP::StringSink;
using CryptoPP::StringSource;
using CryptoPP::AuthenticatedEncryptionFilter;
using CryptoPP::AuthenticatedDecryptionFilter;
#include "aes.h"
using CryptoPP::AES;
#include "gcm.h"
using CryptoPP::GCM;
#include "assert.h"
void GCM_Encode(byte key[], byte iv[], string pdata, string cipher, const int TAG_SIZE)
{
// Encrypted, with Tag
string encoded;
cout << "key size= " << sizeof(key) << endl;
cout << "IV size= " << sizeof(iv) << endl;
/*********************************\
\*********************************/
try
{
GCM< AES >::Encryption e;
e.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );
StringSource ss1( pdata, true,
new AuthenticatedEncryptionFilter( e,
new StringSink( cipher ), false, TAG_SIZE
) // AuthenticatedEncryptionFilter
); // StringSource
cout << "Encoded value: " << cipher << endl;
}
catch( CryptoPP::Exception& e )
{
cerr << e.what() << endl;
exit(1);
}
}
/*********************************\
\*********************************/
void GCM_Decode(byte key[], byte iv[], string cipher, string rpdata, const int TAG_SIZE)
{
try
{
GCM< AES >::Decryption d;
d.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );
AuthenticatedDecryptionFilter df( d,
new StringSink( rpdata ),
AuthenticatedDecryptionFilter::DEFAULT_FLAGS, TAG_SIZE
); // AuthenticatedDecryptionFilter
// The StringSource dtor will be called immediately
// after construction below. This will cause the
// destruction of objects it owns. To stop the
// behavior so we can get the decoding result from
// the DecryptionFilter, we must use a redirector
// or manually Put(...) into the filter without
// using a StringSource.
StringSource ss2( cipher, true,
new Redirector( df /*, PASS_EVERYTHING */ )
); // StringSource
// If the object does not throw, here's the only
// opportunity to check the data's integrity
if( true == df.GetLastResult() ) {
cout << "recovered text: " << rpdata << endl;
}
}
catch( CryptoPP::Exception& e )
{
cerr << e.what() << endl;
exit(1);
}
}
int main()
{
byte key[]= {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
byte iv[] = {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
string pdata = "Authenticated Encryption";
const int TAG_SIZE = 12;
string rpdata, cipher;
//void GCM_Encode(byte key[], byte iv[], string pdata, string cipher, const int TAG_SIZE)
GCM_Encode( key, iv, pdata, cipher, TAG_SIZE);
cout << "======INT MAIN======" << endl;
cout << "Encryption complete" << endl;
cout << "cipher= " << cipher << endl;
//void GCM_Decode(byte key[], byte iv[], string cipher, string rpdata, const int TAG_SIZE)
GCM_Decode( key, iv, cipher, rpdata, TAG_SIZE);
cout << "Decryption complete" << endl;
cout << "rpdata= " << rpdata << endl;
return 0;
}
GDB output is,
Encryption complete
cipher=
HashVerificationFilter: message hash or MAC not valid
[Inferior 1 (process 16632) exited with code 01]
Compilation command
g++ -g3 -O3 -fPIC GCM_Test2.cpp -o GCMTest3 -lcryptopp -pthread -lrt -lc
Include path added using,
export CPLUS_INCLUDE_PATH=/usr/local/include/cryptopp
No output on locate raise.c
Problem is that both functions GCM_Encode were interpreting wrong size of key and iv.
cout << "sizeof(key)= " << sizeof(key) << endl;
cout << "sizeof(iv)= " << sizeof(iv) << endl;
is 8 and not 16. So idea is to convert it to string and get its size using .size()
std::string key1( reinterpret_cast<char const*>(key), sizeof(key) )
std::string iv1( reinterpret_cast<char const*>(iv), sizeof(iv) )
But remember to provide original byte array to SetKeyWithIV function as it does not accept string as its argument.
e.SetKeyWithIV( key, key1.size(), iv, iv1.size() )

thrust remove copy unique by key

I'm a bit confused on the best way to do the following:
Say I have the following sorted key value pairs
(K:V) (0 : .5)(0 : .7)(0 : .9) (1 : .2) (1 : .6) (1 : .8)
and so on..
I want to remove copy the minimum value of each key so I'll have 2 results
minimum by key
(0 : .5)(1 : .2)
remaining
(0 : .7)(0 : .9)(1 : .6)(1 : .8)
thrust::unique_by_key_copy would appear to be able to give me the minimum by key since (K:V) is sorted. However I'm not sure how to remove those that are chosen from original to get the remaining.
Any thoughts or advice greatly appreciated
I'm sure there are a number of ways to do this.
One possible approach is to use thrust::adjacent_difference to create a "flag array".
Then use thrust::copy_if (the stencil version) using the flag array (as the stencil) to select first the elements you want in result 1, then the elements you want in result 2 (using the inverse of the flag array, logically).
Here's a worked example:
$ cat t671.cu
#include <thrust/copy.h>
#include <thrust/adjacent_difference.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/iterator/zip_iterator.h>
#include <iostream>
struct is_zero
{
__host__ __device__
bool operator()(const int s_val) const {
return (!s_val);}
};
struct is_not_zero
{
__host__ __device__
bool operator()(const int s_val) const {
return (s_val);}
};
int main(){
int keys[] = {0, 0, 0, 1, 1, 1 };
float vals[] = {0.5f, 0.7f, 0.9f, 0.2f, 0.6f, 0.8f };
int my_size = sizeof(keys)/sizeof(keys[0]);
thrust::host_vector<int> h_keys(keys, keys+my_size);
thrust::host_vector<float> h_vals(vals, vals+my_size);
thrust::device_vector<int> d_keys = h_keys;
thrust::device_vector<float> d_vals = h_vals;
thrust::device_vector<int> flags(my_size);
thrust::device_vector<int> d_keys1(my_size);
thrust::device_vector<float> d_vals1(my_size);
thrust::device_vector<int> d_keys2(my_size);
thrust::device_vector<float> d_vals2(my_size);
thrust::adjacent_difference(d_keys.begin(), d_keys.end(), flags.begin());
flags[0] = 1; // first element is always included
int len1 = thrust::copy_if(thrust::make_zip_iterator(thrust::make_tuple(d_keys.begin(), d_vals.begin())), thrust::make_zip_iterator(thrust::make_tuple(d_keys.end(), d_vals.end())), flags.begin(), thrust::make_zip_iterator(thrust::make_tuple(d_keys1.begin(), d_vals1.begin())), is_zero()) - thrust::make_zip_iterator(thrust::make_tuple(d_keys1.begin(), d_vals1.begin()));
int len2 = thrust::copy_if(thrust::make_zip_iterator(thrust::make_tuple(d_keys.begin(), d_vals.begin())), thrust::make_zip_iterator(thrust::make_tuple(d_keys.end(), d_vals.end())), flags.begin(), thrust::make_zip_iterator(thrust::make_tuple(d_keys2.begin(), d_vals2.begin())), is_not_zero()) - thrust::make_zip_iterator(thrust::make_tuple(d_keys2.begin(), d_vals2.begin()));
thrust::host_vector<int> h_keys1(len1);
thrust::host_vector<float> h_vals1(len1);
thrust::copy_n(d_keys1.begin(), len1, h_keys1.begin());
thrust::copy_n(d_vals1.begin(), len1, h_vals1.begin());
thrust::host_vector<int> h_keys2(len2);
thrust::host_vector<float> h_vals2(len2);
thrust::copy_n(d_keys2.begin(), len2, h_keys2.begin());
thrust::copy_n(d_vals2.begin(), len2, h_vals2.begin());
std::cout << std::endl << "Input keys:" << std::endl;
thrust::copy(h_keys.begin(), h_keys.end(), std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl << "Input values:" << std::endl;
thrust::copy(h_vals.begin(), h_vals.end(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl << "Output keys 1:" << std::endl;
thrust::copy(h_keys1.begin(), h_keys1.end(), std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl << "Output values 1:" << std::endl;
thrust::copy(h_vals1.begin(), h_vals1.end(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl << "Output keys 2:" << std::endl;
thrust::copy(h_keys2.begin(), h_keys2.end(), std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl << "Output values 2:" << std::endl;
thrust::copy(h_vals2.begin(), h_vals2.end(), std::ostream_iterator<float>(std::cout, ","));
std::cout << std::endl;
return 0;
}
$ nvcc -arch=sm_20 -o t671 t671.cu
$ ./t671
Input keys:
0,0,0,1,1,1,
Input values:
0.5,0.7,0.9,0.2,0.6,0.8,
Output keys 1:
0,0,1,1,
Output values 1:
0.7,0.9,0.6,0.8,
Output keys 2:
0,1,
Output values 2:
0.5,0.2,
$

Template class and related classes

I'm writing a code for a basic adt text editor with a doubly linked list ( for HW ) and Ive run across the error C2244:'Editor::run_command ' :unable to match function to existing declaration. I orignalyy declared the function in my Editor class but i have to use Template in order to use some of the variables from a template class if someon could help me out i'd appreicate it a ton
// assignment 2-2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <assert.h>
#include <string>
#include <windows.h>
#include <list>
using namespace std;
template <class Node_entry>
struct Node {
// data members
Node_entry entry;
Node<Node_entry> *next;
Node<Node_entry> *back;
// constructors
Node( );
~Node();
Node(Node_entry, Node<Node_entry> *link_back = NULL,
Node<Node_entry> *link_next = NULL);
};
template <class List_entry>
class List {
public:
// methods of the List ADT
List( );
int size( ) const;
bool full( ) const;
bool empty( ) const;
void clear( );
int count;
error_code traverse(void (*visit)(List_entry &));
error_code retrieve(int position, List_entry &x) const;
error_code remove(int position, List_entry &x);
error_code insert(int position, const List_entry &x);
protected:
// data members for a contiguous list implementation
List_entry entry[15];
mutable int current_position;
mutable Node<List_entry> *current;
void set_position(int position) const
{
if (current position <= position)
for ( ; current_position != position; current_position++)
current = current->next;
else
for ( ; current_position != position; current_position−−)
current = current->back;
}
};
template <class List_entry>
int List<List_entry>::size( ) const
{
return count;
};
template <class List_entry>
error_code List<List_entry>::insert(int position, const List_entry &x)
{
Node<List_entry> *new_node, *following, *preceding;
if (position < 0 || position > count) return range_error;
if (position == 0) {
if (count == 0) following = NULL;
else {
set_position(0);
following = current;
}
preceding = NULL;
}
else {
set_position(position − 1);
preceding = current;
following = preceding->next;
}
new_node = new Node<List_entry>(x, preceding, following);
if (new_node == NULL)
return overflow;
if (preceding != NULL)
preceding->next = new_node;
if(following != NULL) following->back = new_node;
current=new_node;
current_position=position;
count++;
return success;
};
class Editor: public List<string> {
public:
Editor(ifstream *file_in, ofstream *file_out);
bool get_command( );
void run_command( );
private:
ifstream *infile;
ofstream *outfile;
char user_command;
// auxiliary functions
error_code next_line( );
error_code previous_line( );
error_code goto_line( );
error_code insert_line( );
error_code substitute_line( );
error_code change_line( );
void write_file( );
void read_file( );
void find_string( );
};
int main(int argc, char *argv[ ])
{
if (argc != 3) {
cout << "Usage:\n\t edit inputfile outputfile" << endl;
exit (1);
}
ifstream file_in(argv[1]); // Declare and open the input stream.
if (file_in == 0) {
cout << "Cant open input file " << argv[1] << endl;
exit (1);
}
ofstream file_out(argv[2]); // Declare and open the output stream.
if (file_out == 0) {
cout << "Cant open output file " << argv[2] << endl;
exit (1);
}
Editor buffer( &file_in, &file_out);
while (buffer.get_command())
buffer.run_command();
}
Editor::Editor(ifstream *file_in, ofstream *file_out)
{
infile = file_in;
outfile = file_out;
};
bool Editor::get_command( )
{
if (current != NULL)
cout << current_position << " : "<< current->entry.c_str( ) << "\n??" << flush;
else
cout << "File is empty.\n??" << flush;
cin >> user_command; // ignores white space and gets command
user_command = tolower(user_command);
while(cin.get( ) != '\n')
; // ignore user’s enter key
if(user_command == 'q')
return false;
else
return true;
};
template <class List_entry>
void Editor::run_command( )
{
string temp_string;
cout << "Press h or ? for help or enter a valid command: ";
if(user_command=='b'){
if (empty( ))
cout << " Warning: empty buffer " << endl;
else
while (previous_line( ) == success);
goto point;;}
if(user_command=='c'){
if (empty( ))
cout << " Warning: Empty file" << endl;
else if (change_line( ) != success)
cout << " Error: Substitution failed " << endl;
goto point;;}
if(user_command=='d'){
if (remove(current_position, temp_string) != success)
cout << " Error: Deletion failed " << endl;
goto point;;}
if(user_command=='e'){
if(empty())
cout<<"Warning: Buffer is empty"<<endl
else
while (next_line( ) == success)
;
goto point;}
if(user_command=='f'){
if (empty( )) cout << " Warning: Empty file" << endl;
else
find_string( );
goto point;;}
if(user_command=='g'){
if (goto_line( ) != success)
cout << " Warning: No such line" << endl;
goto point;}
if(user_command=='?'||user_command=="h"){
cout << "Valid commands are: b(egin) c(hange) d(el) e(nd)"
<< endl
<< "f(ind) g(o) h(elp) i(nsert) l(ength) n(ext) p(rior) " << endl
<< "q(uit) r(ead) s(ubstitute) v(iew) w(rite) " << endl;}
if(user_command=='i'){
if (insert_line( ) != success)
cout << " Error: Insertion failed " << endl;
goto point;;}
if(user_command=='l'){
cout << "There are " << size( ) << " lines in the file." << endl;
if (!empty( ))
cout << "Current line length is "<< strlen((current->entry).c_str( )) << endl;
goto point;;}
if(user_command=='n'){
if (next_line( ) != success)
cout << " Warning: at end of buffer" << endl;
goto point;;}
if(user_command=='p'){
if (previous_line( ) != success)
cout << " Warning: at start of buffer" << endl;
goto point;;}
if(user_command=='r'){
read_file( );
goto point;;}
if(user_command=='s'){
if (substitute_line( ) != success)
cout << " Error: Substitution failed " << endl;
goto point;;}
if(user_command=='v'){
traverse(write);
goto point;;}
if(user_command=='w'){
if (empty( ))
cout << " Warning: Empty file" << endl;
else
write_file( );
goto point;}
point:
};
void Editor::read_file( )
{
bool proceed = true;
if (!empty( )) {
cout << "Buffer is not empty; the read will destroy it." << endl;
cout << " OK to proceed? " << endl;
cout<<"(Y)es or (N)0"<<endl;
char choice;
cin>>choice;
if (choice=='y') clear( );
}
int line_number = 0, terminal_char;
while (proceed) {
ifstream read_in;
read_in.open("hw.txt");
string in_string;
read_in>>in_string;
if (terminal_char == EOF) {
proceed = false;
if (strlen(in_string.c_str( )) > 0) insert(line_number, in_string);
}
else insert(line_number++, in_string);
}
};
error_code Editor::insert_line( ){
int line_number;
cout << " Insert what line number? " << flush;
cin >> line_number;
while (cin.get( ) != 'n');
cout << " What is the new line to insert? " << flush;
string userString;
cin>>userString;
string to_insert = userString;
return insert(line_number, to_insert);
};

Thrust scan of just one class member

I have a custom class myClass which has members weight and config. I'd like to run an inclusive scan on a bunch of myClasses, but only on the weights. Basically what I want is to take:
[ {configA, weightA}, {configB, weightB}, {configC, weightC}, ...]
to:
[ {configA, weightA}, {configB, weight A + weightB}, {configC, weight A + weight B + weightC}, ...]
Is there a simple way to do this using Thrust's fancy iterators? Since the binaryOp is required to be associative, I don't see how to do this with just overloading operator+.
inclusive_scan requires an associative operator, but it needn't be commutative. If you create a binary function which copies the config member of its second parameter to the result, it should work out:
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/scan.h>
struct my_struct
{
__host__ __device__
my_struct() {}
__host__ __device__
my_struct(const my_struct &other)
: config(other.config), weight(other.weight)
{}
__host__ __device__
my_struct(char c, double w)
: config(c), weight(w)
{}
char config;
double weight;
};
struct functor
{
__host__ __device__
my_struct operator()(my_struct a, my_struct b)
{
my_struct result;
result.config = b.config;
result.weight = a.weight + b.weight;
return result;
}
};
int main()
{
thrust::device_vector<my_struct> vec(3);
vec[0] = my_struct('a', 1);
vec[1] = my_struct('b', 2);
vec[2] = my_struct('c', 3);
std::cout << "input: ";
for(int i = 0; i < vec.size(); ++i)
{
my_struct x = vec[i];
std::cout << "{" << x.config << ", " << x.weight << "} ";
}
std::cout << std::endl;
thrust::inclusive_scan(vec.begin(), vec.end(), vec.begin(), functor());
std::cout << "result: ";
for(int i = 0; i < vec.size(); ++i)
{
my_struct x = vec[i];
std::cout << "{" << x.config << ", " << x.weight << "} ";
}
std::cout << std::endl;
return 0;
}
The output:
$ nvcc -arch=sm_20 test.cu -run
input: {a, 1} {b, 2} {c, 3}
result: {a, 1} {b, 3} {c, 6}