How to read JP2 using openJPEG C++ tile by tile - c++

I wonder: What is the intented way to read jp2 tile by tile, and to store data in buffer objects?
Right now i do something like that.
/* note I already created stream and configured decoder and resolution factor is set to 0 */
opj_codestream_index_t *pJP2CodeStreamIndex = opj_get_cstr_index(pJP2Codec);
opj_codestream_info_v2_t *pJP2CodeStreamInfo = opj_get_cstr_info(pJP2Codec);
CDrawRect myRect
GetDrawRect(&myRect);
int start_x = myRect.left;
int start_y = myRect.top;
int end_x = myRect.right;
int end_y = myRect.bottom;
int StartXTile = start_x / pJP2CodeStreamInfo->tdx;
int StartYTile = start_y / pJP2CodeStreamInfo->tdy;
int EndXTile = ceil((float)end_x / (float)pJP2CodeStreamInfo->tdx);
int EndYTile = ceil((float)end_y / (float)pJP2CodeStreamInfo->tdy);
std::vector<int> TilesToDecode;
for(int i = StartXTile; i < EndXTile; i++)
for(int j = StartYTile; j < EndYTile; j++)
{
int TileNo = i+ j*pJP2CodeStreamInfo->tw;
TilesToDecode.push_back(TileNo);
}
for(std::vector<int>::iter Iter = TilesToDecode.begin(); Iter != TilesToDecode.end(); Iter++)
{
opj_get_decoded_tile(pJP2Codec, pJP2Stream, pJP2Image, (OPJ_UINT32)TileNo);
}
/* some time later, i got read buffer for one component */
while (pDst != pEndDst)
{
OPJ_UINT32* pSrc = pJP2Image.comps[NumComp].data;
*pDst = (int)*pSrc;
pDst += stepDst;
pSrc += stepSrc;
}
But how it was intended?

Well, in fact it was quite simple. U just need to be careful with pointer mathematics and buffers' sizes.
/code is writen in C++ with MFC and WINAPI support/
First you need to start decode:
opj_stream_t* pJP2Stream = NULL;
opj_codec_t* pJP2Codec = NULL;
opj_image_t* pJP2Image = NULL;
opj_dparameters_t jp2dParams;
pJP2Stream = opj_stream_create_default_file_stream(LPCTSTR2PCHAR(Filename), OPJ_TRUE);
if(!pJP2Stream)
{
pFileInfo->ErrorCode = ERR_OPEN;
return FALSE;
}
strExt = PathFindExtension(Filename);
if(!strExt.CompareNoCase(_T(".JP2")))
pJP2Codec = opj_create_decompress(OPJ_CODEC_JP2);
if(!strExt.CompareNoCase(_T(".J2K")))
pJP2Codec = opj_create_decompress(OPJ_CODEC_J2K);
if(!strExt.CompareNoCase(_T(".JPP")))
pJP2Codec = opj_create_decompress(OPJ_CODEC_JPP);
if(!strExt.CompareNoCase(_T(".JPT")))
pJP2Codec = opj_create_decompress(OPJ_CODEC_JPT);
if(!strExt.CompareNoCase(_T(".JPX")))
pJP2Codec = opj_create_decompress(OPJ_CODEC_JPX);
if(!pJP2Codec)
{
opj_stream_destroy(pJP2Stream);
opj_destroy_codec(pJP2Codec);
return FALSE;
}
//register callbacks
opj_set_info_handler(pJP2Codec, info_callback,00);
opj_set_warning_handler(pJP2Codec, warning_callback,00);
opj_set_error_handler(pJP2Codec, error_callback,00);
opj_set_default_decoder_parameters(&jp2dParams);
if ( !opj_setup_decoder(pJP2Codec, &jp2dParams) )
{
//(stderr, "ERROR -> opj_compress: failed to setup the decoder\n");
opj_stream_destroy(pJP2Stream);
opj_destroy_codec(pJP2Codec);
return FALSE;
}
if( !opj_read_header(pJP2Stream, pJP2Codec, &pJP2Image) || (pJP2Image->numcomps == 0))
{
opj_stream_destroy(pJP2Stream);
opj_destroy_codec(pJP2Codec);
if (pJP2Image)
opj_image_destroy(pJP2Image);
return FALSE;
}
Second you should read CodestreamInfo:
opj_codestream_info_v2_t *pJP2CodeStreamInfo = opj_get_cstr_info(pJP2Codec);
be careful if u have several threads calling this function you might get a memory leak. So i suggest next code to transfer information into stack mem:
opj_codestream_info_v2_t JP2CodeStreamInfo;
opj_codestream_info_v2_t *pJP2CodeStreamInfo = NULL;
pJP2CodeStreamInfo = opj_get_cstr_info(pJP2Codec);
if(pJP2CodeStreamInfo)
{
JP2CodeStreamInfo = *pJP2CodeStreamInfo;
opj_destroy_cstr_info(&pJP2CodeStreamInfo);
}
else
return FALSE;
Codestream Info changes when you alter decode resolution factor:
opj_set_decoded_resolution_factor(pJP2Codec, nResFactor);
Resolution factor - makes decoded images smaller in 2^nResFactor ratio, loading only first of 2^n rows and columls.
I offer next code as universal solution to copy of any tile to any image block.
long posSrcOffsetX = (start_x > JP2Image.comps[NumBand].x0 ? (start_x - JP2Image.comps[NumBand].x0) : 0) >> JP2Image.comps[NumBand].factor >> (iDifRes);
long posSrcOffsetY = (start_y > JP2Image.comps[NumBand].y0 ? (start_y - JP2Image.comps[NumBand].y0) : 0) >> JP2Image.comps[NumBand].factor >> (iDifRes);
long posDstOffsetX = ((JP2Image.comps[NumBand].x0 > start_x? JP2Image.comps[NumBand].x0 - start_x : 0) >> JP2Image.comps[NumBand].factor >> (iDifRes)) ;
long posDstOffsetY = ((JP2Image.comps[NumBand].y0 > start_y? JP2Image.comps[NumBand].y0 - start_y : 0) >> JP2Image.comps[NumBand].factor >> (iDifRes)) ;
long posSrcEndX = (bInnerBlock ? ((JP2Image.comps[NumBand].x0 >> JP2Image.comps[NumBand].factor) + (end_x >> JP2Image.comps[NumBand].factor)) : JP2Image.comps[NumBand].w) >>(iDifRes) ;
long posSrcEndY = (bInnerBlock ? ((JP2Image.comps[NumBand].y0 >> JP2Image.comps[NumBand].factor) + (end_y >> JP2Image.comps[NumBand].factor)) : JP2Image.comps[NumBand].h) >>(iDifRes) ;
long TileEndX = JP2Image.comps[NumBand].x0 + (JP2Image.comps[NumBand].w << JP2Image.comps[NumBand].factor);
long TileEndY = JP2Image.comps[NumBand].y0 + (JP2Image.comps[NumBand].h << JP2Image.comps[NumBand].factor);
long posDstEndX = (TileEndX > end_x ? end_x - start_x : TileEndX - start_x) >> JP2Image.comps[NumBand].factor >> (iDifRes) ;
long posDstEndY = (TileEndY > end_y ? end_y - start_y : TileEndY - start_y) >> JP2Image.comps[NumBand].factor >> (iDifRes) ;
long stepSrcX = 1 << (iDifRes);
long stepSrcY = JP2Image.comps[NumBand].w << (iDifRes);
long stepDstX = 1;
long stepDstY = 64;
DWORD boundX = posDstEndX - posDstOffsetX;
DWORD boundY = posDstEndY - posDstOffsetY;
for(i = 0 ; i < boundY ; i++ )
{
pSrc = JP2Image.comps[NumBand].data + (posSrcOffsetX)*stepSrcX + ((posSrcOffsetY+i) * stepSrcY);
pDst = pDstLine + (posDstOffsetX + ((posDstOffsetY+i) * stepDstY))*PixelSize;
for ( j = 0; j < boundX ; j++ )
{
iValue = *(pSrc + j* stepSrcX);
iValue += JP2Image.comps[NumBand].sgnd ? (1 << (JP2Image.comps[NumBand].prec - 1)) : 0;
if (iValue > dMax)
iValue = (int)dMax;
else
if (iValue < dMin)
iValue = (int)dMin;
UCHAR bufVal = (UCHAR)iValue;
*(UCHAR*)pDst = (UCHAR)iValue;
pDst += stepDstX*PixelSize;
}
}
Just be sure to check bits per pixel and to have a for clause for all image components.

Related

visual studio access violation reading location 0xc0000005

I am receiving data in TCP in C++ using Qt library. I store the received packet in a QByteArray, but after reading the whole data, I face this error in debug. At the end, I try to clear the buffer, but I face this problem while trying to clear it too.
Here is my code :
void AvaNPortTester::scoket_readyRead()
{
ui.lineEdit_Sending_Status_->setText("Sent");
ui.lineEdit_Sending_Status_->setStyleSheet("QLineEdit { background: rgb(50, 255, 50); }");
tcpSocket_data_buffer_.append(tcpSocket_->readAll());
//qDebug() << serialport_data_buffer_.size();
//auto ddd = QString::number(tcpSocket_data_buffer_.size());// +" : " + tcpSocket_data_buffer_.toHex();
//ui.lableSocketRead->setText(ddd);
bool read_aain = false;
QByteArray dummy(int(1446), Qt::Initialization::Uninitialized);
int reminded_data = 0;
int dummy_size = 0;
int frame_size = 0;
int l_size = 0;
int total_size_rcvd = tcpSocket_data_buffer_.size();
//int total_size_rcvd_b = total_size_rcvd_b;
int temp = 0;
while (total_size_rcvd != 0)
{
if(total_size_rcvd != 0){
auto packet = tcpSocket_data_buffer_.mid(0, 1446);
auto rem = tcpSocket_data_buffer_.mid(1446);//****1146
tcpSocket_data_buffer_ = rem;
QDataStream streamdata(packet);
uint8_t Sync_Header[3];
auto ss = streamdata.readRawData((char*)&Sync_Header, 3);
uint8_t Total_size[2];
ss = streamdata.readRawData((char*)&Total_size, 2);
int t_size = Total_size[0] * 256 + Total_size[1];
uint8_t Reserved[2];
ss = streamdata.readRawData((char*)&Reserved, 2);
frame_size = t_size - 2;
reminded_data = t_size - 2;
while (frame_size != 0)
{
uint8_t portid;
ss = streamdata.readRawData((char*)&portid, 1);
//ui.lineEdit_FileSize->setText(QString::number(fileSend_2Ser->size()));
uint8_t ProtocolID;
ss = streamdata.readRawData((char*)&ProtocolID, 1);
uint8_t MoreFragmentFlag;
ss = streamdata.readRawData((char*)&MoreFragmentFlag, 1);
uint8_t Seq;
ss = streamdata.readRawData((char*)&Seq, 1);
uint8_t size[2];
ss = streamdata.readRawData((char*)&size, 2);
l_size = size[0] * 256 + size[1];
if (packet_flags.Ser2Eth.packet_started[portid] == false) {
uint8_t DDCMP_Header[14];
ss = streamdata.readRawData((char*)&DDCMP_Header, 14);
packet_flags.Ser2Eth.protocol_payload_size[portid] = DDCMP_Header[7] + 256 * DDCMP_Header[8];
temp = packet_flags.Ser2Eth.protocol_payload_size[portid];
packet_flags.Ser2Eth.packet_started[portid] = true;
}
QByteArray ddcmp_datap(int(l_size), Qt::Initialization::Uninitialized);
streamdata.readRawData(ddcmp_datap.data(), l_size - 14);
if ((pre_more_frag == 0) && (MoreFragmentFlag == 0)) {
packet_flags.Ser2Eth.packet_ended[portid] = true;
packet_flags.Ser2Eth.protocol_payload_size[portid] = l_size;
temp = packet_flags.Ser2Eth.protocol_payload_size[portid];
}
else if ((pre_more_frag == 0) && (MoreFragmentFlag == 1)) {
packet_flags.Ser2Eth.packet_ended[portid] = false;
packet_flags.Ser2Eth.protocol_payload_size[portid] = l_size + 16;
temp = packet_flags.Ser2Eth.protocol_payload_size[portid];
}
else if ((pre_more_frag == 1) && (MoreFragmentFlag == 1)) {
packet_flags.Ser2Eth.packet_ended[portid] = false;
packet_flags.Ser2Eth.protocol_payload_size[portid] = packet_flags.Ser2Eth.protocol_payload_size[portid] + l_size;
temp = packet_flags.Ser2Eth.protocol_payload_size[portid];
}
else if ((pre_more_frag == 1) && (MoreFragmentFlag == 0)) {
packet_flags.Ser2Eth.packet_ended[portid] = true;
packet_flags.Ser2Eth.protocol_payload_size[portid] = packet_flags.Ser2Eth.protocol_payload_size[portid] + l_size;
temp = packet_flags.Ser2Eth.protocol_payload_size[portid];
}
if (MoreFragmentFlag == 1) {
pre_more_frag = 1;
}
else {
pre_more_frag = 0;
}
int ff = 0;
if (packet_flags.Ser2Eth.packet_ended[portid] == true) {
packet_flags.Ser2Eth.packet_started[portid] = false;
packet_flags.Ser2Eth.packet_started[portid] = false;
set_port_id_flag(portid, packet_flags.Ser2Eth.protocol_payload_size[portid], ProtocolID);
pre_more_frag = 0;
}
reminded_data = reminded_data - 6 - l_size;
//ui.lableSocketRead->setText(ddcmp_datap.toHex());
frame_size = frame_size - l_size - 6;
}//end of while (frame_size != 0)
uint8_t sync_footer[3];
streamdata.readRawData((char *)&sync_footer, 3);
dummy_size = 1446 - t_size - 8;
uint8_t dummy_data[1000];
streamdata.readRawData((char *)&dummy_data, dummy_size);
total_size_rcvd = total_size_rcvd - 1446;
if (total_size_rcvd == 0) {
tcpSocket_data_buffer_.clear();
}
} //end of if
}//end of while()
}

How to reproduce "Stack smashing detected" in C++ application

I get this error constantly in an embedded Linux application. I am trying to locate the problem and I narrowed it down to the following piece of code.
I want to solve this problem, if not I'd appreciate a couple of pointers what might have caused it.
Any suggestions how to reproduce this stack smashing problem is greately appreciated:
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0;
uint8_t i = 0;
int data[5] = {0,0,0,0,0};
int try_again = 1;
float h = 0.0;
float c = 0.0;
int try_count = 0;
const int max_tries = 30;
if (this->DHT22_SETUP_ != 1)
{
fprintf(stderr,"You havent set up Gpio !\n");
}
else
{
data[0] = 0;
data[1] = 0;
data[2] = 0;
data[3] = 0;
data[4] = 0;
//f = 0.0;
h = 0.0;
c = 0.0;
j = 0;
i = 0;
counter = 0;
laststate = HIGH;
/* pull pin down for 18 milliseconds */
pinMode( this->DHT22Pin, OUTPUT );
digitalWrite( this->DHT22Pin, LOW );
delay( 18 );
/* prepare to read the pin */
pinMode( this->DHT22Pin, INPUT );
/* detect change and read data */
for ( i = 0; i < MAX_TIMINGS; i++ )
{
counter = 0;
while ( digitalRead( this->DHT22Pin ) == laststate )
{
counter++;
delayMicroseconds( 1 );
if ( counter == 255 )
{
break;
}
}
laststate = digitalRead( this->DHT22Pin );
if ( counter == 255 )
break;
/* ignore first 3 transitions */
if ( (i >= 4) && (i % 2 == 0) )
{
/* shove each bit into the storage bytes */
data[j / 8] <<= 1;
if ( counter > 16 )
data[j / 8] |= 1;
j++;
}
}
/*
* check we read 40 bits (8bit x 5 ) + verify checksum in the last byte
* print it out if data is good
*/
if ((j >= 40) &&
(data[4] == ( (data[0] + data[1] + data[2] + data[3]) & 0xFF) ) )
{
h = (float)((data[0] << 8) + data[1]) / 10;
if ( h > 100 )
{
h = data[0]; // for DHT11
}
c = (float)(((data[2] & 0x7F) << 8) + data[3]) / 10;
if ( c > 125 )
{
c = data[2]; // for DHT11
}
if ( data[2] & 0x80 )
{
c = -c;
}
//f = c * 1.8f + 32;
#ifdef DEBUG
printf( "Humidity = %.1f %% Temperature = %.1f *C (%.1f *F)\n", h, c, f );
#endif
try_again = 0;
if (h == 0)
{
try_again = 1;
}
}
else
{
/* Data not good */
try_again = 1;
return 0.0;
//printf ("Data not good, skipping\n");
}
/* Return humidity */
return h;
}
Thanks in advance.
If MAX_TIMINGS is >83, and if counter doesn't reach 255 before i goes over that 83 threshold, then the detect change and read data loop is repeated that many times, and therefore the block of ignore first 3 transitions if-expression is executed >40 times (there may be some off-by-one errors in my quick analysis) and therefore j ends up being >40 which means that j / 8 will be >4 which means it is out of bounds of data array and therefore accessing data[j / 8] in that case has undefined behaviour.
Here's a nice easy way:
class T {
char big[<Some number bigger than your stack size>];
}
int main() {
T bang;
return 0;
}
The allocation of T on the stack will result in your stacksmash. What you have done is likely similar just not with a single class.

Why I'm getting different results from GNU g++ and VC++

I'm trying to solve this problem in C++:
"Given a sequence S of integers, find a number of increasing sequences I such that every two consecutive elements in I appear in S, but on the opposite sides of the first element of I."
This is the code I've developed:
#include<iostream>
#include<set>
#include<vector>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int solution(vector<int> &H) {
// set up
int N = (int)H.size();
if (N == 0 || N == 1) return N;
long long sol = 0;
// build trees
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt), leftTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri, li;
for (int i = 0; i < N; i++) {
Element* e = new Element;
e->acc = 0;
e->con = 0;
e->height = H[i];
rightTree.insert(e);
}
//tree elements set up
ri = --rightTree.end();
Element* elem = *ri;
elem->con = 1;
elem->acc = 1;
while (elem->height > H[0]) {
Element* succ = elem;
ri--;
elem = *ri;
elem->con = 1;
elem->acc = succ->acc + 1;
}
rightTree.erase(ri);
elem->con = elem->acc;
leftTree.insert(elem);
sol += elem->acc;
// main loop
Element* pE = new Element;
for (int j = 1; j < (N - 1); j++) {
// bad case
if (H[j] < H[j - 1]) {
///////
Element* nE = new Element;
nE->height = H[j];
pE->height = H[j - 1];
rightTree.erase(nE);
leftTree.insert(nE);
///////
li = leftTree.lower_bound(pE);
long ltAcc = (*li)->acc;
li--;
///////
ri = rightTree.lower_bound(pE);
long rtAcc = 0;
if (ri != rightTree.end()) rtAcc = (*ri)->acc;
ri--;
///////
while (ri != (--rightTree.begin()) && (*ri)->height > H[j]) {
if (fncomp(*ri, *li)) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
else {
(*ri)->con = ltAcc + 1;
(*ri)->acc = ltAcc + 1 + rtAcc;
rtAcc = (*ri)->acc;
--ri;
}
}
while ((*li)->height > H[j]) {
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
ltAcc = (*li)->acc;
--li;
}
(*li)->con = rtAcc + 1;
(*li)->acc = rtAcc + 1 + ltAcc;
sol += (*li)->acc;
}
// good case
else {
Element* nE = new Element;
nE->height = H[j];
ri = rightTree.upper_bound(nE);
li = leftTree.upper_bound(nE);
rightTree.erase(nE);
if (li == leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1;
}
else if (li != leftTree.end() && ri == rightTree.end()) {
nE->con = 1;
nE->acc = 1 + (*li)->acc;
}
else if (li == leftTree.end() && ri != rightTree.end()) {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con;
}
else {
nE->con = (*ri)->acc + 1;
nE->acc = nE->con + (*li)->acc;
}
leftTree.insert(nE);
sol += nE->acc;
}
}
// final step
li = leftTree.upper_bound(*rightTree.begin());
while (li != leftTree.end()) {
sol++;
li++;
}
sol++;
return (int)(sol % 1000000007);
}
int main(int argc, char* argv[]) {
vector<int> H = { 13, 2, 5 };
cout << "sol: " << solution(H) << endl;
system("pause");
}
The main function calls solution(vector<int> H). The point is, when the argument has the particular value of H = {13, 2, 5} the VC++ compiled program give an output value of 7 (which is the correct one), but the GNU g++ compiled program give an output value of 5 (also clang compiled program behave like this).
I'm using this website, among others, for testing different compilers
http://rextester.com/l/cpp_online_compiler_gcc
I've tried to figure out the reason for this wierd behaviour but didn't found any relevant info. Only one post treat a similar problem:
Different results VS C++ and GNU g++
and that's why I'm using long long types in the code, but the problem persists.
The problem was decrementing the start-of-sequence --rightTree.begin()
As I found VC++ and GNU g++ does not behave the same way on above operation. Here is the code that shows the difference, adapted from http://www.cplusplus.com/forum/general/84609/:
#include<iostream>
#include<set>
using namespace std;
struct Element {
long long height;
long long acc;
long long con;
};
bool fncomp(Element* lhs, Element* rhs) {
return lhs->height < rhs->height;
}
int main(){
bool(*fn_pt)(Element*, Element*) = fncomp;
set<Element*, bool(*)(Element*, Element*)> rightTree(fn_pt);
set<Element*, bool(*)(Element*, Element*)>::iterator ri;
ri = rightTree.begin();
--ri;
++ri;
if(ri == rightTree.begin()) cout << "it works!" << endl;
}

Runtime Error signal 11 on simple C++ code

I am getting a runtime error with this code and I have no idea why.
I am creating a grid and then running a BFS over it. The objective here is to read in the rows and columns of the grid, then determine the maximum number of stars you can pass over before reaching the end.
The start is the top left corner and the end is the bottom right corner.
You can only move down and right. Any ideas?
#include <iostream>
#include <queue>
using namespace std;
int main() {
int r, c, stars[1001][1001], grid[1001][1001], ns[1001][1001];
pair<int, int> cr, nx;
char tmp;
queue<pair<int, int> > q;
cin >> r >> c;
for(int i = 0; i < r; i++) {
for(int j = 0; j < c; j++) {
cin >> tmp;
if(tmp == '.') {
grid[i][j] = 1000000000;
ns[i][j] = 0;
stars[i][j] = 0;
}
else if(tmp == '*') {
grid[i][j] = 1000000000;
ns[i][j] = 1;
stars[i][j] = 1;
}
else
grid[i][j] = -1;
}
}
grid[0][0] = 0;
cr.first = 0;
cr.second = 0;
q.push(cr);
while(!q.empty()) {
cr = q.front();
q.pop();
if(cr.first < r - 1 && grid[cr.first + 1][cr.second] != -1 && ns[cr.first][cr.second] + stars[cr.first + 1][cr.second] > ns[cr.first + 1][cr.second]) {
nx.first = cr.first + 1; nx.second = cr.second;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first + 1][cr.second];
q.push(nx);
}
if(cr.second < c - 1 && grid[cr.first][cr.second + 1] != -1 && ns[cr.first][cr.second] + stars[cr.first][cr.second + 1] > ns[cr.first][cr.second + 1]) {
nx.first = cr.first; nx.second = cr.second + 1;
grid[nx.first][nx.second] = grid[cr.first][cr.second] + 1;
ns[nx.first][nx.second] = ns[cr.first][cr.second] + stars[cr.first][cr.second + 1];
q.push(nx);
}
}
if(grid[r - 1][c - 1] == 1000000000)
cout << "Impossible" << endl;
else
cout << ns[r - 1][c - 1] << endl;
}
Sample input :
6 7
.#*..#.
..*#...
#.....#
..###..
..##..*
*#.....
I'm guessing your stack is not big enough for
int stars[1001][1001], grid[1001][1001], ns[1001][1001];
which is 3 * 1001 * 1001 * sizeof(int) bytes. That's ~12MB if the size of int is 4 bytes.
Either increase the stack size with a compiler option, or go with dynamic allocation i.e. std::vector.
To avoid the large stack you should allocate on the heap
Since you seem to have three parallel 2 - dimension arrays you could
maybe create struct that contains all three values for a x,y position.
That would make it easier to maintain:
struct Area
{
int grid;
int ns;
int stars;
};
std::vector<std::array<Area,1001>> dim2(1001);
dim2[x][y].grid = 100001;
...

Consistent monotonic subsequence

I have problem with this algorithm. It should search for longest consistent and monotonic subsequence and sum of it. If there are few subsequense with the same length it should return the first one.
It should work as monotonic function - http://en.wikipedia.org/wiki/Monotonic_function
For input : 1 1 7 3 2 0 0 4 5 5 6 2 1
the result is : 6 20 - so it works.
But for input : 23 34 11 5 23 90 11 10 15 12 28 49
the result is : 3 113 - but should be 3 50
I feel that the problem is in switching between increasing and decreasing case. Any idea?
code :
#include <stdio.h>
#define gc getchar
void scan_integer(unsigned long long int* o)
{
register unsigned long long int c = gc();
int x = 0;
for (; ((c<48 || c>57)); c = gc());
for (; c>47 && c<58; c = gc()) {
x = (x << 1) + (x << 3) + c - 48;
}
*o = x;
}
int main(){
unsigned long long int current_value, last_value, sum_increasing, sum_decreasing, length_increasing, length_decreasing, max_length, max_sum, is_increasing;
bool equal = false;
scan_integer(&current_value);
last_value = 0;
sum_increasing = current_value;
sum_decreasing = current_value;
length_increasing = 1;
length_decreasing = 1;
max_length = 1;
max_sum = current_value;
is_increasing = 0;
while (!feof(stdin))
{
last_value = current_value;
scan_integer(&current_value);
if (current_value == last_value){
sum_increasing += current_value;
sum_decreasing += current_value;
length_increasing += 1;
length_decreasing += 1;
equal = true;
}
else {
if (current_value > last_value){
sum_increasing += current_value;
length_increasing += 1;
if (equal == true){
length_decreasing = 1;
sum_decreasing = 0;
equal = false;
}
if (is_increasing < 0){
sum_increasing += last_value;
if (length_decreasing > max_length){
max_length = length_decreasing;
max_sum = sum_decreasing;
}
sum_decreasing = 0;
length_decreasing = 1;
}
is_increasing = 1;
}
else {
sum_decreasing += current_value;
length_decreasing += 1;
if (equal == true){
length_increasing = 1;
sum_increasing = 0;
equal = false;
}
if (is_increasing == 1){
sum_decreasing += last_value;
if (length_increasing > max_length){
max_length = length_increasing;
max_sum = sum_increasing;
}
sum_increasing = 0;
length_increasing = 1;
}
is_increasing = -1;
}
}
}
printf("%llu %llu", max_length, max_sum);
return 0;
}
I see a problem in the code, in this part:
is_increasing = 1; // here
// Did you mean to write a continue here?
}
else {
sum_decreasing += current_value;
length_decreasing += 1;
if (equal == true){
length_increasing = 1;
sum_increasing = 0;
equal = false;
}
if (is_increasing == 1){
sum_decreasing += last_value;
if (length_increasing > max_length){
max_length = length_increasing;
max_sum = sum_increasing;
}
sum_increasing = 0;
length_increasing = 1;
}
is_increasing = -1; // Or you might want to put this inside of the else above
If I understand correctly, 'is_increasing = -1' at the bottom completely invalidates the setting of it in the true condition of the if statemen (at the top of the code above). That's why, In the "else" that handles decreasing sequences 'is_increasing' always has the value of '-1' and such sequences never get saved as good sequences.
I put some codes in the code I copied and pasted. I think that handling the codition at which two numbers in sequence might need a little more care than those comments, but this should set you in the right direction.
Let me know if this helps.