Example #1
0
  void playWithHomeTheater() {

    // Create all the parts of the home theatre system
    Amplifier amp("Top-O-Line Amplifier");
    CdPlayer cd("Top-O-Line CD Player", &amp);
    DvdPlayer dvd("Top-O-Line DVD Player", &amp);
    Screen screen("My Theater Screen");
    PopcornPopper popper("My Popcorn Popper");
    Tuner tuner("Top-O-Line AM/FM Tuner", &amp);
    TheaterLights lights("Theater Ceiling Lights");
    Projector projector("Top-O-Line Projector");

    popper.on();  // Turn on the popcorn popper...
    popper.pop(); // and start popping...

    lights.dim(10); // Dim the lights to 10%... 
    
    screen.down();  // Put the screen down...

    projector.on();             // Turn on the projector...
    projector.setInput(&dvd);    // set it to DVD...
    projector.wideScreenMode(); // and put it on wide screen mode for the movie...

    amp.on();                // Turn on the amp...
    amp.setInput(&dvd);       // set it to DVD and...
    amp.setSurroundSound();  // put it into surround sound mode...
    amp.setVolume(11);       // and set the volume to 11...

    dvd.on();                            // Turn on the DVD player...
    dvd.play("Raiders of the lost ark"); // and FINALLY, play the movie!

    // What about shutting everything down again?!
    // How would you play a CD? etc...
  }
EKFState getTunedKalmanState_Gradient( EKFState begin, 
									   EKFState step, 
									   std::vector<dmod::array1d> signals, 
									   int iterationsNumber )
{
	FilterTuning::GradientTuner tuner(signals, iterationsNumber, begin, step);
	EKFState tunedParameters = tuner.tune();
	return tunedParameters;
}
Example #3
0
  void playWithHomeTheaterFacade() {
    // Create all the parts of the home theatre system
    // Not encapsulated or owned by the facade.
    Amplifier amp("Top-O-Line Amplifier");
    CdPlayer cd("Top-O-Line CD Player", &amp);
    DvdPlayer dvd("Top-O-Line DVD Player", &amp);
    Screen screen("My Theater Screen");
    PopcornPopper popper("My Popcorn Popper");
    Tuner tuner("Top-O-Line AM/FM Tuner", &amp);
    TheaterLights lights("Theater Ceiling Lights");
    Projector projector("Top-O-Line Projector");

    HomeTheaterFacade theater(&amp, &tuner, &dvd, &cd, &projector, &lights, &screen, &popper);
    theater.watchMovie("Raiders of the Lost Ark");
    theater.endMovie();
  }
/////////////////////
///Tuning///////////
/////////////////////
EKFState getTunedKalmanState_TotalSearch( std::vector<dmod::array1d> signals, 
										  size_t filtersAmount, 
										  std::default_random_engine &gen )
{
	//Creation of EKF tuned by TotalSearch
	EKFState minimal;
	EKFState maximal;

	minimal.state = Eigen::Vector4d(0, 0, 0.00, 0);
	minimal.Rw <<
		0.01, 0, 0, 0,
		0, 0.01, 0, 0,
		0, 0, 0.001, 0,
		0, 0, 0, 0.002;
	minimal.R = minimal.Rw;
	minimal.Rn = 0.1;

	maximal.state = Eigen::Vector4d(255, 10, 0.6, 2 * M_PI);
	maximal.Rw <<
		0.5, 0, 0, 0,
		0, 0.5, 0, 0,
		0, 0, 0.1, 0,
		0, 0, 0, 0.2;
	maximal.R = maximal.Rw;
	maximal.Rn = 10;

	//minimal.state = Eigen::Vector4d(0, 0, 0.00, 0);
	//minimal.Rw <<
	//	0.2, 0, 0, 0,
	//	0, 0.05, 0, 0,
	//	0, 0, 0.001, 0,
	//	0, 0, 0, 0.002;
	//minimal.R = minimal.Rw;
	//minimal.Rn = 0.1;

	//maximal.state = Eigen::Vector4d(255, 5, 0.3, 2 * M_PI);
	//maximal.Rw = minimal.Rw;
	//maximal.R = maximal.Rw;
	//maximal.Rn = 10;

	FilterTuning::TotalSearchTuner tuner(signals, filtersAmount, gen, minimal, maximal);
	tuner.createStates();
	EKFState tunedParameters = tuner.tune();
	
	return tunedParameters;
}
Example #5
0
size_t FirFilterDesigner::wdfirCx (
		T& filtCoeff,
		FIRFilter::filter_type type,
    Real  ripple,
    Real twNorm,
    Real  flNorm,
    Real  fhNorm,
    size_t minTaps,
    size_t maxTaps)
{
	if ((type==FIRFilter::lowpass)||(type==FIRFilter::highpass))
	{
		//design a real filter and mux the imaginary zeros in there to make it complex
		RealArray r;
		size_t ret =  wdfir(r, type, ripple, twNorm, flNorm, 0, minTaps,maxTaps);
		muxImaginaryZeros(r, filtCoeff);
		return ret;
	}
	else
	{
		//create a lowpass or highpass filter and tune the filter with a complex tune to make the bandpass filter
		FIRFilter::filter_type inputType=FIRFilter::lowpass;
		if (type==FIRFilter::bandstop)
			inputType=FIRFilter::highpass;
		RealArray r;
		size_t ret =  wdfir(r, inputType, ripple, twNorm, fabs(fhNorm-flNorm)/2.0, 0, minTaps,maxTaps);

		filtCoeff.resize(ret);
		//tune the filter outputs to the specified center frequency
		//the tune phase is 2*pi*fc_norm = 2*pi*((fhNorm+flNorm)/2) = pi*(fhNorm+flNorm)
		Real tunePhaseUpdate=M_PI*(fhNorm+flNorm);
		Complex phasor(cos(tunePhaseUpdate),sin(tunePhaseUpdate));
		Complex tuner(phasor);
		for (size_t i=0; i!=ret; i++)
		{
			filtCoeff[i]=r[i]*tuner;
			tuner*=phasor;
		}
		return ret;
	}
}
Example #6
0
/** main */
int
main(int argc, char *argv[])
{
	Args args = parseOption(argc, argv);
	// 正常終了時戻り値
	int result = 0;
	boost::scoped_ptr<Recordable> tuner(NULL);
	timeval tv_start;
#ifdef UDP
	Udp udp;
#endif /* defined(UDP) */
#ifdef HTTP
	int dest = 1; // stdout
	int connected_socket = 0;
	int listening_socket = 0;
#endif /* defined(HTTP) */
	
	// 引数確認
	if (!args.forever && args.recsec <= 0) {
		std::cerr << "recsec must be (recsec > 0)." << std::endl;
		exit(1);
	}
	
	// 録画時間の基準開始時間
	time_t time_start = time(NULL);
	
	// ログ出力先設定
	std::ostream& log = args.stdout ? std::cerr : std::cout;

#ifdef HTTP
	if( !args.http_mode ){
		// 出力先ファイルオープン
		if(!args.stdout) {
			dest = open(args.destfile, (O_RDWR | O_CREAT | O_TRUNC), 0666);
			if (0 > dest) {
				std::cerr << "can't open file '" << args.destfile << "' to write." << std::endl;
				exit(1);
			}
		}
	}else{
		struct sockaddr_in	sin;
		int					sock_optval = 1;
		int					ret;

		fprintf(stderr, "run as a daemon..\n");
		if(daemon(1,1)){
			perror("failed to start");
			exit(1);
		}

		listening_socket = socket(AF_INET, SOCK_STREAM, 0);
		if ( listening_socket == -1 ){
			perror("socket");
			exit(1);
		}

		if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, &sock_optval, sizeof(sock_optval)) == -1 ){
			perror("setsockopt");
			exit(1);
		}

		sin.sin_family = AF_INET;
		sin.sin_port = htons(args.http_port);
		sin.sin_addr.s_addr = htonl(INADDR_ANY);

		if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){
			perror("bind");
			exit(1);
		}

		ret = listen(listening_socket, SOMAXCONN);
		if ( ret == -1 ){
			perror("listen");
			exit(1);
		}
		fprintf(stderr,"listening at port %d\n", args.http_port);
	}

	while(1){
		if ( args.http_mode ) {
			struct sockaddr_in	peer_sin;
			int					read_size;
			unsigned int		len;
			char				buffer[256];
			char				s0[256],s1[256],s2[256];
			char				delim[] = "/";
			char				*channel;
			char				*sidflg;

			len = sizeof(peer_sin);
			connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &len);
			if ( connected_socket == -1 ) {
				perror("accept");
				exit(1);
			}

			int error;
			char hbuf[NI_MAXHOST], nhbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
			error = getnameinfo((struct sockaddr *)&peer_sin, sizeof(peer_sin), hbuf, sizeof(hbuf), NULL, 0, 0);
			if (error) {
				fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(error));
				exit(1);
			}
			error = getnameinfo((struct sockaddr *)&peer_sin, sizeof(peer_sin), nhbuf, sizeof(nhbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
			if (error) {
				fprintf(stderr, "getnameinfo(): %s\n", gai_strerror(error));
				exit(1);
			}
			fprintf(stderr,"connect from: %s [%s] port %s\n", hbuf, nhbuf, sbuf);

			read_size = read_line(connected_socket, buffer);
			fprintf(stderr, "request command is %s\n", buffer);
			// ex:GET /C8/333 HTTP/1.1
			sscanf(buffer, "%s%s%s", s0, s1, s2);
			channel = strtok(s1, delim);
			if (channel != NULL) {
				fprintf(stderr, "Channel: %s\n", channel);
				parseChannel(&args, channel);
				sidflg = strtok(NULL, delim);
				if (sidflg != NULL) {
					fprintf(stderr, "SID: %s\n", sidflg);
#ifdef TSSL
					args.splitter = true;
					args.sid_list = sidflg;
				} else {
					args.splitter = false;
					args.sid_list = NULL;
#endif /* defined(TSSL) */
				}
			}
			char header[] =  "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nCache-Control: no-cache\r\n\r\n";
			write(connected_socket, header, strlen(header));
			//set write target to http
			dest = connected_socket;
		}
#endif /* defined(HTTP) */

#ifdef B25
	// B25初期化
	B25Decoder b25dec;
	if (args.b25) {
		try {
			b25dec.setRound(args.round);
			b25dec.setStrip(args.strip);
			b25dec.setEmmProcess(args.emm);
			b25dec.open();
			log << "B25Decoder initialized." << std::endl;
		} catch (b25_error& e) {
			std::cerr << e.what() << std::endl;
			
#ifdef HTTP
			if (!args.http_mode) {
#endif /* defined(HTTP) */
			// エラー時b25を行わず処理続行。終了ステータス1
			std::cerr << "disable b25 decoding." << std::endl;
			args.b25 = false;
			result = 1;
#ifdef HTTP
			}
#endif /* defined(HTTP) */
		}
	}
#endif /* defined(B25) */

#ifdef UDP
	// UDP初期化
	if( ! args.ip.empty() ){
		try{
			udp.setLog(&log);
			udp.init( args.ip, args.port );
		}
		catch( const char* e ){
			log << e << std::endl;
			log << "disable UDP." << std::endl;
		}
	}
#endif /* defined(UDP) */

#ifdef TSSL
	/* initialize splitter */
	splitbuf_t splitbuf;
	splitbuf.size = 0;
	splitter *splitter = NULL;
	int split_select_finish = TSS_ERROR;
	int code;
	if(args.splitter) {
		splitter = split_startup(args.sid_list);
		if(splitter->sid_list == NULL) {
			fprintf(stderr, "Cannot start TS splitter\n");
			return 1;
		}
	}
#endif /* defined(TSSL) */

	// Tuner取得
	tuner.reset(createRecordable(args.type));
#ifdef HDUS
	if( args.type == TUNER_HDUS ) log << "Tuner type is HDUS." << std::endl;
	else if( args.type == TUNER_HDP ) log << "Tuner type is HDP." << std::endl;
#endif /* defined(HDUS) */
	// ログ出力先設定
	tuner->setLog(&log);
	// ロックファイル設定
	if (args.lockfile != NULL) {
		tuner->setDetectLockFile(args.lockfile);
	}
	
	// Tuner初期化
	int retryCount = ERROR_RETRY_MAX;
	while (0 < retryCount) {
		try {
			// チューナopen
			bool r = tuner->open(args.lnb);
			if (!r) {
				std::cerr << "can't open tuner." << std::endl;
				exit(1);
			}
			
			// チャンネル設定
			tuner->setChannel(args.band, args.channel);
			
			// 開始時SignalLevel出力
			float lev_before = 0.0;
			int lev_retry_count = SIGNALLEVEL_RETRY_MAX;
			while (lev_before < SIGNALLEVEL_RETRY_THRESHOLD && 0 < lev_retry_count) {
				lev_before = tuner->getSignalLevel();
				log << "Signal level: " << lev_before << std::endl;
				
				lev_retry_count--;
				usleep(SIGNALLEVEL_RETRY_INTERVAL * 1000);
			}
		} catch (usb_error& e) {
			// リトライ処理
			retryCount--;
			std::cerr << e.what();
			if (retryCount <= 0) {
				std::cerr << " abort." << std::endl;
				exit(1);
			}
			std::cerr << " retry." << std::endl;
			
			tuner->close();
			usleep(ERROR_RETRY_INTERVAL * 1000);
			continue;
		}
		break;
	}
	
#ifndef HTTP
	// 出力先ファイルオープン
	FILE *dest = stdout;
	if (!args.stdout) {
		dest = fopen(args.destfile, "w");
		if (NULL == dest) {
			std::cerr << "can't open file '" << args.destfile << "' to write." << std::endl;
			exit(1);
		}
	}
#endif /* !defined(HTTP) */
	
	// 出力開始/時間計測
	log << "Output ts file." << std::endl;
	if (gettimeofday(&tv_start, NULL) < 0) {
		std::cerr << "gettimeofday failed." << std::endl;
		exit(1);
	}
	
	// SIGINT/SIGTERMキャッチ
	struct sigaction sa;
	memset(&sa, 0, sizeof(struct sigaction));
	sa.sa_handler = sighandler;
	sa.sa_flags = SA_RESTART;
	struct sigaction saDefault;
	memset(&saDefault, 0, sizeof(struct sigaction));
	saDefault.sa_handler = SIG_DFL;
	sigaction(SIGINT,  &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);
	
	uint8_t		*buf = NULL;
	int			rlen;
	
	// 受信スレッド起動
	tuner->startStream();
	// データ読み出し
	uint32_t urb_error_cnt = 0;
	while (!caughtSignal && (args.forever || time(NULL) <= time_start + args.recsec)) {
		try {
			rlen = tuner->getStream((const uint8_t **)&buf, 200);
			if (0 == rlen) {
				continue;
			}
			
#ifdef B25
			// B25を経由させる。
			if (args.b25) {
				static int f_b25_sync = 0;
				try {
					uint8_t *b25buf;
					b25dec.put(buf, rlen);
					rlen = b25dec.get((const uint8_t **)&b25buf);
					if (0 == rlen) {
						continue;
					}
					f_b25_sync = 1;
					buf = b25buf;
				} catch (b25_error& e) {
					if( f_b25_sync == 0 && args.sync ){
						log << "Wait for B25 sync" << std::endl;
						continue;
					}
					log << "B25 Error: " << e.what() << std::endl;
					log << "Continue recording without B25." << std::endl;
#ifdef HTTP
					if (!args.http_mode) {
#endif /* defined(HTTP) */
					// b25停止、戻り値エラー
					args.b25 = false;
					result = 1;
#ifdef HTTP
					}
#endif /* defined(HTTP) */
				}
			}
#endif /* defined(B25) */

#ifdef TSSL
			if (args.splitter) {
				splitbuf.size = 0;
				while (rlen) {
					/* 分離対象PIDの抽出 */
					if (split_select_finish != TSS_SUCCESS) {
						split_select_finish = split_select(splitter, buf, rlen);
						if (split_select_finish == TSS_NULL) {
							/* mallocエラー発生 */
							log << "split_select malloc failed" << std::endl;
							args.splitter = false;
							result = 1;
							goto fin;
						} else if (split_select_finish != TSS_SUCCESS) {
							// 分離対象PIDが完全に抽出できるまで出力しない
							// 1秒程度余裕を見るといいかも
							time_t cur_time;
							time(&cur_time);
							if (cur_time - time_start > 4) {
								args.splitter = false;
								result = 1;
								goto fin;
							}
							break;
						}
					}
					/* 分離対象以外をふるい落とす */
					code = split_ts(splitter, buf, rlen, &splitbuf);
					if (code != TSS_SUCCESS) {
						log << "split_ts failed" << std::endl;
						break;
					}
					break;
				}

				rlen = splitbuf.size;
				buf = splitbuf.buffer;
			fin:
				;
			}
#endif /* defined(TSSL) */

#ifdef UDP
			// UDP 配信
			udp.send(buf, rlen);
#endif /* defined(UDP) */

#ifdef HTTP
			while(rlen > 0) {
				ssize_t wc;
				int ws = rlen < SIZE_CHUNK ? rlen : SIZE_CHUNK;
				while(ws > 0) {
					wc = write(dest, buf, ws);
					if(wc < 0) {
						log << "write failed." << std::endl;
						rlen = 0;
						buf = NULL;
						break;
					}
					ws -= wc;
					rlen -= wc;
					buf += wc;
				}
			}
#else
			fwrite(buf, 1, rlen, dest);
#endif /* defined(HTTP) */

		} catch (usb_error& e) {
			if (urb_error_cnt <= URB_ERROR_MAX) {
				log << e.what() << std::endl;
				if (urb_error_cnt == URB_ERROR_MAX) {
					log << "Too many URB error." << std::endl;
				}
				urb_error_cnt++;
			}
		}
	}
	if (caughtSignal) {
#ifdef HTTP
		if( args.http_mode )
			caughtSignal = false;
		else
#endif /* defined(HTTP) */
		log << "interrupted." << std::endl;
	}
	// 受信スレッド停止
	tuner->stopStream();
	
	// シグナルハンドラを戻す。
	sigaction(SIGINT,  &saDefault, NULL);
	sigaction(SIGTERM, &saDefault, NULL);
	sigaction(SIGPIPE, &saDefault, NULL);

	rlen = 0;
	buf = NULL;

#ifdef B25
	// B25デコーダ内のデータを出力する。
	if (args.b25) {
		try {
			b25dec.flush();
			rlen = b25dec.get((const uint8_t **)&buf);
		} catch (b25_error& e) {
			log << "B25 Error: " << e.what() << std::endl;
			result = 1;
		}
	}
#endif /* defined(B25) */
#ifdef TSSL
	if (args.splitter) {
		splitbuf.size = 0;
		while (rlen) {
			/* 分離対象PIDの抽出 */
			if (split_select_finish != TSS_SUCCESS) {
				split_select_finish = split_select(splitter, buf, rlen);
				if (split_select_finish == TSS_NULL) {
					/* mallocエラー発生 */
					log << "split_select malloc failed" << std::endl;
					args.splitter = false;
					result = 1;
					break;
				} else if (split_select_finish != TSS_SUCCESS) {
					// 分離対象PIDが完全に抽出できるまで出力しない
					// 1秒程度余裕を見るといいかも
					time_t cur_time;
					time(&cur_time);
					if (cur_time - time_start > 4) {
						args.splitter = false;
						result = 1;
					}
					break;
				}
			}
			/* 分離対象以外をふるい落とす */
			code = split_ts(splitter, buf, rlen, &splitbuf);
			if (code != TSS_SUCCESS) {
				log << "split_ts failed" << std::endl;
				break;
			}
			break;
		}
		rlen = splitbuf.size;
		buf = splitbuf.buffer;
		split_shutdown(splitter);
	}
#endif /* defined(TSSL) */
#ifdef HTTP
		while(rlen > 0) {
			ssize_t wc;
			int ws = rlen < SIZE_CHUNK ? rlen : SIZE_CHUNK;
			while(ws > 0) {
				wc = write(dest, buf, ws);
				if(wc < 0) {
					log << "write failed." << std::endl;
					rlen = 0;
					buf = NULL;
					break;
				}
				ws -= wc;
				rlen -= wc;
				buf += wc;
			}
		}
		if( args.http_mode ){
			/* close http socket */
			close(dest);
			fprintf(stderr,"connection closed. still listening at port %d\n", args.http_port);
		}else
			break;
	}
#else
	if (0 < rlen) {
		fwrite(buf, 1, rlen, dest);
	}
#endif /* defined(HTTP) */

	// 時間計測
	timeval tv_end;
	if (gettimeofday(&tv_end, NULL) < 0) {
		err(1, "gettimeofday failed.");
	}
	
	// 出力先ファイルクローズ
#ifdef HTTP
	if (!args.stdout) {
		close(dest);
	}
#else
	fflush(dest);
	if (!args.stdout) {
		fclose(dest);
	}
#endif /* defined(HTTP) */
	log << "done." << std::endl;
	
#ifdef UDP
	// UDP クローズ
	udp.shutdown();
#endif /* defined(UDP) */
	
	// 録画時間出力
	timeval rec_time;
	timersub(&tv_end, &tv_start, &rec_time);
	log << "Rec time: " << rec_time.tv_sec << "." << std::setfill('0') << std::setw(6) << rec_time.tv_usec << " sec." << std::endl;
	
	// 終了時SignalLevel出力
	try {
		float lev_after = tuner->getSignalLevel();
		log << "Signal level: " << lev_after << std::endl;
	} catch (usb_error& e) {
		log << e.what() << " ignored." << std::endl;
	}
	
	return result;
}
Example #7
0
void Tuner(int argc, char* argv[]) {
  constexpr auto kSeed = 42; // fixed seed for reproducibility

  // Sets the parameters and platform/device for which to tune (command-line options)
  auto command_line_args = RetrieveCommandLineArguments(argc, argv);
  auto help = std::string{"* Options given/available:\n"};
  auto args = Arguments<T>{};
  args.platform_id = GetArgument(command_line_args, help, kArgPlatform, ConvertArgument(std::getenv("CLBLAST_PLATFORM"), size_t{0}));
  args.device_id   = GetArgument(command_line_args, help, kArgDevice, ConvertArgument(std::getenv("CLBLAST_DEVICE"), size_t{0}));
  args.precision   = GetArgument(command_line_args, help, kArgPrecision, Precision::kSingle);
  for (auto &o: C::GetOptions()) {
    if (o == kArgM)        { args.m        = GetArgument(command_line_args, help, kArgM, C::DefaultM()); }
    if (o == kArgN)        { args.n        = GetArgument(command_line_args, help, kArgN, C::DefaultN()); }
    if (o == kArgK)        { args.k        = GetArgument(command_line_args, help, kArgK, C::DefaultK()); }
    if (o == kArgAlpha)    { args.alpha    = GetArgument(command_line_args, help, kArgAlpha, GetScalar<T>()); }
    if (o == kArgBeta)     { args.beta     = GetArgument(command_line_args, help, kArgBeta, GetScalar<T>()); }
    if (o == kArgFraction) { args.fraction = GetArgument(command_line_args, help, kArgFraction, C::DefaultFraction()); }
    if (o == kArgBatchCount) { args.batch_count = GetArgument(command_line_args, help, kArgBatchCount, C::DefaultBatchCount()); }
    if (o == tStrategy)   {args.tStrategy   = GetArgument(command_line_args, help, tStrategy, DEFAULT_STRATEGY);  }
    if (o == psoSwarmSize)   {args.psoSwarmSize   = GetArgument(command_line_args, help, psoSwarmSize, DEFAULT_PSO_SWARM);  }
    if (o == psoInfG)   {args.psoInfG   = GetArgument(command_line_args, help, psoInfG, DEFAULT_PSO_G);  }
    if (o == psoInfL)   {args.psoInfL   = GetArgument(command_line_args, help, psoInfL, DEFAULT_PSO_L);  }
    if (o == psoInfR)   {args.psoInfR   = GetArgument(command_line_args, help, psoInfR, DEFAULT_PSO_R);  }
  }
  const auto num_runs = GetArgument(command_line_args, help, kArgNumRuns, C::DefaultNumRuns());

  fprintf(stdout, "%s\n", help.c_str());

  // Tests validity of the given arguments
  C::TestValidArguments(args);

  // Tests for validity of the precision and retrieves properties
  auto isAMD = false;
  auto isARM = false;
  auto isGPU = false;
  {
    const auto platform = Platform(args.platform_id);
    const auto device = Device(platform, args.device_id);
    if (!PrecisionSupported<T>(device)) {
      printf("* Unsupported precision, skipping this tuning run\n\n");
      return;
    }
    isAMD = device.IsAMD();
    isARM = device.IsARM();
    isGPU = device.IsGPU();
  }

  // Creates input buffers with random data
  auto x_vec = std::vector<T>(C::GetSizeX(args));
  auto y_vec = std::vector<T>(C::GetSizeY(args));
  auto a_mat = std::vector<T>(C::GetSizeA(args));
  auto b_mat = std::vector<T>(C::GetSizeB(args));
  auto c_mat = std::vector<T>(C::GetSizeC(args));
  auto temp = std::vector<T>(C::GetSizeTemp(args));
  std::mt19937 mt(kSeed);
  std::uniform_real_distribution<double> dist(kTestDataLowerLimit, kTestDataUpperLimit);
  PopulateVector(x_vec, mt, dist);
  PopulateVector(y_vec, mt, dist);
  PopulateVector(a_mat, mt, dist);
  PopulateVector(b_mat, mt, dist);
  PopulateVector(c_mat, mt, dist);
  PopulateVector(temp, mt, dist);

  // Initializes the tuner for the chosen device
  cltune::Tuner tuner(args.platform_id, args.device_id);

  // Use full-search to explore all parameter combinations or random-search to search only a part of
  // the parameter values. The fraction is set as a command-line argument.
  #ifdef XGEMM_EXEC
  
  if(tStrategyFlag)
  {
   auto localtStrategy = args.tStrategy;  

    if (args.fraction == 1.0 || args.fraction == 0.0) 
    { 
     localtStrategy = FULL_SEARCH_STRATEGY; 
    }
    switch (localtStrategy)
    {
      case FULL_SEARCH_STRATEGY: 
        tuner.UseFullSearch();
        break;

      case RANDOM_SEARCH_STRATEGY: 
          tuner.UseRandomSearch(1.0/args.fraction);
        break;
      case PSO_STRATEGY: 
          tuner.UsePSO(1.0/args.fraction, args.psoSwarmSize, args.psoInfG, args.psoInfL, args.psoInfR);
        break;
      case DVDT_STRATEGY:
      default: 
        tuner.UseFullSearch();
    }
  }

  #else

  if (args.fraction == 1.0 || args.fraction == 0.0) 
  {
    tuner.UseFullSearch();
  }
  else 
  {
    tuner.UseRandomSearch(1.0/args.fraction);
  }

  #endif
  // Set extra settings for specific defines. This mimics src/routine.cc.
  auto defines = std::string{""};
  if (isAMD && isGPU) {
    defines += "#define USE_CL_MAD 1\n";
    defines += "#define USE_STAGGERED_INDICES 1\n";
  }
  if (isARM && isGPU) {
    defines += "#define GLOBAL_MEM_FENCE 1\n";
  }

  // Loads the kernel sources and defines the kernel to tune
  auto sources = defines + C::GetSources();
  auto id = tuner.AddKernelFromString(sources, C::KernelName(), C::GlobalSize(args), C::LocalSize());
  tuner.SetReferenceFromString(sources, C::KernelName(), C::GlobalSizeRef(args), C::LocalSizeRef());

  // Sets the tunable parameters and their possible values
  C::SetParameters(tuner, id);
  C::SetConstraints(tuner, id);
  C::SetLocalMemorySize(tuner, id, args);

  // Tests for a specific precision
  tuner.AddParameter(id, "PRECISION", {static_cast<size_t>(args.precision)});
  tuner.AddParameterReference("PRECISION", static_cast<size_t>(args.precision));

  // Modifies the thread-sizes (both global and local) based on the parameters
  for (auto &parameters: C::MulLocal()) { tuner.MulLocalSize(id, parameters); }
  for (auto &parameters: C::DivLocal()) { tuner.DivLocalSize(id, parameters); }
  for (auto &parameters: C::MulGlobal()) { tuner.MulGlobalSize(id, parameters); }
  for (auto &parameters: C::DivGlobal()) { tuner.DivGlobalSize(id, parameters); }

  // Sets the function's arguments
  C::SetArguments(tuner, args, x_vec, y_vec, a_mat, b_mat, c_mat, temp);

  // Starts the tuning process
  tuner.SetNumRuns(num_runs);
  tuner.Tune();

  // Prints the results to screen
  auto time_ms = tuner.PrintToScreen();
  tuner.PrintFormatted();

  // Also prints the performance of the best-case in terms of GB/s or GFLOPS
  if (time_ms != 0.0) {
    printf("[ -------> ] %.2lf ms", time_ms);
    printf(" or %.1lf %s\n", C::GetMetric(args)/(time_ms*1.0e6), C::PerformanceUnit().c_str());
  }

  // Outputs the results as JSON to disk, including some meta-data
  auto precision_string = std::to_string(static_cast<size_t>(args.precision));
  auto metadata = std::vector<std::pair<std::string,std::string>>{
    {"kernel_family", C::KernelFamily()},
    {"precision", precision_string}
  };
  for (auto &o: C::GetOptions()) {
    if (o == kArgM)     { metadata.push_back({"arg_m", std::to_string(args.m)}); }
    if (o == kArgN)     { metadata.push_back({"arg_n", std::to_string(args.n)}); }
    if (o == kArgK)     { metadata.push_back({"arg_k", std::to_string(args.k)}); }
    if (o == kArgAlpha) { metadata.push_back({"arg_alpha", ToString(args.alpha)}); }
    if (o == kArgBeta)  { metadata.push_back({"arg_beta", ToString(args.beta)}); }
    if (o == kArgBatchCount) { metadata.push_back({"arg_batch_count", ToString(args.batch_count)}); }
  }
  tuner.PrintJSON("clblast_"+C::KernelFamily()+"_"+precision_string+".json", metadata);
 

}