util.cc
来自「用于计算矩阵的特征值,及矩阵的其他运算.可以用与稀疏矩阵」· CC 代码 · 共 474 行
CC
474 行
// Copyright (C) 2002 Charless C. Fowlkes <fowlkes@eecs.berkeley.edu>// Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of the// License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.#include <iostream>#include <string.h>#include <stdio.h>#include <assert.h>#include <stdarg.h>#include <ctype.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include "exception.hh"#include "string.hh"#include "util.hh"#include "array.hh"#include "message.hh"namespace Util { void registerConfig() { Message::registerConfig(); Random::registerConfig(); } void init() { Message::init(); Random::init(); } FILE *openInputStrm(const char *fileName) throw(Exception) { if (strcmp(fileName, "-") == 0) { return stdin; } if (strcmp(fileName, "stdin") == 0) { return stdin; } FILE *strm = fopen(fileName, "r"); if (strm == NULL) { throw Exception(String ("Could not open file \"%s\" for reading.\n", fileName)); } return strm; } FILE *openOutputStrm(const char *fileName) throw(Exception) { if (strcmp(fileName, "-") == 0) { return stdout; } if (strcmp(fileName, "stdout") == 0) { return stdout; } if (strcmp(fileName, "stderr") == 0) { return stderr; } FILE *strm = fopen(fileName, "w"); if (strm == NULL) { throw Exception(String ("Could not open file \"%s\" for writing.\n", fileName)); } return strm; } void bucketSort(const uint * data, uint nElem, uint maxVal, uint * perm, uint * scratch) { uint *counts; if (scratch == NULL) { counts = new uint[maxVal + 1]; } else { counts = scratch; } // Initialize counts. for (uint i = 0; i <= maxVal; i++) { counts[i] = 0; } // Count the values. for (uint i = 0; i < nElem; i++) { uint val = data[i]; assert(val <= maxVal); counts[val]++; } // Compute parallel prefix of counts, shifted right one element. for (uint sum = 0, i = 0; i <= maxVal; i++) { uint tmp = counts[i]; counts[i] = sum; sum += tmp; } // Compute permutation vector. for (uint i = 0; i < nElem; i++) { uint val = data[i]; assert(val <= maxVal); assert(counts[val] < nElem); perm[counts[val]++] = i; } // Delete scratch space if we allocated it. if (scratch == NULL) { delete[]counts; } } static const uint b = 10; uint bucketSortCompressScratchSize(uint maxVal) { return (maxVal >> (b + 12)) + 1 + (maxVal >> 6) + 1; } void bucketSortCompress(uint * data, uint & nElem, uint maxVal, uint64 * scratch) { uint64 *smallBitvec; uint64 *largeBitvec; uint n = bucketSortCompressScratchSize(maxVal); if (scratch == NULL) { uint64 *scratch = new uint64[n]; smallBitvec = &scratch[0]; largeBitvec = &scratch[(maxVal >> (b + 12)) + 1]; } else { smallBitvec = &scratch[0]; largeBitvec = &scratch[(maxVal >> (b + 12)) + 1]; } // Initialize bitvector to zero. memset(smallBitvec, 0, n * 8); // Set bits based on the values. for (uint i = 0; i < nElem; i++) { uint val = data[i]; assert(val <= maxVal); uint index, offset; index = val >> (b + 12); offset = (val >> (b + 6)) & 0x3f; smallBitvec[index] |= 1 << offset; index = val >> 6; offset = val & 0x3f; largeBitvec[index] |= 1 << offset; } // Find the set bits. uint count = 0; for (uint index = 0; index < ((maxVal >> (b + 12)) + 1); index++) { uint64 word = smallBitvec[index]; if (word == 0) { continue; } for (uint offset = 0; offset < 64; offset++) { if ((word & (1 << offset)) == 0) { continue; } uint start = ((index << 6) + offset) << b; for (uint index = start; index < start + (1 << b); index++) { uint64 word = largeBitvec[index]; if (word == 0) { continue; } for (uint offset = 0; offset < 64; offset++) { if ((word & (1 << offset)) == 0) { continue; } uint val = (index << 6) + offset; data[count++] = val; } } } } nElem = count; // Delete scratch space if we allocated it. if (scratch == NULL) { delete[]smallBitvec; } }// O(n) implementation. static void _kOfN_largeK(uint k, uint n, uint * values) { assert(k > 0); assert(k <= n); uint j = 0; for (uint i = 0; i < n; i++) { double prob = (double) (k - j) / (n - i); assert(prob <= 1); double x = Util::rand->fp(); if (x < prob) { values[j++] = i; } } assert(j == k); }// O(k*lg(k)) implementation; constant factor is about 2x the constant// factor for the O(n) implementation. static void _kOfN_smallK(uint k, uint n, uint * values) { assert(k > 0); assert(k <= n); if (k == 1) { values[0] = Util::rand->ui32(0, n - 1); return; } uint leftN = n / 2; uint rightN = n - leftN; uint leftK = 0; uint rightK = 0; for (uint i = 0; i < k; i++) { uint x = Util::rand->ui32(0, n - i - 1); if (x < leftN - leftK) { leftK++; } else { rightK++; } } if (leftK > 0) { _kOfN_smallK(leftK, leftN, values); } if (rightK > 0) { _kOfN_smallK(rightK, rightN, values + leftK); } for (uint i = leftK; i < k; i++) { values[i] += leftN; } }// Return k randomly selected integers from the interval [0,n), in// increasing sorted order. void kOfN(uint k, uint n, uint * values) { if (k == 0) { return; } static double log2 = log(2); double klogk = k * log(k) / log2; if (klogk < n / 2) { _kOfN_smallK(k, n, values); } else { _kOfN_largeK(k, n, values); } } void bug(const char *fmt, ...) { va_list ap; fflush(stdout); fprintf(stderr, "\nINTERNAL BUG: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); abort(); } void fatal(const char *fmt, ...) { va_list ap; fflush(stdout); fprintf(stderr, "\nFATAL ERROR: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(1); } void warning(const char *fmt, ...) { va_list ap; fflush(stdout); fprintf(stderr, "WARNING: "); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } void system(const char *cmd) { std::cerr << "Executing command: " << cmd << std::endl; int status =::system(cmd); if (status == -1) { throw Exception(String("Util::sytem(): system() failed.")); } if (status != 0) { throw Exception(String("Util::sytem(%s): status = %d.", cmd, status)); } }// Execute the command.// Argument list must be NULL-terminated!// Return only if the command exited normally. void execute(const char *path, ...) { va_list ap; // count the number of arguments int argc = 1; va_start(ap, path); while (va_arg(ap, const char *) != NULL) { argc++; } va_end(ap); // create an array of arguments Util::Array1D < const char *>argv(argc + 1); va_start(ap, path); argv(0) = path; String command("%s", argv(0)); for (int i = 1; i <= argc; i++) { argv(i) = va_arg(ap, const char *); if (i < argc) { command.append(" %s", argv(i)); } } va_end(ap); assert(argv(argc) == NULL); std::cerr << "Executing command: " << command << std::endl; // fork and execute command int pid = fork(); if (pid == -1) { throw Exception(String("Util::system(): fork() failed.")); } if (pid == 0) { // child : exec the command (void) execvp(path, (char *const *) argv.data()); // execvp() should never return throw Exception(String("Util::system(): execvp(%s,%s) failed.", path, command.text())); } else { // parent : wait for child int status; int rval = waitpid(pid, &status, 0); // make sure waitpid() call succeeded if (rval != pid) { throw Exception(String("Util::sytem(): waitpid() failed.")); } // make sure child exited normally, under its own // control if (!WIFEXITED(status)) { throw Exception(String ("Util::sytem(): command '%s' exited abnormally.", command.text())); } // make sure child's exit status was 0 if (WEXITSTATUS(status) != 0) { throw Exception(String ("Util::sytem(): command '%s' exited with status=%d.", command.text(), WEXITSTATUS(status))); } // command succeeded return; } }// execvp the program, and return the ends of the pipes corresponding// to the program's stdin, stdout, stderr. int systemPipe(const char *file, char *const argv[], FILE * &in, FILE * &out) { // create the pipes int inPipe[2]; int outPipe[2]; if (pipe(inPipe) == -1) { throw Exception("systemPipe: pipe failed"); } if (pipe(outPipe) == -1) { throw Exception("systemPipe: pipe failed"); } // get process group id of the parent pid_t pgid = getpgrp(); if (pgid == -1) { throw Exception("systemPipe: getpgid failed"); } // fork pid_t pid = fork(); if (pid == -1) { throw Exception("systemPipe: fork failed"); } if (pid == 0) { // CHILD // set process group id to that of the parent if (setpgid(0, pgid) == -1) { std::cerr << "systemPipe: setpgid failed" << std::endl; exit(1); } // bind the pipe ends to stdin and stdout if (dup2(inPipe[0], 0) == -1) { std::cerr << "systemPipe: dup2 failed" << std::endl; exit(1); } if (dup2(outPipe[1], 1) == -1) { std::cerr << "systemPipe: dup2 failed" << std::endl; exit(1); } // close unused file descriptors if (close(inPipe[1]) == -1) { std::cerr << "systemPipe: close failed" << std::endl; exit(1); } if (close(outPipe[0]) == -1) { std::cerr << "systemPipe: close failed" << std::endl; exit(1); } if (close(inPipe[0]) == -1) { std::cerr << "systemPipe: close failed" << std::endl; exit(1); } if (close(outPipe[1]) == -1) { std::cerr << "systemPipe: close failed" << std::endl; exit(1); } // exec if (execvp(file, argv) == -1) { std::cerr << "systemPipe: execvp failed" << std::endl; exit(1); } } // close unused file descriptors if (close(inPipe[0]) == -1) { throw Exception("systemPipe: close failed"); } if (close(outPipe[1]) == -1) { throw Exception("systemPipe: close failed"); } // recast pipe ends as streams in = fdopen(inPipe[1], "w"); out = fdopen(outPipe[0], "r"); if (in == NULL || out == NULL) { throw Exception("systemPipe: fdopen failed"); } // return pid of child return pid; } double mod (double x, double y) { return (y==0) ? x : (x - y*floor(x/y)); }} // namespace Util
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?