int main(int argc, char* argv[]) {
	int ch;

	std::string test_file;
	std::string model_file;
	std::string output_file;

	while ((ch = getopt(argc, argv, "t:m:o:h")) != -1) {
		switch (ch) {
		case 't':
			test_file = optarg;
			break;
		case 'm':
			model_file = optarg;
			break;
		case 'o':
			output_file = optarg;
			break;
		case 'h':
		default:
			print_usage(argc, argv);
			exit(0);
		}
	}

	if (test_file.size() == 0 || model_file.size() == 0 || output_file.size() == 0) {
		print_usage(argc, argv);
		exit(1);
	}

	LRModel<double> model;
	model.Initialize(model_file.c_str());

	double y = 0.;
	std::vector<std::pair<size_t, double> > x;
	FILE* wfp = fopen(output_file.c_str(), "w");
	size_t cnt = 0, correct = 0;
	double loss = 0.;
	FileParser<double> parser;
	parser.OpenFile(test_file.c_str());

	std::vector<std::pair<double, unsigned> > pred_scores;

	while (1) {
		bool res = parser.ReadSample(y, x);
		if (!res) break;

		double pred = model.Predict(x);
		pred = std::max(std::min(pred, 1. - 10e-15), 10e-15);
		fprintf(wfp, "%lf\n", pred);

		pred_scores.push_back(std::move(
			std::make_pair(pred, static_cast<unsigned>(y))));

		++cnt;
		double pred_label = 0;
		if (pred > 0.5) pred_label = 1;
		if (util_equal(pred_label, y)) ++correct;

		pred = std::max(std::min(pred, 1. - 10e-15), 10e-15);
		loss += y > 0 ? -log(pred) : -log(1. - pred);
	}

	std::sort(
		pred_scores.begin(),
		pred_scores.end(),
		[] (const std::pair<double, unsigned>& l, const std::pair<double, unsigned>& r) {
		    return l.first > r.first;
		}
	);
	double auc = calc_auc(pred_scores);

	if (cnt > 0) {
		printf("Accuracy = %.2lf%% (%zu/%zu)\n",
			static_cast<double>(correct) / cnt * 100, correct, cnt);
		printf("Log-likelihood = %lf\n", loss / cnt);
		printf("AUC = %lf\n", auc);
	}

	parser.CloseFile();
	fclose(wfp);

	return 0;
}