<commit_before>#include "LIBCD.H"

#include "EMULATOR_SETUP.H"
#include "EMULATOR.H"

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

enum ReadMode
{
	RM_DATA,
	RM_XA_AUDIO
};

enum ReadMode readMode = RM_DATA;

int CD_Debug = 0;

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
}commandQueue_s, *commandQueue_p;

#define COMMAND_QUEUE_SIZE 128

struct commandQueue comQueue[COMMAND_QUEUE_SIZE];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 0;
int currentTrack = 0;
int numFrames = 0;
int CD_com = 0;

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};

struct AudioSector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2304];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	SDL_memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
        struct Sector sector;
		fread(&sector, sizeof(struct Sector), 1, openFile);
        struct TOC* toc = (struct TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(struct Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				eprintf("Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (struct TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlLOC* cd = (CdlLOC*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(cd)*sectorSize, SEEK_SET);
		break;
	case CdlReadS:
	{
		unsigned int filePos = ftell(openFile);
		CdlLOC currentLoc;
		CdIntToPos(filePos, &currentLoc);
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		currentSector = CdPosToInt(cd);
		if (cd->sector != currentLoc.sector)
		{
			return 1;
		}
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		readMode = RM_DATA;
		break;
	}
	case CdlSetfilter:
	{
		CdlFILTER* cdf = (CdlFILTER*)param;
		//TODO Set channel
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		break;
	}
	case CdlSetfilter:
	{
		CdlFILTER* cdf = (CdlFILTER*)param;
		//TODO Set channel
		break;
	}
	case CdlGetlocP:
		readMode = RM_XA_AUDIO;
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return (75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;///@TODO really mode
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
			break;
		}
	}
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 0)
		{
			if (readMode == RM_DATA)
			{
				struct Sector sector;
				fread(&sector, sizeof(struct Sector), 1, openFile);

				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
				comQueue[i].p += sizeof(sector.data);
			}
			else if (readMode == RM_XA_AUDIO)
			{
				struct AudioSector sector;
				fread(&sector, sizeof(struct AudioSector), 1, openFile);

				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
				comQueue[i].p += sizeof(sector.data);
			}
			else
			{
				assert(FALSE);
			}

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	int lastLevel = CD_Debug;
	CD_Debug = level;
	return lastLevel;
}

int CdSync(int mode, u_char * result)
{
	CdlLOC* loc = (CdlLOC*)result;
	switch (mode)
	{
	case 0:
		UNIMPLEMENTED();
		assert(FALSE);
		break;
	case 1:

		switch (CdLastCom())
		{
		case CdlGetlocP:
			CdlLOC locP;
			CdIntToPos(currentSector+=20, &locP);
			result[0] = currentTrack;
			result[1] = 1;//index, usually 1
			result[2] = locP.minute;
			result[3] = locP.second;
			result[4] = locP.sector;
			result[5] = locP.minute + ENCODE_BCD(numFrames);
			result[6] = locP.second + ENCODE_BCD(numFrames);
			result[7] = locP.sector + ENCODE_BCD(numFrames);

			//Dirty, for now read the audio data
			if (readMode == RM_XA_AUDIO)
			{
				char xaAudioData[2304];
				CdRead(1, (unsigned long*)&xaAudioData[0], CdlReadS);
				CdReadSync(CdlReadS, NULL);

				//Sector should be read now
				xaAudioData[0] = 0;
			}

			break;
		}
		return CdlComplete;
		break;
	}

	return 0;
}

int ParseCueSheet()
{
	char* binFileName = NULL;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
		return 0;
	}

	fseek(openFile, 0, SEEK_END);
	unsigned int cueSheetFileLength = ftell(openFile);
	char* cueSheet = (char*)malloc(cueSheetFileLength);
	fseek(openFile, 0, SEEK_SET);
	fread(cueSheet, cueSheetFileLength, 1, openFile);

	//Null terminated
	char* string = &cueSheet[0];
	if (!strncmp(string, "FILE", 4))
	{
		//Read the binary name since it's a file
		string += 5;
		if (isspace(string[0]))
		{
			string++;
		}

		//Get file name length
		char* afterFileName = string;
		char fileNameLength = 0;
		//While
		while (!isspace(afterFileName[0]))
		{
			afterFileName++;
			fileNameLength++;
		}

		if (string[0] == '"')
		{
			string[fileNameLength - 1] = 0;
			string++;
		}

		binFileName = string;
		string = afterFileName;

		if (isspace(string[0]))
			string++;

		/* Get Type of BIN file */
		assert(!strncmp(string, "BINARY", 6));
		string += 6;

		while (isspace(string[0]))
			string++;

		/* Get Track of BIN file */
		assert(!strncmp(string, "TRACK", 5));
		string += 5;

		while (isspace(string[0]))
			string++;

		currentTrack = atoi(string);

		string += 2;

		while (isspace(string[0]))
			string++;

		assert(!strncmp(string, "MODE1", 5));
		string += 5;

		assert(string[0] == '/');
		string++;

		sectorSize = atoi(string);

		assert(sectorSize == 2352);

		fclose(openFile);
		openFile = fopen(binFileName, "rb");
		fseek(openFile, 0, SEEK_END);
		unsigned int binFileLength = ftell(openFile);
		numFrames = binFileLength / sectorSize;
		assert(numFrames != 0);
		fseek(openFile, 0, SEEK_SET);
		free(cueSheet);
	}

	return 1;
}

int CdInit(void)
{
	currentSector = 0;

	//Read the cue sheet and obtain properties from it.
	if (!ParseCueSheet())
	{
		eprinterr("Failed to read cue sheet!");
		return 0;
	}

	SDL_memset(&comQueue, 0, sizeof(comQueue));
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		comQueue[i].processed = 1;
	}

	return 1;
}

int CdLastCom(void)
{
	return CD_com;
}
<commit_msg>[Emu]: Correct AudioSector.<commit_after>#include "LIBCD.H"

#include "EMULATOR_SETUP.H"
#include "EMULATOR.H"

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

enum ReadMode
{
	RM_DATA,
	RM_XA_AUDIO
};

enum ReadMode readMode = RM_DATA;

int CD_Debug = 0;

FILE* openFile = NULL;

typedef struct commandQueue
{
	unsigned int mode;
	unsigned char* p;
	unsigned int processed;
	unsigned int count;
}commandQueue_s, *commandQueue_p;

#define COMMAND_QUEUE_SIZE 128

struct commandQueue comQueue[COMMAND_QUEUE_SIZE];
int comQueueIndex = 0;
int comQueueCount = 0;
int currentSector = 0;
int sectorSize = 0;
int currentTrack = 0;
int numFrames = 0;
int CD_com = 0;

#pragma pack(push, 1)
struct TOC
{
	unsigned char tocEntryLength;
	unsigned char extEntryLength;
	unsigned int sectorPosition[2];
	unsigned int fileSize[2];
	unsigned char date[7];
	unsigned char flags;
	unsigned char fileUnitSize;
	unsigned char interleaveGapSize;
	unsigned short volSeqNum[2];
	unsigned char nameLength;
};

struct Sector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (see below for encoding details)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	subHead[8];	/// Sub-header (00 00 08 00 00 00 08 00 for Form 1 data sectors)
	unsigned char	data[2048];	/// Data (form 1)
	unsigned char	edc[4];		/// Error-detection code (CRC32 of data area)
	unsigned char	ecc[276];	/// Error-correction code (uses Reed-Solomon ECC algorithm)
};

struct AudioSector
{
	unsigned char	sync[12];	/// Sync pattern (usually 00 FF FF FF FF FF FF FF FF FF FF 00)
	unsigned char	addr[3];	/// Sector address (a 24-bit big-endian integer. starts at 200, 201 an onwards)
	unsigned char	mode;		/// Mode (usually 2 for Mode 2 Form 1/2 sectors)
	unsigned char	data[2336];	/// 8 bytes Subheader, 2324 bytes Data (form 2), and 4 bytes ECC
};
#pragma pack(pop)

CdlFILE* CdSearchFile(CdlFILE* fp, char* name)
{
	SDL_memset(fp, 0, sizeof(CdlFILE));

	if (name[0] == '\\')
	{
		name++;
	}

	if (openFile != NULL)
	{
		fseek(openFile, 22 * sectorSize, SEEK_SET);

		int tocLocalOffset = 0;
        struct Sector sector;
		fread(&sector, sizeof(struct Sector), 1, openFile);
        struct TOC* toc = (struct TOC*)&sector.data[0];
		while (toc->tocEntryLength != 0)
		{
			if (strcmp((char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], name) == 0)
			{
				memcpy(&fp->name[0], (char*)&sector.data[tocLocalOffset + sizeof(struct TOC)], strlen(name));
				fp->size = toc->fileSize[0];
				fseek(openFile, toc->sectorPosition[0] * sectorSize, SEEK_SET);
				fread(&sector, sizeof(struct Sector), 1, openFile);
				fp->pos.minute = sector.addr[0];
				fp->pos.second = sector.addr[1];
				fp->pos.sector = sector.addr[2];

#if _DEBUG
				eprintf("Found %s\n", name);
#endif
				return fp;
			}
			tocLocalOffset += toc->tocEntryLength;
			toc = (struct TOC*)&sector.data[tocLocalOffset];
		}
	}

	return NULL;
}

CdlLOC* CdIntToPos(int i, CdlLOC* p)
{
	i += 150;
	p->sector = ENCODE_BCD(i % 75);
	int rem = i / 75;
	p->second = ENCODE_BCD(rem % 60);
	p->minute = ENCODE_BCD(rem / 60);
	return p;
}

int CdControl(u_char com, u_char * param, u_char * result)
{
	CdlLOC* cd = (CdlLOC*)param;

	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
		fseek(openFile, CdPosToInt(cd)*sectorSize, SEEK_SET);
		break;
	case CdlReadS:
	{
		unsigned int filePos = ftell(openFile);
		CdlLOC currentLoc;
		CdIntToPos(filePos, &currentLoc);
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		currentSector = CdPosToInt(cd);
		if (cd->sector != currentLoc.sector)
		{
			return 1;
		}
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlB(u_char com, u_char* param, u_char* result)
{
	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		readMode = RM_DATA;
		break;
	}
	case CdlSetfilter:
	{
		CdlFILTER* cdf = (CdlFILTER*)param;
		//TODO Set channel
		break;
	}
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdControlF(u_char com, u_char * param)
{
	CD_com = com;

	switch (com)
	{
	case CdlSetloc:
	{
		CdlLOC* cd = (CdlLOC*)param;
		fseek(openFile, CdPosToInt(cd) * sectorSize, SEEK_SET);
		break;
	}
	case CdlSetfilter:
	{
		CdlFILTER* cdf = (CdlFILTER*)param;
		//TODO Set channel
		break;
	}
	case CdlGetlocP:
		readMode = RM_XA_AUDIO;
		break;
	default:
		eprinterr("Unhandled command 0x%02X!\n", com);
		break;
	}

	return 0;
}

int CdPosToInt(CdlLOC* p)
{
	return (75 * (60 * DECODE_BCD(p->minute) + DECODE_BCD(p->second))) + DECODE_BCD(p->sector) - 150;
}

int CdRead(int sectors, u_long* buf, int mode)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 1)
		{
			comQueue[i].mode = CdlReadS;///@TODO really mode
			comQueue[i].p = (unsigned char*)buf;
			comQueue[i].processed = 0;
			comQueue[i].count = sectors;
			break;
		}
	}
	return 0;
}

int CdReadSync(int mode, u_char* result)
{
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		if (comQueue[i].processed == 0)
		{
			if (readMode == RM_DATA)
			{
				struct Sector sector;
				fread(&sector, sizeof(struct Sector), 1, openFile);

				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
				comQueue[i].p += sizeof(sector.data);
			}
			else if (readMode == RM_XA_AUDIO)
			{
				struct AudioSector sector;
				fread(&sector, sizeof(struct AudioSector), 1, openFile);

				memcpy(comQueue[i].p, &sector.data[0], sizeof(sector.data));
				comQueue[i].p += sizeof(sector.data);
			}
			else
			{
				assert(FALSE);
			}

			if (--comQueue[i].count == 0)
			{
				comQueue[i].processed = 1;
				break;
			}

			return 1;
		}
	}
	return 0;
}

int CdSetDebug(int level)
{
	int lastLevel = CD_Debug;
	CD_Debug = level;
	return lastLevel;
}

int CdSync(int mode, u_char * result)
{
	CdlLOC* loc = (CdlLOC*)result;
	switch (mode)
	{
	case 0:
		UNIMPLEMENTED();
		assert(FALSE);
		break;
	case 1:

		switch (CdLastCom())
		{
		case CdlGetlocP:
			CdlLOC locP;
			CdIntToPos(currentSector+=20, &locP);
			result[0] = currentTrack;
			result[1] = 1;//index, usually 1
			result[2] = locP.minute;
			result[3] = locP.second;
			result[4] = locP.sector;
			result[5] = locP.minute + ENCODE_BCD(numFrames);
			result[6] = locP.second + ENCODE_BCD(numFrames);
			result[7] = locP.sector + ENCODE_BCD(numFrames);

			//Dirty, for now read the audio data
			if (readMode == RM_XA_AUDIO)
			{
				char xaAudioData[2336];
				CdRead(1, (unsigned long*)&xaAudioData[0], CdlReadS);
				CdReadSync(CdlReadS, NULL);

				//Sector should be read now
				xaAudioData[0] = 0;
			}

			break;
		}
		return CdlComplete;
		break;
	}

	return 0;
}

int ParseCueSheet()
{
	char* binFileName = NULL;
	openFile = fopen(DISC_IMAGE_FILENAME, "rb");

	if (openFile == NULL)
	{
		eprinterr("Failed to open disc image file! %s\n", DISC_IMAGE_FILENAME);
		return 0;
	}

	fseek(openFile, 0, SEEK_END);
	unsigned int cueSheetFileLength = ftell(openFile);
	char* cueSheet = (char*)malloc(cueSheetFileLength);
	fseek(openFile, 0, SEEK_SET);
	fread(cueSheet, cueSheetFileLength, 1, openFile);

	//Null terminated
	char* string = &cueSheet[0];
	if (!strncmp(string, "FILE", 4))
	{
		//Read the binary name since it's a file
		string += 5;
		if (isspace(string[0]))
		{
			string++;
		}

		//Get file name length
		char* afterFileName = string;
		char fileNameLength = 0;
		//While
		while (!isspace(afterFileName[0]))
		{
			afterFileName++;
			fileNameLength++;
		}

		if (string[0] == '"')
		{
			string[fileNameLength - 1] = 0;
			string++;
		}

		binFileName = string;
		string = afterFileName;

		if (isspace(string[0]))
			string++;

		/* Get Type of BIN file */
		assert(!strncmp(string, "BINARY", 6));
		string += 6;

		while (isspace(string[0]))
			string++;

		/* Get Track of BIN file */
		assert(!strncmp(string, "TRACK", 5));
		string += 5;

		while (isspace(string[0]))
			string++;

		currentTrack = atoi(string);

		string += 2;

		while (isspace(string[0]))
			string++;

		assert(!strncmp(string, "MODE1", 5));
		string += 5;

		assert(string[0] == '/');
		string++;

		sectorSize = atoi(string);

		assert(sectorSize == 2352);

		fclose(openFile);
		openFile = fopen(binFileName, "rb");
		fseek(openFile, 0, SEEK_END);
		unsigned int binFileLength = ftell(openFile);
		numFrames = binFileLength / sectorSize;
		assert(numFrames != 0);
		fseek(openFile, 0, SEEK_SET);
		free(cueSheet);
	}

	return 1;
}

int CdInit(void)
{
	currentSector = 0;

	//Read the cue sheet and obtain properties from it.
	if (!ParseCueSheet())
	{
		eprinterr("Failed to read cue sheet!");
		return 0;
	}

	SDL_memset(&comQueue, 0, sizeof(comQueue));
	for (int i = 0; i < COMMAND_QUEUE_SIZE; i++)
	{
		comQueue[i].processed = 1;
	}

	return 1;
}

int CdLastCom(void)
{
	return CD_com;
}
<|endoftext|>


<commit_before>#include "bluetoothRobotCommunicationThread.h"

#include <QtCore/QMetaType>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <time.h>

#include <qrkernel/settingsManager.h>
#include <plugins/robots/thirdparty/qextserialport/src/qextserialport.h>
#include <utils/tracer.h>

#include "src/robotModel/real/ev3DirectCommand.h"
#include "commandConstants.h"

unsigned const keepAliveResponseSize = 5;

using namespace ev3KitInterpreter::communication;

BluetoothRobotCommunicationThread::BluetoothRobotCommunicationThread()
	: mPort(nullptr)
	, mKeepAliveTimer(new QTimer(this))
{
	QObject::connect(mKeepAliveTimer, SIGNAL(timeout()), this, SLOT(checkForConnection()));
}

BluetoothRobotCommunicationThread::~BluetoothRobotCommunicationThread()
{
	disconnect();
}

void BluetoothRobotCommunicationThread::send(QObject *addressee
		, QByteArray const &buffer, unsigned const responseSize)
{
	if (!mPort) {
		emit response(addressee, QByteArray());
		return;
	}

	send(buffer);
	if (buffer.size() >= 5 && buffer[4] == enums::commandType::CommandTypeEnum::DIRECT_COMMAND_REPLY) {
		QByteArray const result = receive(responseSize);
		emit response(addressee, result);
	} else {
		emit response(addressee, QByteArray());
	}
}

void BluetoothRobotCommunicationThread::connect()
{
	if (mPort) {
		disconnect();
		QThread::msleep(1000);  // Give port some time to close
	}

	QString const portName = qReal::SettingsManager::value("Ev3BluetoothPortName").toString();
	mPort = new QextSerialPort(portName, QextSerialPort::Polling);
	mPort->setBaudRate(BAUD9600);
	mPort->setFlowControl(FLOW_OFF);
	mPort->setParity(PAR_NONE);
	mPort->setDataBits(DATA_8);
	mPort->setStopBits(STOP_2);
	mPort->setTimeout(3000);

	mPort->open(QIODevice::ReadWrite | QIODevice::Unbuffered);

	//utils::Tracer::debug(utils::Tracer::initialization, "BluetoothRobotCommunicationThread::connect"
	//		, "Port " + mPort->portName() + " is open: " + QString("%1").arg(mPort->isOpen()));

	// Sending "Keep alive" command to check connection.
	keepAlive();
	QByteArray const response = receive(keepAliveResponseSize);

	emit connected(response != QByteArray(), QString());

	mKeepAliveTimer->start(500);
}

void BluetoothRobotCommunicationThread::reconnect()
{
	connect();
}

void BluetoothRobotCommunicationThread::disconnect()
{
	if (mPort) {
		mPort->close();
		delete mPort;
		mPort = nullptr;
		mKeepAliveTimer->stop();
	}

	emit disconnected();
}

void BluetoothRobotCommunicationThread::allowLongJobs(bool allow)
{
	Q_UNUSED(allow);
}

void BluetoothRobotCommunicationThread::send(QByteArray const &buffer
		, unsigned const responseSize, QByteArray &outputBuffer)
{
	send(buffer);
	outputBuffer = receive(responseSize);
}

void BluetoothRobotCommunicationThread::send(QByteArray const &buffer) const
{
	//utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::send", "Sending:");
	//for (int i = 0; i < buffer.size(); ++i) {
	//	utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::send"
	//			, QString("Byte %1 %2").arg(i).arg(static_cast<unsigned char>(buffer[i])));
	//}

	mPort->write(buffer);
}

QByteArray BluetoothRobotCommunicationThread::receive(int size) const
{
	QByteArray const result = mPort->read(size);

	//utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::receive", "Received:");
	//for (int i = 0; i < result.size(); ++i) {
	//	utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::receive"
	//			, QString("Byte %1 %2").arg(i).arg(static_cast<unsigned char>(result[i])));
	//}

	return result;
}

void BluetoothRobotCommunicationThread::checkForConnection()
{
	if (!mPort || !mPort->isOpen()) {
		return;
	}

	keepAlive();
	QByteArray const response = receive(keepAliveResponseSize);

	if (response == QByteArray()) {
		emit disconnected();
	}
}

void BluetoothRobotCommunicationThread::keepAlive()
{
	QByteArray command = robotModel::real::Ev3DirectCommand::formCommand(9, 0, 0, 0, enums::commandType::CommandTypeEnum::DIRECT_COMMAND_REPLY);
	command[7] = enums::opcode::OpcodeEnum::KEEP_ALIVE;
	command[8] = 10;
	send(command);
}

void BluetoothRobotCommunicationThread::checkConsistency()
{
}
<commit_msg>small fix<commit_after>#include "bluetoothRobotCommunicationThread.h"

#include <QtCore/QMetaType>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <time.h>

#include <qrkernel/settingsManager.h>
#include <plugins/robots/thirdparty/qextserialport/src/qextserialport.h>
#include <utils/tracer.h>

#include "src/robotModel/real/ev3DirectCommand.h"
#include "commandConstants.h"

unsigned const keepAliveResponseSize = 5;

using namespace ev3KitInterpreter::communication;

BluetoothRobotCommunicationThread::BluetoothRobotCommunicationThread()
	: mPort(nullptr)
	, mKeepAliveTimer(new QTimer(this))
{
	QObject::connect(mKeepAliveTimer, SIGNAL(timeout()), this, SLOT(checkForConnection()));
}

BluetoothRobotCommunicationThread::~BluetoothRobotCommunicationThread()
{
	disconnect();
}

void BluetoothRobotCommunicationThread::send(QObject *addressee
		, QByteArray const &buffer, unsigned const responseSize)
{
	if (!mPort) {
		emit response(addressee, QByteArray());
		return;
	}

	send(buffer);
	if (buffer.size() >= 5 && buffer[4] == enums::commandType::CommandTypeEnum::DIRECT_COMMAND_REPLY) {
		QByteArray const result = receive(responseSize);
		emit response(addressee, result);
	} else {
		emit response(addressee, QByteArray());
	}
}

void BluetoothRobotCommunicationThread::connect()
{
	if (mPort) {
		disconnect();
		QThread::msleep(1000);  // Give port some time to close
	}

	QString const portName = qReal::SettingsManager::value("Ev3BluetoothPortName").toString();
	mPort = new QextSerialPort(portName, QextSerialPort::Polling);
	mPort->setBaudRate(BAUD9600);
	mPort->setFlowControl(FLOW_OFF);
	mPort->setParity(PAR_NONE);
	mPort->setDataBits(DATA_8);
	mPort->setStopBits(STOP_2);
	mPort->setTimeout(3000);

	mPort->open(QIODevice::ReadWrite | QIODevice::Unbuffered);

	//utils::Tracer::debug(utils::Tracer::initialization, "BluetoothRobotCommunicationThread::connect"
	//		, "Port " + mPort->portName() + " is open: " + QString("%1").arg(mPort->isOpen()));

	// Sending "Keep alive" command to check connection.
	keepAlive();
	QByteArray const response = receive(keepAliveResponseSize);

	emit connected(response != QByteArray(), QString());

	mKeepAliveTimer->start(500);
}

void BluetoothRobotCommunicationThread::reconnect()
{
	connect();
}

void BluetoothRobotCommunicationThread::disconnect()
{
	if (mPort) {
		mPort->close();
		delete mPort;
		mPort = nullptr;
		mKeepAliveTimer->stop();
	}

	emit disconnected();
}

void BluetoothRobotCommunicationThread::allowLongJobs(bool allow)
{
	Q_UNUSED(allow);
}

void BluetoothRobotCommunicationThread::send(QByteArray const &buffer
		, unsigned const responseSize, QByteArray &outputBuffer)
{
	send(buffer);
	outputBuffer = receive(responseSize);
}

void BluetoothRobotCommunicationThread::send(QByteArray const &buffer) const
{
	//utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::send", "Sending:");
	//for (int i = 0; i < buffer.size(); ++i) {
	//	utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::send"
	//			, QString("Byte %1 %2").arg(i).arg(static_cast<unsigned char>(buffer[i])));
	//}

	mPort->write(buffer);
}

QByteArray BluetoothRobotCommunicationThread::receive(int size) const
{
	QByteArray const result = mPort->read(size);

	//utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::receive", "Received:");
	//for (int i = 0; i < result.size(); ++i) {
	//	utils::Tracer::debug(utils::Tracer::robotCommunication, "BluetoothRobotCommunicationThread::receive"
	//			, QString("Byte %1 %2").arg(i).arg(static_cast<unsigned char>(result[i])));
	//}

	return result;
}

void BluetoothRobotCommunicationThread::checkForConnection()
{
	if (!mPort || !mPort->isOpen()) {
		return;
	}

	keepAlive();
	QByteArray const response = receive(keepAliveResponseSize);

	if (response == QByteArray()) {
		emit disconnected();
	}
}

void BluetoothRobotCommunicationThread::keepAlive()
{
	QByteArray command = robotModel::real::Ev3DirectCommand::formCommand(10, 0, 0, 0, enums::commandType::CommandTypeEnum::DIRECT_COMMAND_REPLY);
	int index = 7;
	robotModel::real::Ev3DirectCommand::addOpcode(enums::opcode::OpcodeEnum::KEEP_ALIVE, command, index);
	robotModel::real::Ev3DirectCommand::addByteParameter(10, command, index); //10 - Number of minutes before entering sleep mode.
	send(command);
}

void BluetoothRobotCommunicationThread::checkConsistency()
{
}
<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2/19/2019, 9:14:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N;
ll W;
ll v[210];
ll w[210];

typedef tuple<ll, ll> P;

vector<P> half(int x, int y)
{
  map<ll, ll> M;
  M[0] = 0;
  int l = y - x;
  for (auto i = 0; i < (1 << l); i++)
  {
    ll value = 0;
    ll weight = 0;
    for (auto k = 0; k < l; k++)
    {
      if ((i >> k) & 1)
      {
        value += v[k + x];
        weight += w[k + x];
        if (M.find(weight) == M.end())
        {
          M[weight] = value;
        }
        else
        {
          M[weight] = max(M[weight], value);
        }
      }
    }
  }
  vector<P> V;
  for (auto x : M)
  {
    V.push_back(P(x.first, x.second));
  }
  return V;
}

void solve1()
{
  vector<P> X[2] = {half(0, N / 2), half(N / 2, N)};
  reverse(X[1].begin(), X[1].end());
  int ind[2] = {0, 0};
  ll ans = 0;
  while (ind[0] < (int)X[0].size() && ind[1] < (int)X[1].size())
  {
    ll w_0 = get<0>(X[0][ind[0]]);
    ll v_0 = get<1>(X[0][ind[0]]);
    ll w_1 = get<0>(X[1][ind[1]]);
    ll v_1 = get<1>(X[1][ind[1]]);
    if (w_0 + w_1 <= W)
    {
      ans = max(ans, v_0 + v_1);
      ind[0]++;
    }
    else
    {
      ind[1]++;
    }
  }
  cout << ans << endl;
}

ll DP[210][200010];

void solve2()
{
  fill(&DP[0][0], &DP[0][0] + 210 * 200010, -1);
  DP[0][0] = 0;
  int H = min(W, 200001LL);
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j <= H; j++)
    {
      if (DP[i][j] == -1)
      {
        continue;
      }
      DP[i + 1][j] = max(DP[i + 1][j], DP[i][j]);
      if (j + w[i] <= H)
      {
        DP[i + 1][j + w[i]] = max(DP[i + 1][j + w[i]], DP[i][j] + v[i]);
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i <= H; i++)
  {
    ans = max(ans, DP[N][i]);
  }
  cout << ans << endl;
}

ll const infty = 1000000000000000000;

void solve3()
{
  fill(&DP[0][0], &DP[0][0] + 210 * 200010, infty);
  DP[0][0] = 0;
  int H = 200001;
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j <= H; j++)
    {
      if (DP[i][j] == infty)
      {
        continue;
      }
      DP[i + 1][j] = min(DP[i + 1][j], DP[i][j]);
      if (j + v[i] <= H)
      {
        DP[i + 1][j + v[i]] = min(DP[i + 1][j + v[i]], DP[i][j] + w[i]);
      }
    }
  }
  for (auto i = H - 1; i >= 0; i--)
  {
    if (DP[N][i] <= W)
    {
      cout << i << endl;
      return;
    }
  }
}

int main()
{
  cin >> N >> W;
  for (auto i = 0; i < N; i++)
  {
    cin >> v[i] >> w[i];
  }
  bool ok_w = true;
  for (auto i = 0; i < N; i++)
  {
    if (w[i] > 1000LL)
    {
      ok_w = false;
      break;
    }
  }
  bool ok_v = true;
  for (auto i = 0; i < N; i++)
  {
    if (v[i] > 1000LL)
    {
      ok_v = false;
      break;
    }
  }
  if (!ok_v && !ok_w)
  {
    solve1();
  }
  else if (ok_w)
  {
    solve2();
  }
  else
  {
    solve3();
  }
}<commit_msg>submit D.cpp to 'D - ナップサック問題' (abc032) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1

/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2/19/2019, 9:14:45 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N;
ll W;
ll v[210];
ll w[210];

typedef tuple<ll, ll> P;

vector<P> half(int x, int y)
{
  map<ll, ll> M;
  M[0] = 0;
  int l = y - x;
  for (auto i = 0; i < (1 << l); i++)
  {
    ll value = 0;
    ll weight = 0;
    for (auto k = 0; k < l; k++)
    {
      if ((i >> k) & 1)
      {
        value += v[k + x];
        weight += w[k + x];
        if (M.find(weight) == M.end())
        {
          M[weight] = value;
        }
        else
        {
          M[weight] = max(M[weight], value);
        }
      }
    }
  }
  vector<P> V;
  ll maxi = 0;
  for (auto x : M)
  {
    maxi = max(x.second, maxi);
    V.push_back(P(x.first, maxi));
  }
  return V;
}

void solve1()
{
  vector<P> X[2] = {half(0, N / 2), half(N / 2, N)};
  reverse(X[1].begin(), X[1].end());
  int ind[2] = {0, 0};
  ll ans = 0;
  while (ind[0] < (int)X[0].size() && ind[1] < (int)X[1].size())
  {
    ll w_0 = get<0>(X[0][ind[0]]);
    ll v_0 = get<1>(X[0][ind[0]]);
    ll w_1 = get<0>(X[1][ind[1]]);
    ll v_1 = get<1>(X[1][ind[1]]);
    if (w_0 + w_1 <= W)
    {
      ans = max(ans, v_0 + v_1);
      ind[0]++;
    }
    else
    {
      ind[1]++;
    }
  }
  cout << ans << endl;
}

ll DP[210][200010];

void solve2()
{
  fill(&DP[0][0], &DP[0][0] + 210 * 200010, -1);
  DP[0][0] = 0;
  int H = min(W, 200001LL);
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j <= H; j++)
    {
      if (DP[i][j] == -1)
      {
        continue;
      }
      DP[i + 1][j] = max(DP[i + 1][j], DP[i][j]);
      if (j + w[i] <= H)
      {
        DP[i + 1][j + w[i]] = max(DP[i + 1][j + w[i]], DP[i][j] + v[i]);
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i <= H; i++)
  {
    ans = max(ans, DP[N][i]);
  }
  cout << ans << endl;
}

ll const infty = 1000000000000000000;

void solve3()
{
  fill(&DP[0][0], &DP[0][0] + 210 * 200010, infty);
  DP[0][0] = 0;
  int H = 200001;
  for (auto i = 0; i < N; i++)
  {
    for (auto j = 0; j <= H; j++)
    {
      if (DP[i][j] == infty)
      {
        continue;
      }
      DP[i + 1][j] = min(DP[i + 1][j], DP[i][j]);
      if (j + v[i] <= H)
      {
        DP[i + 1][j + v[i]] = min(DP[i + 1][j + v[i]], DP[i][j] + w[i]);
      }
    }
  }
  for (auto i = H - 1; i >= 0; i--)
  {
    if (DP[N][i] <= W)
    {
      cout << i << endl;
      return;
    }
  }
}

int main()
{
  cin >> N >> W;
  for (auto i = 0; i < N; i++)
  {
    cin >> v[i] >> w[i];
  }
  bool ok_w = true;
  for (auto i = 0; i < N; i++)
  {
    if (w[i] > 1000LL)
    {
      ok_w = false;
      break;
    }
  }
  bool ok_v = true;
  for (auto i = 0; i < N; i++)
  {
    if (v[i] > 1000LL)
    {
      ok_v = false;
      break;
    }
  }
  if (!ok_v && !ok_w)
  {
    solve1();
  }
  else if (ok_w)
  {
    solve2();
  }
  else
  {
    solve3();
  }
}<|endoftext|>


<commit_before>//******************************************************************************************************
//  SubscriberInstance.cpp - Gbtc
//
//  Copyright  2018, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
//  not use this file except in compliance with the License. You may obtain a copy of the License at:
//
//      http://opensource.org/licenses/MIT
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  03/21/2018 - J. Ritchie Carroll
//       Generated original version of source code.
//
//******************************************************************************************************

#include "SubscriberInstance.h"
#include "../Transport/Constants.h"

SubscriberInstance::SubscriberInstance() :
    m_hostname("localhost"),
    m_port(6165),
    m_udpPort(0),
    m_filterExpression(SubscribeAllNoStatsExpression),
    m_startTime(""),
    m_stopTime("")
{
    // Reference this SubscriberInstance in DataSubsciber user data
    m_subscriber.SetUserData(this);
    m_subscriber.SetMetadataCompressed(false);
}

SubscriberInstance::~SubscriberInstance()
{
}

// public functions

void SubscriberInstance::Initialize(std::string hostname, gsfts::uint16_t port, gsfts::uint16_t udpPort)
{
    m_hostname = hostname;
    m_port = port;
    m_udpPort = udpPort;
}

void SubscriberInstance::EstablishHistoricalRead(std::string startTime, std::string stopTime)
{
    m_startTime = startTime;
    m_stopTime = stopTime;
}

void SubscriberInstance::SetFilterExpression(std::string filterExpression)
{
    m_filterExpression = filterExpression;

    // Resubscribe with new filter expression if already connected
    if (m_subscriber.IsSubscribed())
        m_subscriber.Subscribe(m_info);
}

void SubscriberInstance::Connect()
{
    // The connector is declared here because it
    // is only needed for the initial connection
    tst::SubscriberConnector connector;

    // Set up helper objects (derived classes can override behavior ad settings)
    connector = CreateSubscriberConnector();
    m_info = CreateSubscriptionInfo();

    // Register callbacks
    m_subscriber.RegisterStatusMessageCallback(&HandleStatusMessage);
    m_subscriber.RegisterErrorMessageCallback(&HandleErrorMessage);
    m_subscriber.RegisterDataStartTimeCallback(&HandleDataStartTime);
    m_subscriber.RegisterMetadataCallback(&HandleMetadata);
    m_subscriber.RegisterNewMeasurementsCallback(&HandleNewMeasurements);
    m_subscriber.RegisterConfigurationChangedCallback(&HandleConfigurationChanged);
    m_subscriber.RegisterConnectionTerminatedCallback(&HandleConnectionTerminated);

    if (!m_startTime.empty() && !m_stopTime.empty())
    {
        m_subscriber.RegisterProcessingCompleteCallback(&HandleProcessingComplete);
        m_info.StartTime = m_startTime;
        m_info.StopTime = m_stopTime;
    }

    if (m_udpPort > 0)
    {
        m_info.UdpDataChannel = true;
        m_info.DataChannelLocalPort = m_udpPort;
    }

    // Connect and subscribe to publisher
    if (connector.Connect(m_subscriber))
    {
        ConnectionEstablished();

        // Request metadata upon successful connection, after metadata is handled
        // the SubscriberInstance will then subscribe to the desired data
        m_subscriber.SendServerCommand(tst::ServerCommand::MetadataRefresh);
    }
    else
    {
        ErrorMessage("All connection attempts failed");
    }
}

void SubscriberInstance::Disconnect()
{
    m_subscriber.Disconnect();
}

void SubscriberInstance::SetHistoricalReplayInterval(int32_t replayInterval)
{
    if (m_subscriber.IsSubscribed())
    {
        replayInterval = m_endianConverter.ConvertBigEndian(replayInterval);
        m_subscriber.SendServerCommand(tst::ServerCommand::UpdateProcessingInterval, (gsfts::uint8_t*)&replayInterval, 0, 4);
    }
}

void* SubscriberInstance::GetUserData() const
{
    return m_userData;
}

void SubscriberInstance::SetUserData(void* userData)
{
    m_userData = userData;
}

bool SubscriberInstance::IsMetadataCompressed() const
{
    return m_subscriber.IsMetadataCompressed();
}

void SubscriberInstance::SetMetadataCompressed(bool compressed)
{
    m_subscriber.SetMetadataCompressed(compressed);
}

long SubscriberInstance::GetTotalCommandChannelBytesReceived() const
{
    return m_subscriber.GetTotalCommandChannelBytesReceived();
}

long SubscriberInstance::GetTotalDataChannelBytesReceived() const
{
    return m_subscriber.GetTotalDataChannelBytesReceived();
}

long SubscriberInstance::GetTotalMeasurementsReceived() const
{
    return m_subscriber.GetTotalMeasurementsReceived();
}

bool SubscriberInstance::IsConnected() const
{
    return m_subscriber.IsConnected();
}

bool SubscriberInstance::IsSubscribed() const
{
    return m_subscriber.IsSubscribed();
}

// protected functions

// All the following protected functions are virtual so that derived
// classes can customize behavior of the SubscriberInstance

tst::SubscriberConnector SubscriberInstance::CreateSubscriberConnector()
{
    // SubscriberConnector is another helper object which allows the
    // user to modify settings for auto-reconnects and retry cycles.
    tst::SubscriberConnector connector;

    // Register callbacks
    connector.RegisterErrorMessageCallback(&HandleErrorMessage);
    connector.RegisterReconnectCallback(&HandleResubscribe);

    connector.SetHostname(m_hostname);
    connector.SetPort(m_port);
    connector.SetMaxRetries(-1);
    connector.SetRetryInterval(5000);
    connector.SetAutoReconnect(true);

    return connector;
}

tst::SubscriptionInfo SubscriberInstance::CreateSubscriptionInfo()
{
    // SubscriptionInfo is a helper object which allows the user
    // to set up their subscription and reuse subscription settings.
    tst::SubscriptionInfo info;

    // Define desired filter expression
    info.FilterExpression = m_filterExpression;

    // To set up a remotely synchronized subscription, set this flag
    // to true and add the framesPerSecond parameter to the
    // ExtraConnectionStringParameters. Additionally, the following
    // example demonstrates the use of some other useful parameters
    // when setting up remotely synchronized subscriptions.
    //
    //info.RemotelySynchronized = true;
    //info.ExtraConnectionStringParameters = "framesPerSecond=30;timeResolution=10000;downsamplingMethod=Closest";

    info.RemotelySynchronized = false;
    info.Throttled = false;

    info.UdpDataChannel = false;

    info.IncludeTime = true;
    info.LagTime = 3.0;
    info.LeadTime = 1.0;
    info.UseLocalClockAsRealTime = false;
    info.UseMillisecondResolution = true;

    return info;
}

void SubscriberInstance::StatusMessage(std::string message)
{
    std::cout << message << std::endl << std::endl;
}

void SubscriberInstance::ErrorMessage(std::string message)
{
    std::cerr << message << std::endl << std::endl;
}

void SubscriberInstance::DataStartTime(std::time_t unixSOC, int milliseconds)
{
}

void SubscriberInstance::ReceivedMetadata(std::vector<uint8_t> payload)
{
}

void SubscriberInstance::ReceivedNewMeasurements(std::vector<gsfts::Measurement> measurements)
{
}

void SubscriberInstance::ConfigurationChanged()
{
    StatusMessage("Configuration changed");
}

void SubscriberInstance::HistoricalReadComplete()
{
    StatusMessage("Historical read complete");
}

void SubscriberInstance::ConnectionEstablished()
{
    StatusMessage("Connection established");
}

void SubscriberInstance::ConnectionTerminated()
{
    StatusMessage("Connection terminated");
}

// private functions

// The following member methods are defined as static so they
// can be used as callback registrations for DataSubscriber

void SubscriberInstance::HandleResubscribe(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    if (source->IsConnected())
    {
        instance->ConnectionEstablished();
        source->Subscribe(instance->m_info);
    }
}

void SubscriberInstance::HandleStatusMessage(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->StatusMessage(message);
}

void SubscriberInstance::HandleErrorMessage(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ErrorMessage(message);
}

void SubscriberInstance::HandleDataStartTime(tst::DataSubscriber* source, gsfts::int64_t startTime)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    std::time_t unixSOC;
    int milliseconds;

    gsfts::GetUnixTime(startTime, unixSOC, milliseconds);

    instance->DataStartTime(unixSOC, milliseconds);
}

void SubscriberInstance::HandleMetadata(tst::DataSubscriber* source, std::vector<uint8_t> payload)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    // Call virtual method to handle metadata payload
    instance->ReceivedMetadata(payload);

    // Start subscription after successful user meta-data handling
    source->Subscribe(instance->m_info);
}

void SubscriberInstance::HandleNewMeasurements(tst::DataSubscriber* source, std::vector<gsfts::Measurement> measurements)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ReceivedNewMeasurements(measurements);
}

void SubscriberInstance::HandleConfigurationChanged(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    // Call virtual method to notify consumer that configuration has changed
    instance->ConfigurationChanged();

    // When publisher configuration has changed, request updated metadata
    source->SendServerCommand(tst::ServerCommand::MetadataRefresh);
}

void SubscriberInstance::HandleProcessingComplete(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->StatusMessage(message);
    instance->HistoricalReadComplete();
}

void SubscriberInstance::HandleConnectionTerminated(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ConnectionTerminated();
}<commit_msg>TimeSeriesPlatformLibrary: Fixed auto-resubscribe functionality when filter expression is updated in SubscriberInstance<commit_after>//******************************************************************************************************
//  SubscriberInstance.cpp - Gbtc
//
//  Copyright  2018, Grid Protection Alliance.  All Rights Reserved.
//
//  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
//  the NOTICE file distributed with this work for additional information regarding copyright ownership.
//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
//  not use this file except in compliance with the License. You may obtain a copy of the License at:
//
//      http://opensource.org/licenses/MIT
//
//  Unless agreed to in writing, the subject software distributed under the License is distributed on an
//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
//  License for the specific language governing permissions and limitations.
//
//  Code Modification History:
//  ----------------------------------------------------------------------------------------------------
//  03/21/2018 - J. Ritchie Carroll
//       Generated original version of source code.
//
//******************************************************************************************************

#include "SubscriberInstance.h"
#include "../Transport/Constants.h"

SubscriberInstance::SubscriberInstance() :
    m_hostname("localhost"),
    m_port(6165),
    m_udpPort(0),
    m_filterExpression(SubscribeAllNoStatsExpression),
    m_startTime(""),
    m_stopTime("")
{
    // Reference this SubscriberInstance in DataSubsciber user data
    m_subscriber.SetUserData(this);
    m_subscriber.SetMetadataCompressed(false);
}

SubscriberInstance::~SubscriberInstance()
{
}

// public functions

void SubscriberInstance::Initialize(std::string hostname, gsfts::uint16_t port, gsfts::uint16_t udpPort)
{
    m_hostname = hostname;
    m_port = port;
    m_udpPort = udpPort;
}

void SubscriberInstance::EstablishHistoricalRead(std::string startTime, std::string stopTime)
{
    m_startTime = startTime;
    m_stopTime = stopTime;
}

void SubscriberInstance::SetFilterExpression(std::string filterExpression)
{
    m_filterExpression = filterExpression;

    // Resubscribe with new filter expression if already connected
    if (m_subscriber.IsSubscribed())
    {
        m_info.FilterExpression = m_filterExpression;
        m_subscriber.Subscribe(m_info);
    }
}

void SubscriberInstance::Connect()
{
    // The connector is declared here because it
    // is only needed for the initial connection
    tst::SubscriberConnector connector;

    // Set up helper objects (derived classes can override behavior and settings)
    connector = CreateSubscriberConnector();
    m_info = CreateSubscriptionInfo();

    // Register callbacks
    m_subscriber.RegisterStatusMessageCallback(&HandleStatusMessage);
    m_subscriber.RegisterErrorMessageCallback(&HandleErrorMessage);
    m_subscriber.RegisterDataStartTimeCallback(&HandleDataStartTime);
    m_subscriber.RegisterMetadataCallback(&HandleMetadata);
    m_subscriber.RegisterNewMeasurementsCallback(&HandleNewMeasurements);
    m_subscriber.RegisterConfigurationChangedCallback(&HandleConfigurationChanged);
    m_subscriber.RegisterConnectionTerminatedCallback(&HandleConnectionTerminated);

    if (!m_startTime.empty() && !m_stopTime.empty())
    {
        m_subscriber.RegisterProcessingCompleteCallback(&HandleProcessingComplete);
        m_info.StartTime = m_startTime;
        m_info.StopTime = m_stopTime;
    }

    if (m_udpPort > 0)
    {
        m_info.UdpDataChannel = true;
        m_info.DataChannelLocalPort = m_udpPort;
    }

    // Connect and subscribe to publisher
    if (connector.Connect(m_subscriber))
    {
        ConnectionEstablished();

        // Request metadata upon successful connection, after metadata is handled
        // the SubscriberInstance will then subscribe to the desired data
        m_subscriber.SendServerCommand(tst::ServerCommand::MetadataRefresh);
    }
    else
    {
        ErrorMessage("All connection attempts failed");
    }
}

void SubscriberInstance::Disconnect()
{
    m_subscriber.Disconnect();
}

void SubscriberInstance::SetHistoricalReplayInterval(int32_t replayInterval)
{
    if (m_subscriber.IsSubscribed())
    {
        replayInterval = m_endianConverter.ConvertBigEndian(replayInterval);
        m_subscriber.SendServerCommand(tst::ServerCommand::UpdateProcessingInterval, (gsfts::uint8_t*)&replayInterval, 0, 4);
    }
}

void* SubscriberInstance::GetUserData() const
{
    return m_userData;
}

void SubscriberInstance::SetUserData(void* userData)
{
    m_userData = userData;
}

bool SubscriberInstance::IsMetadataCompressed() const
{
    return m_subscriber.IsMetadataCompressed();
}

void SubscriberInstance::SetMetadataCompressed(bool compressed)
{
    m_subscriber.SetMetadataCompressed(compressed);
}

long SubscriberInstance::GetTotalCommandChannelBytesReceived() const
{
    return m_subscriber.GetTotalCommandChannelBytesReceived();
}

long SubscriberInstance::GetTotalDataChannelBytesReceived() const
{
    return m_subscriber.GetTotalDataChannelBytesReceived();
}

long SubscriberInstance::GetTotalMeasurementsReceived() const
{
    return m_subscriber.GetTotalMeasurementsReceived();
}

bool SubscriberInstance::IsConnected() const
{
    return m_subscriber.IsConnected();
}

bool SubscriberInstance::IsSubscribed() const
{
    return m_subscriber.IsSubscribed();
}

// protected functions

// All the following protected functions are virtual so that derived
// classes can customize behavior of the SubscriberInstance

tst::SubscriberConnector SubscriberInstance::CreateSubscriberConnector()
{
    // SubscriberConnector is another helper object which allows the
    // user to modify settings for auto-reconnects and retry cycles.
    tst::SubscriberConnector connector;

    // Register callbacks
    connector.RegisterErrorMessageCallback(&HandleErrorMessage);
    connector.RegisterReconnectCallback(&HandleResubscribe);

    connector.SetHostname(m_hostname);
    connector.SetPort(m_port);
    connector.SetMaxRetries(-1);
    connector.SetRetryInterval(5000);
    connector.SetAutoReconnect(true);

    return connector;
}

tst::SubscriptionInfo SubscriberInstance::CreateSubscriptionInfo()
{
    // SubscriptionInfo is a helper object which allows the user
    // to set up their subscription and reuse subscription settings.
    tst::SubscriptionInfo info;

    // Define desired filter expression
    info.FilterExpression = m_filterExpression;

    // To set up a remotely synchronized subscription, set this flag
    // to true and add the framesPerSecond parameter to the
    // ExtraConnectionStringParameters. Additionally, the following
    // example demonstrates the use of some other useful parameters
    // when setting up remotely synchronized subscriptions.
    //
    //info.RemotelySynchronized = true;
    //info.ExtraConnectionStringParameters = "framesPerSecond=30;timeResolution=10000;downsamplingMethod=Closest";

    info.RemotelySynchronized = false;
    info.Throttled = false;

    info.UdpDataChannel = false;

    info.IncludeTime = true;
    info.LagTime = 3.0;
    info.LeadTime = 1.0;
    info.UseLocalClockAsRealTime = false;
    info.UseMillisecondResolution = true;

    return info;
}

void SubscriberInstance::StatusMessage(std::string message)
{
    std::cout << message << std::endl << std::endl;
}

void SubscriberInstance::ErrorMessage(std::string message)
{
    std::cerr << message << std::endl << std::endl;
}

void SubscriberInstance::DataStartTime(std::time_t unixSOC, int milliseconds)
{
}

void SubscriberInstance::ReceivedMetadata(std::vector<uint8_t> payload)
{
}

void SubscriberInstance::ReceivedNewMeasurements(std::vector<gsfts::Measurement> measurements)
{
}

void SubscriberInstance::ConfigurationChanged()
{
    StatusMessage("Configuration changed");
}

void SubscriberInstance::HistoricalReadComplete()
{
    StatusMessage("Historical read complete");
}

void SubscriberInstance::ConnectionEstablished()
{
    StatusMessage("Connection established");
}

void SubscriberInstance::ConnectionTerminated()
{
    StatusMessage("Connection terminated");
}

// private functions

// The following member methods are defined as static so they
// can be used as callback registrations for DataSubscriber

void SubscriberInstance::HandleResubscribe(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    if (source->IsConnected())
    {
        instance->ConnectionEstablished();
        source->Subscribe(instance->m_info);
    }
}

void SubscriberInstance::HandleStatusMessage(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->StatusMessage(message);
}

void SubscriberInstance::HandleErrorMessage(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ErrorMessage(message);
}

void SubscriberInstance::HandleDataStartTime(tst::DataSubscriber* source, gsfts::int64_t startTime)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    std::time_t unixSOC;
    int milliseconds;

    gsfts::GetUnixTime(startTime, unixSOC, milliseconds);

    instance->DataStartTime(unixSOC, milliseconds);
}

void SubscriberInstance::HandleMetadata(tst::DataSubscriber* source, std::vector<uint8_t> payload)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    // Call virtual method to handle metadata payload
    instance->ReceivedMetadata(payload);

    // Start subscription after successful user meta-data handling
    source->Subscribe(instance->m_info);
}

void SubscriberInstance::HandleNewMeasurements(tst::DataSubscriber* source, std::vector<gsfts::Measurement> measurements)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ReceivedNewMeasurements(measurements);
}

void SubscriberInstance::HandleConfigurationChanged(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();

    // Call virtual method to notify consumer that configuration has changed
    instance->ConfigurationChanged();

    // When publisher configuration has changed, request updated metadata
    source->SendServerCommand(tst::ServerCommand::MetadataRefresh);
}

void SubscriberInstance::HandleProcessingComplete(tst::DataSubscriber* source, std::string message)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->StatusMessage(message);
    instance->HistoricalReadComplete();
}

void SubscriberInstance::HandleConnectionTerminated(tst::DataSubscriber* source)
{
    SubscriberInstance* instance = (SubscriberInstance*)source->GetUserData();
    instance->ConnectionTerminated();
}<|endoftext|>


<commit_before>/* ************************************************************************
 * Copyright 2018 Advanced Micro Devices, Inc.
 * ************************************************************************ */

#include "rocsparse.h"
#include "definitions.h"
#include "handle.h"
#include "utility.h"
#include "coomv_device.h"

#include <hip/hip_runtime.h>

template <typename T, rocsparse_int BLOCKSIZE, rocsparse_int WARPSIZE>
__global__ void coomvn_warp_host_pointer(rocsparse_int nnz,
                                         rocsparse_int loops,
                                         T alpha,
                                         const rocsparse_int* coo_row_ind,
                                         const rocsparse_int* coo_col_ind,
                                         const T* coo_val,
                                         const T* x,
                                         T* y,
                                         rocsparse_int* row_block_red,
                                         T* val_block_red)
{
    coomvn_general_warp_reduce<T, BLOCKSIZE, WARPSIZE>(
        nnz, loops, alpha, coo_row_ind, coo_col_ind, coo_val, x, y, row_block_red, val_block_red);
}

template <typename T, rocsparse_int BLOCKSIZE, rocsparse_int WARPSIZE>
__global__ void coomvn_warp_device_pointer(rocsparse_int nnz,
                                           rocsparse_int loops,
                                           T* alpha,
                                           const rocsparse_int* coo_row_ind,
                                           const rocsparse_int* coo_col_ind,
                                           const T* coo_val,
                                           const T* x,
                                           T* y,
                                           rocsparse_int* row_block_red,
                                           T* val_block_red)
{
    coomvn_general_warp_reduce<T, BLOCKSIZE, WARPSIZE>(
        nnz, loops, *alpha, coo_row_ind, coo_col_ind, coo_val, x, y, row_block_red, val_block_red);
}

template <typename T, rocsparse_int BLOCKSIZE>
__global__ void coomvn_block_reduce(rocsparse_int nnz,
                                    const rocsparse_int* row_block_red,
                                    const T* val_block_red,
                                    T* y)
{
    coomvn_general_block_reduce<T, BLOCKSIZE>(nnz, row_block_red, val_block_red, y);
}

/*! \brief SPARSE Level 2 API

    \details
    coomv  multiplies the dense vector x[i] with scalar alpha and sparse m x n
    matrix A that is defined in COO storage format and add the result to y[i]
    that is multiplied by beta, for  i = 1 , … , n

        y := alpha * op(A) * x + beta * y,

    @param[in]
    handle      rocsparse_handle.
                handle to the rocsparse library context queue.
    @param[in]
    trans       operation type of A.
    @param[in]
    m           number of rows of A.
    @param[in]
    n           number of columns of A.
    @param[in]
    nnz         number of non-zero entries of A.
    @param[in]
    alpha       scalar alpha.
    @param[in]
    descr       descriptor of A.
    @param[in]
    coo_val     array of nnz elements of A.
    @param[in]
    coo_row_ind array of nnz elements containing the row indices of A.
    @param[in]
    coo_col_ind array of nnz elements containing the column indices of A.
    @param[in]
    x           array of n elements (op(A) = A) or m elements (op(A) = A^T or
                op(A) = A^H).
    @param[in]
    beta        scalar beta.
    @param[inout]
    y           array of m elements (op(A) = A) or n elements (op(A) = A^T or
                op(A) = A^H).

    ********************************************************************/
template <typename T>
rocsparse_status rocsparse_coomv_template(rocsparse_handle handle,
                                          rocsparse_operation trans,
                                          rocsparse_int m,
                                          rocsparse_int n,
                                          rocsparse_int nnz,
                                          const T* alpha,
                                          const rocsparse_mat_descr descr,
                                          const T* coo_val,
                                          const rocsparse_int* coo_row_ind,
                                          const rocsparse_int* coo_col_ind,
                                          const T* x,
                                          const T* beta,
                                          T* y)
{
    // Check for valid handle and matrix descriptor
    if(handle == nullptr)
    {
        return rocsparse_status_invalid_handle;
    }
    else if(descr == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }

    // Logging TODO bench logging
    if(handle->pointer_mode == rocsparse_pointer_mode_host)
    {
        log_trace(handle,
                  replaceX<T>("rocsparse_Xcoomv"),
                  trans,
                  m,
                  n,
                  nnz,
                  *alpha,
                  (const void*&)descr,
                  (const void*&)coo_val,
                  (const void*&)coo_row_ind,
                  (const void*&)coo_col_ind,
                  (const void*&)x,
                  *beta,
                  (const void*&)y);
    }
    else
    {
        log_trace(handle,
                  replaceX<T>("rocsparse_Xcoomv"),
                  trans,
                  m,
                  n,
                  nnz,
                  (const void*&)alpha,
                  (const void*&)descr,
                  (const void*&)coo_val,
                  (const void*&)coo_row_ind,
                  (const void*&)coo_col_ind,
                  (const void*&)x,
                  (const void*&)beta,
                  (const void*&)y);
    }

    // Check matrix type
    if(descr->base != rocsparse_index_base_zero)
    {
        // TODO
        return rocsparse_status_not_implemented;
    }
    if(descr->type != rocsparse_matrix_type_general)
    {
        // TODO
        return rocsparse_status_not_implemented;
    }

    // Check sizes
    if(m < 0)
    {
        return rocsparse_status_invalid_size;
    }
    else if(n < 0)
    {
        return rocsparse_status_invalid_size;
    }
    else if(nnz < 0)
    {
        return rocsparse_status_invalid_size;
    }

    // Check pointer arguments
    if(coo_val == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(coo_row_ind == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(coo_col_ind == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(x == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(y == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(alpha == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(beta == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }

    // Quick return if possible
    if(m == 0 || n == 0 || nnz == 0)
    {
        return rocsparse_status_success;
    }

    // Stream
    hipStream_t stream = handle->stream;

    // Run different coomv kernels
    if(trans == rocsparse_operation_none)
    {
#define COOMVN_DIM 128
        rocsparse_int maxthreads = handle->properties.maxThreadsPerBlock;
        rocsparse_int nprocs     = handle->properties.multiProcessorCount;
        rocsparse_int maxblocks  = (nprocs * maxthreads - 1) / COOMVN_DIM + 1;
        rocsparse_int minblocks  = (nnz - 1) / COOMVN_DIM + 1;

        rocsparse_int nblocks = maxblocks < minblocks ? maxblocks : minblocks;
        rocsparse_int nwarps  = nblocks * (COOMVN_DIM / handle->warp_size);
        rocsparse_int nloops  = (nnz / handle->warp_size + 1) / nwarps + 1;

        dim3 coomvn_blocks(nblocks);
        dim3 coomvn_threads(COOMVN_DIM);

        rocsparse_int* row_block_red = NULL;
        T* val_block_red             = NULL;

        RETURN_IF_HIP_ERROR(hipMalloc((void**)&row_block_red, sizeof(rocsparse_int) * nwarps));
        RETURN_IF_HIP_ERROR(hipMalloc((void**)&val_block_red, sizeof(T) * nwarps));

        if(handle->pointer_mode == rocsparse_pointer_mode_device)
        {
            if(handle->warp_size == 32)
            {
                return rocsparse_status_not_implemented;
            }
            else if(handle->warp_size == 64)
            {
                return rocsparse_status_not_implemented;
            }
            else
            {
                return rocsparse_status_arch_mismatch;
            }
        }
        else
        {
            if(*alpha == 0.0 && *beta == 1.0)
            {
                return rocsparse_status_success;
            }

            // If beta == 0.0 we need to set y to 0
            if(*beta == 0.0)
            {
                RETURN_IF_HIP_ERROR(hipMemset(y, 0, sizeof(T) * m));
            }
            else if(*beta != 1.0)
            {
                // Scale y by beta
                // scale y TODO
                return rocsparse_status_not_implemented;
            }

            if(handle->warp_size == 32)
            {
                return rocsparse_status_not_implemented;
            }
            else if(handle->warp_size == 64)
            {
                hipLaunchKernelGGL((coomvn_warp_host_pointer<T, COOMVN_DIM, 64>),
                                   coomvn_blocks,
                                   coomvn_threads,
                                   0,
                                   stream,
                                   nnz,
                                   nloops,
                                   *alpha,
                                   coo_row_ind,
                                   coo_col_ind,
                                   coo_val,
                                   x,
                                   y,
                                   row_block_red,
                                   val_block_red);
            }
            else
            {
                return rocsparse_status_arch_mismatch;
            }
        }

        hipLaunchKernelGGL((coomvn_block_reduce<T, COOMVN_DIM>),
                           dim3(1),
                           coomvn_threads,
                           0,
                           stream,
                           nwarps,
                           row_block_red,
                           val_block_red,
                           y);

        RETURN_IF_HIP_ERROR(hipFree(row_block_red));
        RETURN_IF_HIP_ERROR(hipFree(val_block_red));
#undef COOMVN_DIM
    }
    else
    {
        // TODO
        return rocsparse_status_not_implemented;
    }
    return rocsparse_status_success;
}

/*
 * ===========================================================================
 *    C wrapper
 * ===========================================================================
 */

extern "C" rocsparse_status rocsparse_scoomv(rocsparse_handle handle,
                                             rocsparse_operation trans,
                                             rocsparse_int m,
                                             rocsparse_int n,
                                             rocsparse_int nnz,
                                             const float* alpha,
                                             const rocsparse_mat_descr descr,
                                             const float* coo_val,
                                             const rocsparse_int* coo_row_ind,
                                             const rocsparse_int* coo_col_ind,
                                             const float* x,
                                             const float* beta,
                                             float* y)
{
    return rocsparse_coomv_template<float>(
        handle, trans, m, n, nnz, alpha, descr, coo_val, coo_row_ind, coo_col_ind, x, beta, y);
}

extern "C" rocsparse_status rocsparse_dcoomv(rocsparse_handle handle,
                                             rocsparse_operation trans,
                                             rocsparse_int m,
                                             rocsparse_int n,
                                             rocsparse_int nnz,
                                             const double* alpha,
                                             const rocsparse_mat_descr descr,
                                             const double* coo_val,
                                             const rocsparse_int* coo_row_ind,
                                             const rocsparse_int* coo_col_ind,
                                             const double* x,
                                             const double* beta,
                                             double* y)
{
    return rocsparse_coomv_template<double>(
        handle, trans, m, n, nnz, alpha, descr, coo_val, coo_row_ind, coo_col_ind, x, beta, y);
}
<commit_msg>added support for other warpsizes and arbitrary beta<commit_after>/* ************************************************************************
 * Copyright 2018 Advanced Micro Devices, Inc.
 * ************************************************************************ */

#include "rocsparse.h"
#include "definitions.h"
#include "handle.h"
#include "utility.h"
#include "coomv_device.h"

#include <hip/hip_runtime.h>

template <typename T, rocsparse_int BLOCKSIZE, rocsparse_int WARPSIZE>
__global__ void coomvn_warp_host_pointer(rocsparse_int nnz,
                                         rocsparse_int loops,
                                         T alpha,
                                         const rocsparse_int* coo_row_ind,
                                         const rocsparse_int* coo_col_ind,
                                         const T* coo_val,
                                         const T* x,
                                         T* y,
                                         rocsparse_int* row_block_red,
                                         T* val_block_red)
{
    coomvn_general_warp_reduce<T, BLOCKSIZE, WARPSIZE>(
        nnz, loops, alpha, coo_row_ind, coo_col_ind, coo_val, x, y, row_block_red, val_block_red);
}

template <typename T, rocsparse_int BLOCKSIZE, rocsparse_int WARPSIZE>
__global__ void coomvn_warp_device_pointer(rocsparse_int nnz,
                                           rocsparse_int loops,
                                           T* alpha,
                                           const rocsparse_int* coo_row_ind,
                                           const rocsparse_int* coo_col_ind,
                                           const T* coo_val,
                                           const T* x,
                                           T* y,
                                           rocsparse_int* row_block_red,
                                           T* val_block_red)
{
    coomvn_general_warp_reduce<T, BLOCKSIZE, WARPSIZE>(
        nnz, loops, *alpha, coo_row_ind, coo_col_ind, coo_val, x, y, row_block_red, val_block_red);
}

/*! \brief SPARSE Level 2 API

    \details
    coomv  multiplies the dense vector x[i] with scalar alpha and sparse m x n
    matrix A that is defined in COO storage format and add the result to y[i]
    that is multiplied by beta, for  i = 1 , … , n

        y := alpha * op(A) * x + beta * y,

    @param[in]
    handle      rocsparse_handle.
                handle to the rocsparse library context queue.
    @param[in]
    trans       operation type of A.
    @param[in]
    m           number of rows of A.
    @param[in]
    n           number of columns of A.
    @param[in]
    nnz         number of non-zero entries of A.
    @param[in]
    alpha       scalar alpha.
    @param[in]
    descr       descriptor of A.
    @param[in]
    coo_val     array of nnz elements of A.
    @param[in]
    coo_row_ind array of nnz elements containing the row indices of A.
    @param[in]
    coo_col_ind array of nnz elements containing the column indices of A.
    @param[in]
    x           array of n elements (op(A) = A) or m elements (op(A) = A^T or
                op(A) = A^H).
    @param[in]
    beta        scalar beta.
    @param[inout]
    y           array of m elements (op(A) = A) or n elements (op(A) = A^T or
                op(A) = A^H).

    ********************************************************************/
template <typename T>
rocsparse_status rocsparse_coomv_template(rocsparse_handle handle,
                                          rocsparse_operation trans,
                                          rocsparse_int m,
                                          rocsparse_int n,
                                          rocsparse_int nnz,
                                          const T* alpha,
                                          const rocsparse_mat_descr descr,
                                          const T* coo_val,
                                          const rocsparse_int* coo_row_ind,
                                          const rocsparse_int* coo_col_ind,
                                          const T* x,
                                          const T* beta,
                                          T* y)
{
    // Check for valid handle and matrix descriptor
    if(handle == nullptr)
    {
        return rocsparse_status_invalid_handle;
    }
    else if(descr == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }

    // Logging TODO bench logging
    if(handle->pointer_mode == rocsparse_pointer_mode_host)
    {
        log_trace(handle,
                  replaceX<T>("rocsparse_Xcoomv"),
                  trans,
                  m,
                  n,
                  nnz,
                  *alpha,
                  (const void*&)descr,
                  (const void*&)coo_val,
                  (const void*&)coo_row_ind,
                  (const void*&)coo_col_ind,
                  (const void*&)x,
                  *beta,
                  (const void*&)y);
    }
    else
    {
        log_trace(handle,
                  replaceX<T>("rocsparse_Xcoomv"),
                  trans,
                  m,
                  n,
                  nnz,
                  (const void*&)alpha,
                  (const void*&)descr,
                  (const void*&)coo_val,
                  (const void*&)coo_row_ind,
                  (const void*&)coo_col_ind,
                  (const void*&)x,
                  (const void*&)beta,
                  (const void*&)y);
    }

    // Check matrix type
    if(descr->base != rocsparse_index_base_zero)
    {
        // TODO
        return rocsparse_status_not_implemented;
    }
    if(descr->type != rocsparse_matrix_type_general)
    {
        // TODO
        return rocsparse_status_not_implemented;
    }

    // Check sizes
    if(m < 0)
    {
        return rocsparse_status_invalid_size;
    }
    else if(n < 0)
    {
        return rocsparse_status_invalid_size;
    }
    else if(nnz < 0)
    {
        return rocsparse_status_invalid_size;
    }

    // Check pointer arguments
    if(coo_val == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(coo_row_ind == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(coo_col_ind == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(x == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(y == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(alpha == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }
    else if(beta == nullptr)
    {
        return rocsparse_status_invalid_pointer;
    }

    // Quick return if possible
    if(m == 0 || n == 0 || nnz == 0)
    {
        return rocsparse_status_success;
    }

    // Stream
    hipStream_t stream = handle->stream;

    // Run different coomv kernels
    if(trans == rocsparse_operation_none)
    {
#define COOMVN_DIM 128
        rocsparse_int maxthreads = handle->properties.maxThreadsPerBlock;
        rocsparse_int nprocs     = handle->properties.multiProcessorCount;
        rocsparse_int maxblocks  = (nprocs * maxthreads - 1) / COOMVN_DIM + 1;
        rocsparse_int minblocks  = (nnz - 1) / COOMVN_DIM + 1;

        rocsparse_int nblocks = maxblocks < minblocks ? maxblocks : minblocks;
        rocsparse_int nwarps  = nblocks * (COOMVN_DIM / handle->warp_size);
        rocsparse_int nloops  = (nnz / handle->warp_size + 1) / nwarps + 1;

        dim3 coomvn_blocks(nblocks);
        dim3 coomvn_threads(COOMVN_DIM);

        rocsparse_int* row_block_red = NULL;
        T* val_block_red             = NULL;

        RETURN_IF_HIP_ERROR(hipMalloc((void**)&row_block_red, sizeof(rocsparse_int) * nwarps));
        RETURN_IF_HIP_ERROR(hipMalloc((void**)&val_block_red, sizeof(T) * nwarps));

        if(handle->pointer_mode == rocsparse_pointer_mode_device)
        {
            // We need a host copy of beta to avoid unneccessary kernel launch
            T h_beta;
            RETURN_IF_HIP_ERROR(hipMemcpy(&h_beta, beta, sizeof(T), hipMemcpyDeviceToHost));

            if(h_beta == static_cast<T>(0))
            {
                RETURN_IF_HIP_ERROR(hipMemset(y, 0, sizeof(T) * m));
            }
            else if(h_beta != static_cast<T>(1))
            {
                hipLaunchKernelGGL((coomv_scale<T>),
                                   dim3((m - 1) / COOMVN_DIM + 1),
                                   coomvn_threads,
                                   0,
                                   stream,
                                   m,
                                   h_beta,
                                   y);
            }

            if(handle->warp_size == 32)
            {
                hipLaunchKernelGGL((coomvn_warp_device_pointer<T, COOMVN_DIM, 32>),
                                   coomvn_blocks,
                                   coomvn_threads,
                                   0,
                                   stream,
                                   nnz,
                                   nloops,
                                   alpha,
                                   coo_row_ind,
                                   coo_col_ind,
                                   coo_val,
                                   x,
                                   y,
                                   row_block_red,
                                   val_block_red);
            }
            else if(handle->warp_size == 64)
            {
                hipLaunchKernelGGL((coomvn_warp_device_pointer<T, COOMVN_DIM, 64>),
                                   coomvn_blocks,
                                   coomvn_threads,
                                   0,
                                   stream,
                                   nnz,
                                   nloops,
                                   alpha,
                                   coo_row_ind,
                                   coo_col_ind,
                                   coo_val,
                                   x,
                                   y,
                                   row_block_red,
                                   val_block_red);
            }
            else
            {
                return rocsparse_status_arch_mismatch;
            }
        }
        else
        {
            if(*alpha == static_cast<T>(0) && *beta == static_cast<T>(1))
            {
                return rocsparse_status_success;
            }

            // If beta == 0.0 we need to set y to 0
            if(*beta == static_cast<T>(0))
            {
                RETURN_IF_HIP_ERROR(hipMemset(y, 0, sizeof(T) * m));
            }
            else if(*beta != static_cast<T>(1))
            {
                hipLaunchKernelGGL((coomv_scale<T>),
                                   dim3((m - 1) / COOMVN_DIM + 1),
                                   coomvn_threads,
                                   0,
                                   stream,
                                   m,
                                   *beta,
                                   y);
            }

            if(handle->warp_size == 32)
            {
                hipLaunchKernelGGL((coomvn_warp_host_pointer<T, COOMVN_DIM, 32>),
                                   coomvn_blocks,
                                   coomvn_threads,
                                   0,
                                   stream,
                                   nnz,
                                   nloops,
                                   *alpha,
                                   coo_row_ind,
                                   coo_col_ind,
                                   coo_val,
                                   x,
                                   y,
                                   row_block_red,
                                   val_block_red);
            }
            else if(handle->warp_size == 64)
            {
                hipLaunchKernelGGL((coomvn_warp_host_pointer<T, COOMVN_DIM, 64>),
                                   coomvn_blocks,
                                   coomvn_threads,
                                   0,
                                   stream,
                                   nnz,
                                   nloops,
                                   *alpha,
                                   coo_row_ind,
                                   coo_col_ind,
                                   coo_val,
                                   x,
                                   y,
                                   row_block_red,
                                   val_block_red);
            }
            else
            {
                return rocsparse_status_arch_mismatch;
            }
        }

        hipLaunchKernelGGL((coomvn_general_block_reduce<T, COOMVN_DIM>),
                           dim3(1),
                           coomvn_threads,
                           0,
                           stream,
                           nwarps,
                           row_block_red,
                           val_block_red,
                           y);

        RETURN_IF_HIP_ERROR(hipFree(row_block_red));
        RETURN_IF_HIP_ERROR(hipFree(val_block_red));
#undef COOMVN_DIM
    }
    else
    {
        // TODO
        return rocsparse_status_not_implemented;
    }
    return rocsparse_status_success;
}

/*
 * ===========================================================================
 *    C wrapper
 * ===========================================================================
 */

extern "C" rocsparse_status rocsparse_scoomv(rocsparse_handle handle,
                                             rocsparse_operation trans,
                                             rocsparse_int m,
                                             rocsparse_int n,
                                             rocsparse_int nnz,
                                             const float* alpha,
                                             const rocsparse_mat_descr descr,
                                             const float* coo_val,
                                             const rocsparse_int* coo_row_ind,
                                             const rocsparse_int* coo_col_ind,
                                             const float* x,
                                             const float* beta,
                                             float* y)
{
    return rocsparse_coomv_template<float>(
        handle, trans, m, n, nnz, alpha, descr, coo_val, coo_row_ind, coo_col_ind, x, beta, y);
}

extern "C" rocsparse_status rocsparse_dcoomv(rocsparse_handle handle,
                                             rocsparse_operation trans,
                                             rocsparse_int m,
                                             rocsparse_int n,
                                             rocsparse_int nnz,
                                             const double* alpha,
                                             const rocsparse_mat_descr descr,
                                             const double* coo_val,
                                             const rocsparse_int* coo_row_ind,
                                             const rocsparse_int* coo_col_ind,
                                             const double* x,
                                             const double* beta,
                                             double* y)
{
    return rocsparse_coomv_template<double>(
        handle, trans, m, n, nnz, alpha, descr, coo_val, coo_row_ind, coo_col_ind, x, beta, y);
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 7/28/2019, 1:18:49 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}

class UnionFind
{
  vector<long long> par;

public:
  UnionFind() {}
  UnionFind(int n) : par(n, -1) {}

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }

private:
  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }
};

class RollingHash
{ // S の方を変更する処理はまだ書いていない。
  string S;
  static mint B;
  vector<mint> H;

public:
  RollingHash(string s, int t = -1) : S{s}
  {
    if (t == -1)
    {
      t = s.size();
    }
    assert(1 <= t && t <= static_cast<int>(s.size()));
    H = make_init_hash(t);
  }

  RollingHash(string s, size_t t)
  {
    RollingHash{s, static_cast<int>(t)};
#if DEBUG == 1
    cerr << "t = " << t << endl;
    cerr << "static_cast<int>(t) = " << static_cast<int>(t) << endl;
#endif
  }

  size_t size() { return S.size() + 1u - H.size(); }

  const mint operator[](size_t t) const { return H[t]; }

private:
  mint Sm(size_t k) { return static_cast<mint>(S[k]); }
  vector<mint> make_init_hash(int);
};

mint RollingHash::B = 1234567;

vector<mint> RollingHash::make_init_hash(int t)
{
  vector<mint> res(S.size() + 1 - t);
  mint now = 0;
  const mint pb = B.power(t);
  for (auto i = 0; i < t; i++)
  {
    now = now * B + Sm(i);
  }
  res[0] = now;
  for (auto i = 0u; i < res.size() - 1; i++)
  {
    res[i + 1] = res[i] * B - Sm(i) * pb + Sm(i + t);
  }
  return res;
}

int main()
{
  string S, T;
  cin >> S >> T;
  int N = S.size();
  stringstream U{};
  U << S << S << S;
  while (U.str().size() < T.size() * 2)
  {
    U << S;
  }
  S = U.str();
  vector<bool> ok(N, false);
  RollingHash rh_S{S, T.size()};
  RollingHash rh_T{T};
  const mint base = rh_T[0];
#if DEBUG == 1
  cerr << "rh_S.size() = " << rh_S.size() << endl;
  cerr << "rh_T.size() = " << rh_T.size() << endl;
  cerr << "base = " << base << endl;
#endif
  for (auto i = 0; i < N; i++)
  {
    ok[i] = (rh_S[i] == base);
#if DEBUG == 1
    cerr << "rh_S[" << i << "] = " << rh_S[i] << endl;
    if (ok[i])
    {
      cerr << "ok[" << i << "]" << endl;
    }
#endif
  }
  UnionFind uf{N};
  for (auto i = 0; i < N; i++)
  {
    int j = (i + T.size()) % N;
    if (ok[i] && ok[j])
    {
      if (!uf.merge(i, j))
      {
        No();
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    if (ok[i])
    {
      maxs(ans, uf.size(i));
    }
  }
  cout << ans << endl;
}<commit_msg>tried F.cpp to 'F'<commit_after>#define DEBUG 1
/**
 * File    : F.cpp
 * Author  : Kazune Takahashi
 * Created : 7/28/2019, 1:18:49 AM
 * Powered by Visual Studio Code
 */
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <string>
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <functional>
#include <random>
#include <chrono>
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define maxs(x, y) (x = max(x, y))
#define mins(x, y) (x = min(x, y))
using ll = long long;
class mint
{
public:
  static ll MOD;
  ll x;
  mint() : x(0) {}
  mint(ll x) : x(x % MOD) {}
  mint operator-() const { return x ? MOD - x : 0; }
  mint &operator+=(const mint &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  mint &operator-=(const mint &a) { return *this += -a; }
  mint &operator*=(const mint &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  mint &operator/=(const mint &a)
  {
    mint b{a};
    return *this *= b.power(MOD - 2);
  }
  mint operator+(const mint &a) const { return mint(*this) += a; }
  mint operator-(const mint &a) const { return mint(*this) -= a; }
  mint operator*(const mint &a) const { return mint(*this) *= a; }
  mint operator/(const mint &a) const { return mint(*this) /= a; }
  bool operator<(const mint &a) const { return x < a.x; }
  bool operator==(const mint &a) const { return x == a.x; }
  const mint power(ll N)
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      mint half = power(N / 2);
      return half * half;
    }
  }
};
ll mint::MOD = 1e9 + 7;
istream &operator>>(istream &stream, mint &a) { return stream >> a.x; }
ostream &operator<<(ostream &stream, const mint &a) { return stream << a.x; }
class combination
{
public:
  vector<mint> inv, fact, factinv;
  static int MAX_SIZE;
  combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i = 2; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[mint::MOD % i]) * (mint::MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i = 1; i < MAX_SIZE; i++)
    {
      fact[i] = mint(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  mint operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
};
int combination::MAX_SIZE = 3000010;
ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
// constexpr double epsilon = 1e-10;
// constexpr ll infty = 1000000000000000LL;
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "-1" << endl;
  exit(0);
}

class UnionFind
{
  vector<long long> par;

public:
  UnionFind() {}
  UnionFind(int n) : par(n, -1) {}

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }

private:
  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }
};

class RollingHash
{ // S の方を変更する処理はまだ書いていない。
  string S;
  static mint B;
  vector<mint> H;

public:
  RollingHash(string s, int t = -1) : S{s}
  {
    if (t == -1)
    {
      t = s.size();
    }
    assert(1 <= t && t <= static_cast<int>(s.size()));
    H = make_init_hash(t);
  }

  RollingHash(string s, size_t t)
  {
    RollingHash{s, static_cast<int>(t)};
  }

  size_t size() { return S.size() + 1u - H.size(); }

  const mint operator[](size_t t) const { return H[t]; }

private:
  mint Sm(size_t k) { return static_cast<mint>(S[k]); }
  vector<mint> make_init_hash(int);
};

mint RollingHash::B = 1234567;

vector<mint> RollingHash::make_init_hash(int t)
{
  vector<mint> res(S.size() + 1 - t);
  mint now = 0;
  const mint pb = B.power(t);
  for (auto i = 0; i < t; i++)
  {
    now = now * B + Sm(i);
  }
  res[0] = now;
  for (auto i = 0u; i < res.size() - 1; i++)
  {
    res[i + 1] = res[i] * B - Sm(i) * pb + Sm(i + t);
  }
  return res;
}

int main()
{
  string S, T;
  cin >> S >> T;
  int N = S.size();
  stringstream U{};
  U << S << S << S;
  while (U.str().size() < T.size() * 2)
  {
    U << S;
  }
  S = U.str();
#if DEBUG == 1
  cerr << "S = " << S << endl;
#endif
  vector<bool> ok(N, false);
  RollingHash rh_S{S, T.size()};
  RollingHash rh_T{T};
  const mint base = rh_T[0];
#if DEBUG == 1
  cerr << "rh_S.size() = " << rh_S.size() << endl;
  cerr << "rh_T.size() = " << rh_T.size() << endl;
  cerr << "base = " << base << endl;
#endif
  for (auto i = 0; i < N; i++)
  {
    ok[i] = (rh_S[i] == base);
#if DEBUG == 1
    cerr << "rh_S[" << i << "] = " << rh_S[i] << endl;
    if (ok[i])
    {
      cerr << "ok[" << i << "]" << endl;
    }
#endif
  }
  UnionFind uf{N};
  for (auto i = 0; i < N; i++)
  {
    int j = (i + T.size()) % N;
    if (ok[i] && ok[j])
    {
      if (!uf.merge(i, j))
      {
        No();
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; i++)
  {
    if (ok[i])
    {
      maxs(ans, uf.size(i));
    }
  }
  cout << ans << endl;
}<|endoftext|>