コード例 #1
0
void stick20HiddenVolumeDialog::on_HVPasswordEdit_textChanged (const QString & arg1)
{
    int Len;

    double Entropy;

    Len = arg1.length ();
    Entropy = GetEntropy ((unsigned char *) arg1.toLatin1 ().data (), Len);

    if (0 < Entropy)
    {
        // ui->HVEntropieLabel->setText(QString ("%1").sprintf("Entropy
        // guess: %3.1lf bits for random chars\nEntropy guess: %3.1lf for
        // real words",Entropy,Entropy/2.0));
        ui->HVEntropieRealWords->setText (QString ("%1").sprintf (" %3.1lf for real words", Entropy / 2.0));
        ui->HVEntropieRandChars->setText (QString ("%1").sprintf (" %3.1lf bits for random chars", Entropy));
    }
    else
    {
        // ui->HVEntropieLabel->setText(QString ("%1").sprintf("Entropy
        // guess: %3.1lf bits for random chars\nEntropy guess: %3.1lf for
        // real words",0.0,0.0));
        ui->HVEntropieRealWords->setText (QString ("%1").sprintf (" %3.1lf for real words", 0.0));
        ui->HVEntropieRandChars->setText (QString ("%1").sprintf (" %3.1lf bits for random chars", 0.0));
    }
}
コード例 #2
0
void HehFeatureGen::Compute(const ImageRGB<byte>& imagergb,
														const ImageF& image,
														const MatI& seg) {
	// General notes:

	//   We must always be careful to deal with normalized image
	//   coordinates, which range from 0 to 1 in both dimensions. This
	//   includes pixel locations, vanishing point locations, and line
	//   intersections.

	//   Any homogeneous vector can represent a point at infinity, which
	//   will manifest as an INF if we Project() it. This is fine so
	//   long as we keep track of which coordinates might potentially be
	//   INF and only do sensible things with them -- e.g. no sqrt(),
	//   atan2(), division between two variables that can both be INF,
	//   etc.

	const int w = image.GetWidth();
	const int h = image.GetHeight();
	const int image_size = w*h;

	// Run the filter bank
	// TODO: implement LM filters. Here we just use 12 Gabor filters.
	vector<shared_ptr<ImageF> > responses;
	FilterBank filterbank(1);  // *** should be 3 scales
	MakeGaborFilters(4, &filterbank.filters);
	filterbank.Run(image, &responses);

	//
	// Find lines and compute vanishing points
	//
	vpts.Compute(image);
	const int num_lines = vpts.lines.segments.size();
	const int num_vpts = vpts.vanpts.size();

	//
	// Pre-process the line segments
	//

	// Whether each pair of lines is nearly parallel
	MatI is_nearly_parallel(num_lines, num_lines);
	// Whether the intersection of each pair is right of center
	MatI isct_is_right(num_lines, num_lines);
	// Whether the intersection of each pair is below center
	MatI isct_is_bottom(num_lines, num_lines);
	// Histogram bin index for intersection of each pair, or -1 if outside
	MatI isct_bin(num_lines, num_lines);

	// Compute line intersections
	for (int i = 0; i < num_lines; i++) {
		const LineSegment& segi = *vpts.lines.segments[i];
		is_nearly_parallel[i][i] = 0;
		for (int j = 1; j < num_lines; j++) {
			const LineSegment& segj = *vpts.lines.segments[j];

			// Parallel ?
			float dtheta = segi.theta - segj.theta;
			dtheta = min(dtheta, M_PI-dtheta);
			is_nearly_parallel[i][j] = (dtheta <= kParallelThresh ? 1 : 0);

			if (is_nearly_parallel[i][j]) {
				// Intersection position relative to center
				Vec3 isct = Cross3D(segi.line, segj.line);
				isct[0] /= w;  // can be +/- INF
				isct[1] /= h;  // can be +/- INF
				const float eucl_x = Project(isct)[0];
				const float eucl_y = Project(isct)[1];
				isct_is_right[i][j] = eucl_x > 0.5;
				isct_is_bottom[i][j] = eucl_y > 0.5;

				// Compute distance from centre
				// don't take sqrt(radius_sqr) because radius_sqr can be INF
				const float radius_sqr = eucl_x*eucl_x + eucl_y*eucl_y;
				int rad_bin = -1;
				if (radius_sqr > kFarRadius*kFarRadius) {
					rad_bin = 1;
				} else if (radius_sqr > kNearRadius*kNearRadius) {
					rad_bin = 0;
				}

				// Compute orientation from centre
				if (rad_bin == -1) {
					isct_bin[i][j] = -1;
				} else {
					// Must do atan2 with homogeneous coords. It will stay sane in
					// the case of points-at-infinity
					float phi = atan2(isct[1] - 0.5*isct[2],
															isct[0] - 0.5*isct[2]);
					int phi_bin = static_cast<int>(phi*M_PI/kNumOrientBins)%kNumOrientBins;
					int bin = rad_bin * kNumOrientBins + phi_bin;
					isct_bin[i][j] = bin;
				}
			}

			is_nearly_parallel[j][i] = is_nearly_parallel[i][j];
			isct_is_right[j][i] = isct_is_right[i][j];
			isct_is_bottom[j][i] = isct_is_bottom[i][j];
			isct_bin[j][i] = isct_bin[i][j];
		}
	}

	// 
	// Pre-process vanishing points
	//
	enum VanPointCla {
		kVptNone,
		kVptHoriz,
		kVptVert
	};
	const float h_vpt_min = 0.5-kHorizVptThresh;
	const float h_vpt_max = 0.5+kHorizVptThresh;
	const float v_vpt_low = 0.5-kVertVptThresh;
	const float v_vpt_high = 0.5+kVertVptThresh;
	int num_hvpts = 0;
	float sum_hvpts_y = 0;
	vector<VectorFixed<2,float> > norm_vpts;  // can contain INF
	VecI vanpt_cla(vpts.vanpts.size(), kVptNone);
	COUNTED_FOREACH(int i, const VecD& vpt, vpts.vanpts) {
		const float eucl_x = Project(vpt)[0] / w;  // can be +/-INF
		const float eucl_y = Project(vpt)[1] / h;  // can be +/-INF

		// Classify vanishing point as horizontal, vertical, or none
		norm_vpts.push_back(MakeVector<2,float>(eucl_x, eucl_y));
		if (eucl_y > h_vpt_min &&	eucl_y < h_vpt_max) {
			vanpt_cla[i] = kVptHoriz;
			sum_hvpts_y += eucl_y;
			num_hvpts++;
		} else if (eucl_y < v_vpt_low || eucl_y > v_vpt_high) {
			vanpt_cla[i] = kVptVert;
		}
	}

	// Assume horizon is horizontal with Y coord equal to average of the
	// "horizontal" vanishing points
	float horizon_y = 0.5;
	if (num_hvpts > 0) {
		horizon_y = sum_hvpts_y / num_hvpts;
	}

	// Print vanpt clas
	DREPORT(vanpt_cla);



	// Initialize features
	int num_segments = seg.MaxValue()+1;
	features.resize(num_segments);
	for (int i = 0; i < features.size(); i++) {
		features[i].seen = VecI(num_lines, 0);
	}

	//
	// Compute sums over the image
	//
	for (int r = 0; r < h; r++) {
		const PixelRGB<byte>* imrgbrow = imagergb[r];
		const PixelF* imrow = image[r];
		const int* segrow = seg[r];
		const int* linerow = vpts.lines.segment_map[r];
		for (int c = 0; c < w; c++) {
			HehFeature& ftr = features[segrow[c]];

			// Shape
			ftr.xs.push_back(1.0*c/w);
			ftr.ys.push_back(1.0*r/h);

			// Color
			PixelHSV<byte> hsv;
			const PixelRGB<byte>& rgb = imrgbrow[c];
			ImageConversions::RGB2HSV(rgb.r, rgb.g, rgb.b,
																hsv.h, hsv.s, hsv.v);
			ftr.r_mean += rgb.r;
			ftr.g_mean += rgb.g;
			ftr.b_mean += rgb.b;
			ftr.h_mean += hsv.h;
			ftr.s_mean += hsv.s;
			ftr.v_mean += hsv.v;

			const int hbin = static_cast<int>(kNumHueBins * hsv.h / 256);
			const int sbin = static_cast<int>(kNumSatBins * hsv.s / 256);
			ftr.hue_hist[hbin]++;
			ftr.sat_hist[sbin]++;
			
			// Texture
			ImageRef pyrpos(c, r);
			int maxi;
			float maxv = -INFINITY;
			for (int i = 0; i < responses.size(); i++) {
				if (i > 0 && responses[i]->GetWidth() < responses[i-1]->GetWidth()) {
					pyrpos /= 2;
				}
				const float v = (*responses[i])[pyrpos].y;
				ftr.filter_means[i] += v;
				if (v > maxv) {
					maxv = v;
					maxi = i;
				}
			}
			ftr.filter_max_hist[maxi]++;

			// Lines
			const int line = linerow[c];
			if (line != -1) {
				if (!ftr.seen[line]) {
					ftr.seen[line] = 1;
					ftr.lines.push_back(line);
				}
				ftr.num_line_pix++;
				const int line_cla = vanpt_cla[vpts.owners[line]];
				if (line_cla == kVptVert) {
					ftr.pct_vert_vpt++;
					ftr.pct_vert_vpt_pix++;
				} else if (line_cla == kVptHoriz) {
					ftr.pct_horiz_vpt_pix++;
				}
			}
		}
	}

	//
	// Normalize over each segment
	//
	for (int i = 0; i < features.size(); i++) {
		HehFeature& ftr = features[i];
		float size = ftr.xs.size();

		// Shape
		ftr.area = size/image_size;

		sort_all(ftr.xs);
		sort_all(ftr.ys);

		ftr.x_mean = accumulate_all(ftr.xs, 0.0) / size;
		ftr.x_10pct = ftr.xs[size/10];
		ftr.x_90pct = ftr.xs[size*9/10];

		ftr.y_mean = accumulate_all(ftr.ys, 0.0) / size;
		ftr.y_10pct = ftr.ys[size/10];
		ftr.y_90pct = ftr.ys[size*9/10];

		ftr.y_mean_wrt_horizon = ftr.y_mean - horizon_y;
		ftr.y_10pct_wrt_horizon = ftr.y_10pct - horizon_y;
		ftr.y_90pct_wrt_horizon = ftr.y_90pct - horizon_y;

		// Color
		ftr.r_mean /= size;
		ftr.g_mean /= size;
		ftr.b_mean /= size;
		ftr.h_mean /= size;
		ftr.s_mean /= size;
		ftr.v_mean /= size;
		ftr.hue_hist /= size;
		ftr.sat_hist /= size;

		// Texture
		ftr.filter_means /= size;
		ftr.filter_max_hist /= size;

		// Lines
		int num_nearly_parallel = 0;
		BOOST_FOREACH(int i, ftr.lines) {
			BOOST_FOREACH(int j, ftr.lines) {
				if (i == j) continue;
				if (is_nearly_parallel[i][j]) {
					num_nearly_parallel++;
					ftr.pct_parallel_lines++;
					if (isct_is_right[i][j]) {
						ftr.pct_isct_right++;
					}
					if (isct_is_bottom[i][j]) {
						ftr.pct_isct_bottom++;
					}
					if (isct_bin[i][j] != -1) {
						ftr.isct_hist[isct_bin[i][j]]++;
					}
				}
			}
		}
		const int num_line_pairs = ftr.lines.size() * (ftr.lines.size()-1);
		const float sqrt_area = sqrt(size);  // don't use normalized area!
		ftr.pct_line_pix = ftr.num_line_pix / sqrt_area;
		if (num_line_pairs > 0) {
			ftr.pct_parallel_lines /= num_line_pairs;
		}
		if (num_nearly_parallel > 0) {
			ftr.isct_hist /= num_nearly_parallel;
			ftr.isct_hist_entropy = GetEntropy(ftr.isct_hist);
			ftr.pct_isct_right /= num_nearly_parallel;
			ftr.pct_isct_bottom /= num_nearly_parallel;
		}

		// Vanishing points
		bool has_horiz_vpt = false;
		bool has_vert_vpt = false;
		float horiz_vpt_x;
		float vert_vpt_y;
		for (int i = 0; i < ftr.lines.size(); i++) {
			const int owner_vpt = vpts.owners[ftr.lines[i]];
			if (vanpt_cla[owner_vpt] == kVptHoriz) {
				horiz_vpt_x = Project(norm_vpts[owner_vpt])[0];  // can be +/- INF
				has_horiz_vpt = true;
			}
			if (vanpt_cla[owner_vpt] == kVptHoriz) {
				vert_vpt_y = Project(norm_vpts[owner_vpt])[1];  // can be +/- INF
				has_vert_vpt = true;
			}
		}
		ftr.pct_vert_vpt_pix /= sqrt_area;
		ftr.pct_horiz_vpt_pix /= sqrt_area;
		if (ftr.num_line_pix > 0) {
			ftr.pct_vert_vpt /= ftr.num_line_pix;
		}
		if (has_horiz_vpt) {
			ftr.x_mean_wrt_hvpt = ftr.x_mean - horiz_vpt_x;  // can be +/- INF
			ftr.x_10pct_wrt_hvpt = ftr.x_10pct - horiz_vpt_x;  // can be +/- INF
			ftr.x_90pct_wrt_hvpt = ftr.x_90pct - horiz_vpt_x;  // can be +/- INF
		} else {
			ftr.x_mean_wrt_hvpt = 0;
			ftr.x_10pct_wrt_hvpt = 0;
			ftr.x_90pct_wrt_hvpt = 0;
		}
		if (has_vert_vpt) {
			ftr.y_mean_wrt_vert_vpt = ftr.y_mean - vert_vpt_y;
		} else {
			ftr.y_mean_wrt_vert_vpt = 0;
		}
	}
}
コード例 #3
0
ファイル: test.c プロジェクト: skal65535/fsc
int main(int argc, const char* argv[]) {
  int N = 100000000;
  int pdf_type = 2;
  int pdf_param = 5;
  int max_symbol = MAX_SYMBOLS;
  int print_pdf = 0;
  int log_tab_size = LOG_TAB_SIZE;
  FSCCodingMethod method = CODING_METHOD_DEFAULT;
  const char* in_file = NULL;
  const char* pdf_file = NULL;
  int c;

  for (c = 1; c < argc; ++c) {
    if (!strcmp(argv[c], "-t") && c + 1 < argc) {
      pdf_type = atoi(argv[++c]);
      if (pdf_type < 0) pdf_type = 0;
      else if (pdf_type > 5) pdf_type = 5;
    } else if (!strcmp(argv[c], "-p") && c + 1 < argc) {
      pdf_param = atoi(argv[++c]);
      if (pdf_type < 0) pdf_param = 0;
    } else if (!strcmp(argv[c], "-s") && c + 1 < argc) {
      max_symbol = atoi(argv[++c]);
      if (max_symbol < 2) max_symbol = 2;
      else if (max_symbol > 256) max_symbol = 256;
    } else if (!strcmp(argv[c], "-l") && c + 1 < argc) {
      log_tab_size = atoi(argv[++c]);
      if (log_tab_size > LOG_TAB_SIZE) log_tab_size = LOG_TAB_SIZE;
    } else if (!strcmp(argv[c], "-f") && c + 1 < argc) {
      in_file = argv[++c];
    } else if (FSCParseCodingMethodOpt(argv[c], &method)) {
      continue;
    } else if (!strcmp(argv[c], "-m") && c + 1 < argc) {
      method = (FSCCodingMethod)atoi(argv[++c]);
    } else if (!strcmp(argv[c], "-save") && c + 1 < argc) {
      pdf_file = argv[++c];
    } else if (!strcmp(argv[c], "-d")) {
      print_pdf = 1;
    } else if (!strcmp(argv[c], "-h")) {
      Help();
    } else {
      N = atoi(argv[c]);
      if (N <= 2) N = 2;
    }
  }
  uint8_t* base;
  FILE* file = NULL;
  if (in_file != NULL) {
    file = fopen(in_file, "rb");
    if (file == NULL) {
      fprintf(stderr, "Error opening file %s!\n", in_file);
      exit(-1);
    }
    fseek(file, 0L, SEEK_END);
    N = ftell(file);
    fseek(file, 0L, SEEK_SET);
    printf("Read File [%s] (%d bytes)\n", in_file, N);
  }

  base = (uint8_t*)malloc(N * sizeof(*base));
  if (base == NULL) {
    fprintf(stderr, "Malloc(%d) failed!\n", N);
    exit(-1);
  }

  if (file != NULL) {
    N = fread(base, 1, N, file);
    fclose(file);
  }  else {
    uint32_t pdf[256] = { 0 };
    int i;
    FSCRandom r;
    FSCInitRandom(&r);
    const int total = GeneratePdf(pdf_type, pdf_param, pdf, &r, max_symbol);
    const int nb_bits = 1 + log2(total - 1);
    uint64_t cumul[256 + 1];
    cumul[0] = 0;
    for (i = 1; i <= max_symbol; ++i) {
      cumul[i] = cumul[i - 1] + pdf[i - 1];
    }
    for (i = 0; i < N; ++i) {
      base[i] = DrawSymbol(cumul, max_symbol, total, nb_bits, &r);
    }
  }
  printf("PDF generated OK (max symbol:%d).\n", max_symbol);
  if (print_pdf) {
    PrintPdf(base, N);
    printf("[Params: type=%d param=%d max_symbol=%d size=%d]\n",
           pdf_type, pdf_param, max_symbol, N);
  }
  if (pdf_file != NULL) {
    SavePdfToFile(base, N, pdf_file);
  }
  const double entropy = GetEntropy(base, N);

  int nb_errors = 0;
  uint8_t* out = NULL;
  size_t out_size = 0;
  // Encode
  uint8_t* bits = NULL;
  size_t bits_size = 0;
  MyClock start, tmp;
  GetElapsed(&start, NULL);
  int ok = FSCEncode(base, N, &bits, &bits_size, log_tab_size, method);
  double elapsed = GetElapsed(&tmp, &start);
  const double MS = 1.e-6 * N; // 8.e-6 * bits_size;
  const double reduction = 1. * bits_size / N;

  printf("Enc time: %.3f sec [%.2lf MS/s] (%ld bytes out, %d in).\n",
         elapsed, MS / elapsed, bits_size, N);
  printf("Entropy: %.4lf vs expected %.4lf "
         "(off by %.5lf bit/symbol [%.3lf%%])\n",
         reduction, entropy, reduction - entropy,
         100. * (reduction - entropy) / entropy);

  if (!ok) {
    fprintf(stderr, "ERROR while encoding!\n");
    nb_errors = 1;
  } else {   // Decode
    GetElapsed(&start, NULL);
    ok = FSCDecode(bits, bits_size, &out, &out_size);
    elapsed = GetElapsed(&tmp, &start);
    printf("Dec time: %.3f sec [%.2lf MS/s].\n", elapsed, MS / elapsed);
    ok &= (out_size == N);

    if (!ok) {
      fprintf(stderr, "Decoding error!\n");
      nb_errors = 1;
    } else {
      int i;
      for (i = 0; i < N; ++i) {
        nb_errors += (out[i] != base[i]);
      }
      printf("#%d errors\n", nb_errors);
      if (nb_errors) fprintf(stderr, "*** PROBLEM!! ***\n");
    }
  }

 End:
  free(base);
  free(out);
  free(bits);
  return (nb_errors != 0);
}
コード例 #4
0
ファイル: Cluster.cpp プロジェクト: bayesiancook/pbmpi2
	vector<int> GetSubset(double cutoff, int type)	{

		vector<int> a(Nstate,0);

        // all amino-acids with freq > cutoff
		if (type == 0)	{
			for (int i=0; i<Nstate; i++)	{
				a[i] = ((v[i] > cutoff));
			}
			return a;
		}
	
		else if (type == 1)	{

			double* tmp = new double[Nstate];
			for (int i=0; i<Nstate; i++)	{
				tmp[i] = v[i];
			}
			double tot = 0;
			while (tot < cutoff)	{
				double max = 0;
				int imax = 0;
				for (int i=0; i<Nstate; i++)	{
					if (max < tmp[i])	{
						max = tmp[i];
						imax = i;
					}
				}
				if (max == 0)	{
					cerr << "error: total mass is not 1\n";
					exit(1);
				}
				tot += tmp[imax];
				a[imax] = 1;
				tmp[imax] = 0;
			}
			delete[] tmp;
			return a;
		}
        else if (type == 2) {

            int naa = int(exp(GetEntropy()) + 0.5);
            vector<double> tmp = v;
            for (int k=0; k<naa; k++)   {
                double max = 0;
                int imax = 0;
                for (int i=0; i<Nstate; i++)    {
                    if (max < tmp[i])   {
                        max = tmp[i];
                        imax = i;
                    }
                }
                a[imax] = 1;
                tmp[imax] = 0;
            }
            return a;
        }
		// type == 3

		int naa = 1;
		int found = 0;
        double f = 0.33;
        double g = 3;
		while ((g * (1-cutoff) * naa < f * cutoff * (Nstate-naa)) && (! found))	{
			int n = 0;
            int complies = 1;
			for (int i=0; i<Nstate; i++)	{
				if (v[i] > f*cutoff/naa)	{
					n++;
				}
                else    {
                    if (v[i] > g*(1-cutoff)/(Nstate-naa))    {
                        complies = 0;
                    }
                }
			}
			if ((n == naa) && (complies))	{
				found = 1;
				for (int i=0; i<Nstate; i++)	{
					if (v[i] > f*cutoff/naa)	{
						a[i] = 1;
					}
				}
			}
			else	{
				naa++;
			}
		}
        if (! found)  {
            for (int i=0; i<Nstate; i++)    {
                a[i] = 0;
            }
        }
		return a;
	}
コード例 #5
0
ファイル: fsc.c プロジェクト: skal65535/fsc
int main(int argc, const char* argv[]) {
  int log_tab_size = 12;
  int compress = 1;
  FSCCodingMethod method = CODING_METHOD_DEFAULT;
  int stats_only = 0;
  int ok = 0;
  int c;

  for (c = 1; c < argc; ++c) {
    if (!strcmp(argv[c], "-l") && c + 1 < argc) {
      log_tab_size = atoi(argv[++c]);
      if (log_tab_size > LOG_TAB_SIZE) log_tab_size = LOG_TAB_SIZE;
      else if (log_tab_size < 2) log_tab_size = 2;
    } else if (FSCParseCodingMethodOpt(argv[c], &method)) {
      continue;
    } else if (!strcmp(argv[c], "-m") && c + 1 < argc) {
      method = (FSCCodingMethod)atoi(argv[++c]);
    } else if (!strcmp(argv[c], "-s")) {
      stats_only = 1;
    } else if (!strcmp(argv[c], "-c")) {
      compress = 1;
    } else if (!strcmp(argv[c], "-d")) {
      compress = 0;
    } else if (!strcmp(argv[c], "-h")) {
      Help();
    }
  }

  uint8_t* out = NULL;
  size_t out_size = 0;
  uint8_t* in = NULL;
  size_t in_size = 0;

  // Read input
  fseek(stdin, 0L, SEEK_END);
  in_size = ftell(stdin);
  fseek(stdin, 0L, SEEK_SET);
  if (in_size == (size_t)-1) {
    fprintf(stderr, "Missing/erroneous input!\n");
    goto End;
  }
  in = (uint8_t*)malloc(in_size * sizeof(*in));
  if (in == NULL) {
    fprintf(stderr, "Malloc(%lu) failed!\n", in_size);
    exit(-1);
  }
  ok = (fread(in, in_size, 1, stdin) == 1);
  if (!ok) {
    fprintf(stderr, "Error reading from stdin!\n");
    goto End;
  }

  // Compress or decompress.
  MyClock start, tmp;
  if (compress) {   // encoding
    GetElapsed(&start, NULL);
    ok = FSCEncode(in, in_size, &out, &out_size, log_tab_size, method);
    if (!ok) {
      fprintf(stderr, "ERROR while encoding!\n");
      goto End;
    }

    if (stats_only) {
      const double elapsed = GetElapsed(&tmp, &start);
      const double entropy = GetEntropy(in, in_size);
      const double MS = 1.e-6 * in_size;
      const double reduction = 1. * out_size / in_size;
      printf("Enc time: %.3f sec [%.2lf MS/s] (%ld bytes out, %ld in).\n",
             elapsed, MS / elapsed, out_size, in_size);
      printf("Entropy: %.4lf vs expected %.4lf "
             "(off by %.5lf bit/symbol [%.3lf%%])\n",
             reduction, entropy, reduction - entropy,
             100. * (reduction - entropy) / entropy);
    }
  } else {         // decoding
    GetElapsed(&start, NULL);
    ok = FSCDecode(in, in_size, &out, &out_size);
    if (!ok) {
      fprintf(stderr, "ERROR while decoding!\n");
      goto End;
    }
    if (stats_only) {
      const double elapsed = GetElapsed(&tmp, &start);
      const double MS = 1.e-6 * out_size;
      printf("Dec time: %.3f sec [%.2lf MS/s].\n", elapsed, MS / elapsed);
    }
  }

  if (!stats_only) {
    ok = (fwrite(out, out_size, 1, stdout) == 1);
    if (!ok) {
      fprintf(stderr, "Error writing to stdout!\n");
      goto End;
    }
  }

 End:
  free(in);
  free(out);
  return !ok;
}