text:
/*
 *  Phusion Passenger - http://www.modrails.com/
 *  Copyright (c) 2009 Phusion
 *
 *  "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <cstring>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>

#include <set>
#include <vector>
#include <string>

#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include "oxt/thread.hpp"
#include "oxt/system_calls.hpp"

#include "ScgiRequestParser.h"
#include "HttpStatusExtractor.h"

#include "StandardApplicationPool.h"
#include "ApplicationPoolStatusReporter.h"
#include "Application.h"
#include "PoolOptions.h"
#include "Exceptions.h"
#include "Utils.h"

using namespace boost;
using namespace oxt;
using namespace Passenger;

#define HELPER_SERVER_PASSWORD_SIZE     64

/**
 * Wrapper class around a file descriptor integer, for RAII behavior.
 *
 * A FileDescriptor object behaves just like an int, so that you can pass it to
 * system calls such as read(). It performs reference counting. When the last
 * copy of a FileDescriptor has been destroyed, the underlying file descriptor
 * will be automatically closed.
 */
class FileDescriptor {
private:
	struct SharedData {
		int fd;

		/**
		 * Constructor to assign this file descriptor's handle.
		 */
		SharedData(int fd) {
			this->fd = fd;
		}

		/**
		 * Attempts to close this file descriptor. When created on the stack,
		 * this destructor will automatically be invoked as a result of C++
		 * semantics when exiting the scope this object was created in. This
		 * ensures that stack created objects with destructors like these will
		 * de-allocate their resources upon leaving their corresponding scope.
		 * This pattern is also known Resource Acquisition Is Initialization (RAII).
		 *
		 * @throws SystemException File descriptor could not be closed.
		 */
		~SharedData() {
			if (syscalls::close(fd) == -1) {
				throw SystemException("Cannot close file descriptor", errno);
			}
		}
	};

	/* Shared pointer for reference counting on this file descriptor */
	shared_ptr<SharedData> data;

public:
	FileDescriptor() {
		// Do nothing.
	}

	/**
	 * Creates a new FileDescriptor instance with the given fd as a handle.
	 */
	FileDescriptor(int fd) {
		data = ptr(new SharedData(fd));
	}

	/**
	 * Overloads the integer cast operator so that it will return the file
	 * descriptor handle as an integer.
	 *
	 * @return This file descriptor's handle as an integer.
	 */
	operator int () const {
		return data->fd;
	}
};

/**
 * A representation of a Client from the Server's point of view. This class
 * contains the methods used to communicate from a server to a connected
 * client, i.e. it is a client handler.
 * These Client instances will communicate concurrently with the server through
 * threads. Considering the overhead of these threads, i.e. setup and teardown
 * costs and the volatility of client requests, these client instances will be
 * pooled. It is for this reason that the State design pattern has been applied:
 * this class can be considered as being a skeleton implemention whose state
 * --e.g. the client file descriptor-- needs to be provided in order to function
 * properly.
 */
class Client {
private:
	/** The client thread stack size in bytes. */
	static const int CLIENT_THREAD_STACK_SIZE = 1024 * 128;

	/** The client number for this Client object, assigned by Server. */
	unsigned int number;

	/** The application pool to which this Client object belongs to. */
	StandardApplicationPoolPtr pool;

	/** This client's password. */
	string password;

	/** Whether privilege lowering should be used. */
	bool lowerPrivilege;

	/** The user that spawned processes should run as, if initial attempt
	 * at privilege lowering failed. */
	string lowestUser;

	/** The server socket file descriptor. */
	int serverSocket;

	/** This client's thread. */
	oxt::thread *thr;

	/**
	 * Attempts to accept a connection made by the client.
	 *
	 * @return The file descriptor corresponding to the accepted connection.
	 * @throws SystemException Could not accept new connection.
	 */
	FileDescriptor acceptConnection() {
		TRACE_POINT();
		struct sockaddr_un addr;
		socklen_t addrlen = sizeof(addr);
		int fd = syscalls::accept(serverSocket,
			(struct sockaddr *) &addr,
			&addrlen);
		if (fd == -1) {
			throw SystemException("Cannot accept new connection", errno);
		} else {
			return FileDescriptor(fd);
		}
	}

	/**
	 * Reads and checks the password of a client message channel identified by the given file descriptor.
	 * The HelperServer makes extensive use of Unix Sockets that would normally allow other processes to
	 * connect to it as well. In our case, we just want to limit this to Nginx and it is for this reason
	 * that we've secured communication channels between this server and its clients with passwords.
	 * This method indicates whether or not the password of this client channel matches the one known to
	 * the server.
	 *
	 * @param fd The file descriptor identifying the client message channel.
	 * @return True if the password of the client channel indicated by the given file descriptor
	 *   matches the password known to the server. False will be returned if either the
	 *   passwords don't match or EOF has been encountered.
	 */
	bool readAndCheckPassword(FileDescriptor &fd) {
		TRACE_POINT();
		MessageChannel channel(fd);
		char buf[HELPER_SERVER_PASSWORD_SIZE];

		if (channel.readRaw(buf, sizeof(buf))) {
			const char *password_data;

			password_data = const_cast<const string &>(password).c_str();
			return memcmp(password_data, buf, sizeof(buf)) == 0;
		} else {
			return false;
		}
	}

	/**
	 * Reads and parses the request headers from the given file descriptor with the given SCGI request parser
	 * and if succesful, assigns the remainder of the request (i.e. non SCGI header data) to the given
	 * requestBody.
	 *
	 * @param fd The file descriptor to read and parse from.
	 * @param parser The ScgiRequestParser to use for parsing the SCGI headers.
	 * @param requestBody The requestBody that was extracted as a result from parsing the SCGI headers.
	 * @return True if the request was succesfully read and parsed. False if an invalid SCGI header was
	 *   received by the parser or if the header information was invalid.
	 * @throws SystemException Request header could not be read.
	 */
	bool readAndParseRequestHeaders(FileDescriptor &fd, ScgiRequestParser &parser, string &requestBody) {
		TRACE_POINT();
		char buf[1024 * 16];
		ssize_t size;
		unsigned int accepted = 0;

		do {
			size = syscalls::read(fd, buf, sizeof(buf));
			if (size == -1) {
				throw SystemException("Cannot read request header", errno);
			} else if (size == 0) {
				break;
			} else {
				accepted = parser.feed(buf, size);
			}
		} while (parser.acceptingInput());

		if (parser.getState() != ScgiRequestParser::DONE) {
			P_ERROR("Invalid SCGI header received.");
			return false;
		} else if (!parser.hasHeader("DOCUMENT_ROOT")) {
			P_ERROR("DOCUMENT_ROOT header is missing.");
			return false;
		} else {
			requestBody.assign(buf + accepted, size - accepted);
			return true;
		}
	}

	/**
	 * Sends a request body to this client. The <tt>partialRequestBody</tt> will first be
	 * sent to the specified <tt>session</tt>, but if the specified <tt>contentLength</tt>
	 * is larger than the size of the <tt>partialRequestBody</tt>, then this method will
	 * attempt to read the remaining bytes from the specified <tt>clientFd</tt> and send it
	 * to the <tt>session</tt> as well until <tt>contentLength</tt> bytes have been sent in
	 * total.
	 *
	 * @param session The Ruby on Rails application instance.
	 * @param clientFd The client file descriptor to send the request body to.
	 * @param partialRequestBody The partial request body to send to this client.
	 * @param contentLength The content length of the request body in bytes.
	 * @throws SystemException Request body could not be read from the specified
	 *   <tt>clientFd</tt>.
	 */
	void sendRequestBody(Application::SessionPtr &session,
	                     FileDescriptor &clientFd,
	                     const string &partialRequestBody,
	                     unsigned long contentLength) {
		TRACE_POINT();
		char buf[1024 * 16];
		ssize_t size;
		size_t bytesToRead;
		unsigned long bytesForwarded = 0;

		if (partialRequestBody.size() > 0) {
			UPDATE_TRACE_POINT();
			session->sendBodyBlock(partialRequestBody.c_str(),
				partialRequestBody.size());
			bytesForwarded = partialRequestBody.size();
		}

		bool done = bytesForwarded == contentLength;
		while (!done) {
			UPDATE_TRACE_POINT();

			bytesToRead = contentLength - bytesForwarded;
			if (bytesToRead > sizeof(buf)) {
				bytesToRead = sizeof(buf);
			}
			size = syscalls::read(clientFd, buf, bytesToRead);

			if (size == 0) {
				done = true;
			} else if (size == -1) {
				throw SystemException("Cannot read request body", errno);
			} else {
				UPDATE_TRACE_POINT();
				session->sendBodyBlock(buf, size);
				bytesForwarded += size;
				done = bytesForwarded == contentLength;
			}
		}
	}

	/**
	 * Forwards an HTTP response from the given (Rails) <tt>session</tt> to the
	 * given <tt>clientFd</tt>.
	 *
	 * @param session The Ruby on Rails session to read the response from.
	 * @param clientFd The client file descriptor to write the response to.
	 * @throws SystemException Response could not be read from backend (Rails) process.
	 */
	void forwardResponse(Application::SessionPtr &session, FileDescriptor &clientFd) {
		TRACE_POINT();
		HttpStatusExtractor ex;
		int stream = session->getStream();
		int eof = false;
		MessageChannel output(clientFd);
		char buf[1024 * 32];
		ssize_t size;

		/* Read data from the backend process until we're able to
		 * extract the HTTP status line from it.
		 */
		while (!eof) {
			UPDATE_TRACE_POINT();
			size = syscalls::read(stream, buf, sizeof(buf));
			if (size == 0) {
				eof = true;
			} else if (size == -1) {
				throw SystemException("Cannot read response from backend process", errno);
			} else if (ex.feed(buf, size)) {
				/* We now have an HTTP status line. Send back
				 * a proper HTTP response, then exit this while
				 * loop and continue with forwarding the rest
				 * of the response data.
				 */
				UPDATE_TRACE_POINT();
				string statusLine("HTTP/1.1 ");
				statusLine.append(ex.getStatusLine());
				UPDATE_TRACE_POINT();
				output.writeRaw(statusLine.c_str(), statusLine.size());
				UPDATE_TRACE_POINT();
				output.writeRaw(ex.getBuffer().c_str(), ex.getBuffer().size());
				break;
			}
		}

		UPDATE_TRACE_POINT();
		while (!eof) {
			UPDATE_TRACE_POINT();
			size = syscalls::read(stream, buf, sizeof(buf));
			if (size == 0) {
				eof = true;
			} else if (size == -1) {
				throw SystemException("Cannot read response from backend process", errno);
			} else {
				UPDATE_TRACE_POINT();
				output.writeRaw(buf, size);
			}
		}
	}

	/**
	 * Handles a spawn related exception by writing an appropriate HTTP error response (500)
	 * for the given spawn exception <tt>e</ee> to given file descriptor <tt>fd</tt>'s message
	 * channel.
	 *
	 * @param fd The file descriptor identifying the message channel to write the given
	 *   spawn exception <tt>e</tt> to.
	 * @param e The spawn exception to be written to the given <tt>fd</tt>'s message
	 *   channel.
	 */
	void handleSpawnException(FileDescriptor &fd, const SpawnException &e) {
		MessageChannel channel(fd);
		channel.writeRaw("HTTP/1.1 500 Internal Server Error\x0D\x0A");
		channel.writeRaw("Status: 500 Internal Server Error\x0D\x0A");
		channel.writeRaw("Connection: close\x0D\x0A");
		channel.writeRaw("Content-Type: text/html; charset=utf-8\x0D\x0A");

		if (e.hasErrorPage()) {
			channel.writeRaw("Content-Length: " +
				toString(e.getErrorPage().size()) +
				"\x0D\x0A");
			channel.writeRaw("\x0D\x0A");
			channel.writeRaw(e.getErrorPage());
		} else {
			channel.writeRaw("Content-Length: " +
				toString(strlen(e.what())) + "\x0D\x0A");
			channel.writeRaw("\x0D\x0A");
			channel.writeRaw(e.what());
		}
	}

	/**
	 * Handles an SCGI request from a client whose identity is derived by the given <tt>clientFd</tt>.
	 *
	 * @param clientFd The file descriptor identifying the client to handle the request from.
	 * @return True if an error occurred while trying to handle the request of the client. False if
	 *   the request was succesfully processed.
	 */
	bool handleRequest(FileDescriptor &clientFd) {
		TRACE_POINT();
		ScgiRequestParser parser;
		string partialRequestBody;
		unsigned long contentLength;

		if (!readAndCheckPassword(clientFd)) {
			P_ERROR("Client did not send a correct password.");
			return true;
		}
		if (!readAndParseRequestHeaders(clientFd, parser, partialRequestBody)) {
			return true;
		}

		try {
			PoolOptions options;
			if (parser.getHeader("RAILS_RELATIVE_URL_ROOT").empty()) {
				options.appRoot = extractDirName(parser.getHeader("DOCUMENT_ROOT"));
			} else {
				options.appRoot = extractDirName(resolveSymlink(parser.getHeader("DOCUMENT_ROOT")));
			}
			options.useGlobalQueue = parser.getHeader("PASSENGER_USE_GLOBAL_QUEUE") == "true";
			options.environment    = parser.getHeader("PASSENGER_ENVIRONMENT");
			options.spawnMethod    = parser.getHeader("PASSENGER_SPAWN_METHOD");
			options.lowerPrivilege = lowerPrivilege;
			options.lowestUser     = lowestUser;
			options.appType        = parser.getHeader("PASSENGER_APP_TYPE");
			options.frameworkSpawnerTimeout = atol(parser.getHeader("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME"));
			options.appSpawnerTimeout       = atol(parser.getHeader("PASSENGER_APP_SPAWNER_IDLE_TIME"));

			try {
				Application::SessionPtr session(pool->get(options));

				UPDATE_TRACE_POINT();
				session->sendHeaders(parser.getHeaderData().c_str(),
					parser.getHeaderData().size());

				contentLength = atol(
					parser.getHeader("CONTENT_LENGTH").c_str());
				sendRequestBody(session,
					clientFd,
					partialRequestBody,
					contentLength);

				session->shutdownWriter();
				forwardResponse(session, clientFd);
			} catch (const SpawnException &e) {
				handleSpawnException(clientFd, e);
			}
			return false;
		} catch (const boost::thread_interrupted &) {
			throw;
		} catch (const tracable_exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace:\n" << e.backtrace());
			return true;
		} catch (const exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace: not available");
			return true;
		} catch (...) {
			P_ERROR("Uncaught unknown exception in PassengerServer client thread.");
			return true;
		}
	}

	/**
	 * This client's main thread, responsible for accepting connections made by a client
	 * to the server and to handle its request.
	 *
	 * @see acceptConnection(void)
	 * @see handleRequest(FileDescriptor)
	 */
	void threadMain() {
		TRACE_POINT();
		try {
			while (true) {
				UPDATE_TRACE_POINT();
				FileDescriptor fd(acceptConnection());
				handleRequest(fd);
			}
		} catch (const boost::thread_interrupted &) {
			P_TRACE(2, "Client thread " << this << " interrupted.");
		} catch (const tracable_exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace:\n" << e.backtrace());
			abort();
		} catch (const exception &e) {
			P_ERROR("Uncaught exception in PassengerServer client thread:\n"
				<< "   exception: " << e.what() << "\n"
				<< "   backtrace: not available");
			abort();
		} catch (...) {
			P_ERROR("Uncaught unknown exception in PassengerServer client thread.");
			throw;
		}
	}

public:
	/**
	 * Constructs a client handler for the server with the given arguments and runs
	 * it in its own thread.
	 *
	 * @param number The id assigned by the server to identify this client by.
	 * @param pool The application pool where this client belongs to.
	 * @param password The password that is required to connect to this client handler.
	 *   This value is determined and assigned by the server.
	 * @param lowerPrivilege Whether privilege lowering should be used.
	 * @param lowestUser The user that spawned processes should run as, if
	 *   initial attempt at privilege lowering failed.
	 * @param serverSocket The server socket to accept this clients connection from.
	 */
	Client(unsigned int number, StandardApplicationPoolPtr &pool,
	       const string &password, bool lowerPrivilege,
	       const string &lowestUser, int serverSocket) {
		this->number = number;
		this->pool = pool;
		this->password = password;
		this->lowerPrivilege = lowerPrivilege;
		this->lowestUser = lowestUser;
		this->serverSocket = serverSocket;
		thr = new oxt::thread(
			bind(&Client::threadMain, this),
			"Client thread " + toString(number),
			CLIENT_THREAD_STACK_SIZE
		);
	}

	/**
	 * Destroys this client and its thread.
	 */
	~Client() {
		TRACE_POINT();
		this_thread::disable_syscall_interruption dsi;
		this_thread::disable_interruption di;

		thr->interrupt_and_join();
		delete thr;
	}
};

typedef shared_ptr<Client> ClientPtr;

/**
 * A representation of the Server responsible for handling Client instances.
 *
 * @see Client
 */
class Server {
private:
	static const unsigned int BACKLOG_SIZE = 50;

	string password;
	int adminPipe;
	int serverSocket;
	bool userSwitching;
	string defaultUser;
	unsigned int numberOfThreads;
	set<ClientPtr> clients;
	StandardApplicationPoolPtr pool;
	shared_ptr<ApplicationPoolStatusReporter> reporter;

	/**
	 * Starts listening for client connections from this server's <tt>serverSocket</tt>.
	 * This server will first attempt to create an unconnected Unix socket on which it will
	 * attempt to bind on. Once it is bound, it will start listening for incoming client
	 * activity.
	 *
	 * @throws SystemException Could not create unconnected Unix socket or bind on Unix socket.
	 */
	void startListening() {
		this_thread::disable_syscall_interruption dsi;
		string socketName = getPassengerTempDir() + "/master/helper_server.sock";
		struct sockaddr_un addr;
		int ret;

		serverSocket = syscalls::socket(PF_UNIX, SOCK_STREAM, 0);
		if (serverSocket == -1) {
			throw SystemException("Cannot create an unconnected Unix socket", errno);
		}

		addr.sun_family = AF_UNIX;
		strncpy(addr.sun_path, socketName.c_str(), sizeof(addr.sun_path));
		addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';

		ret = syscalls::bind(serverSocket, (const struct sockaddr *) &addr, sizeof(addr));
		if (ret == -1) {
			int e = errno;
			syscalls::close(serverSocket);

			string message("Cannot bind on Unix socket '");
			message.append(socketName);
			message.append("'");
			throw SystemException(message, e);
		}

		ret = syscalls::listen(serverSocket, BACKLOG_SIZE);
		if (ret == -1) {
			int e = errno;
			syscalls::close(serverSocket);

			string message("Cannot bind on Unix socket '");
			message.append(socketName);
			message.append("'");
			throw SystemException(message, e);
		}

		do {
			ret = chmod(socketName.c_str(), S_ISVTX |
				S_IRUSR | S_IWUSR | S_IXUSR |
				S_IRGRP | S_IWGRP | S_IXGRP |
				S_IROTH | S_IWOTH | S_IXOTH);
		} while (ret == -1 && errno == EINTR);
	}

	/**
	 * Starts the client handler threads that are responsible for handling the communication
	 * between the client and this Server.
	 *
	 * @see Client
	 */
	void startClientHandlerThreads() {
		for (unsigned int i = 0; i < numberOfThreads; i++) {
			ClientPtr client(new Client(i + 1, pool, password,
				userSwitching, defaultUser, serverSocket));
			clients.insert(client);
		}
	}

	/**
	 * Lowers this process's privilege to that of <em>username</em>.
	 */
	void lowerPrivilege(const string &username) {
		struct passwd *entry;

		entry = getpwnam(username.c_str());
		if (entry != NULL) {
			if (initgroups(username.c_str(), entry->pw_gid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set supplementary groups for this "
					"user: " << strerror(e) << " (" << e << ")");
			}
			if (setgid(entry->pw_gid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set group ID: " << strerror(e) <<
					" (" << e << ")");
			}
			if (setuid(entry->pw_uid) != 0) {
				int e = errno;
				P_WARN("WARNING: Unable to lower Passenger HelperServer's "
					"privilege to that of user '" << username <<
					"': cannot set user ID: " << strerror(e) <<
					" (" << e << ")");
			}
		} else {
			P_WARN("WARNING: Unable to lower Passenger HelperServer's "
				"privilege to that of user '" << username <<
				"': user does not exist.");
		}
	}

public:
	/**
	 * Creates a server instance based on the given parameters, which starts to listen
	 * for clients.
	 *
	 * @param password The password this server uses for its clients.
	 * @param rootDir The Passenger root folder.
	 * @param ruby The filename of the Ruby interpreter to use.
	 * @param adminPipe The pipe that is used to receive this Server's password and to see if Nginx
	 *   has exited.
	 * @param feedbackPipe The feedback pipe, used for telling the web server that we're done
	 *   initializing.
	 * @param maxPoolSize The maximum number of simultaneously alive application instances.
	 * @param maxInstancesPerApp The maximum number of simultaneously alive Rails instances that
	 *   a single Rails application may occupy.
	 * @param poolIdleTime The maximum number of seconds that an application may be idle before
	 *   it gets terminated.
	 * @param userSwitching Whether user switching should be used.
	 * @param defaultUser If user switching is turned on, then this is the
	 *   username that a process should lower its privilege to if the
	 *   initial attempt at user switching fails. If user switching is off,
	 *   then this is the username that HelperServer and all spawned
	 *   processes should run as.
	 * @param workerUid The UID of the web server's worker processes. Used for determining
	 *   the optimal permissions for some temp files.
	* @param workerGid The GID of the web server's worker processes. Used for determining
	 *   the optimal permissions for some temp files.
	 */
	Server(const string &password, const string &rootDir, const string &ruby,
	       int adminPipe, int feedbackPipe, unsigned int maxPoolSize,
	       unsigned int maxInstancesPerApp, unsigned int poolIdleTime,
	       bool userSwitching, const string &defaultUser, uid_t workerUid,
	       gid_t workerGid) {
		this->password      = password;
		this->adminPipe     = adminPipe;
		this->userSwitching = userSwitching;
		this->defaultUser   = defaultUser;
		numberOfThreads     = maxPoolSize * 4;

		removeDirTree(getPassengerTempDir());
		createPassengerTempDir(getSystemTempDir(), userSwitching, defaultUser,
			workerUid, workerGid);
		startListening();

		if (!userSwitching && geteuid() == 0) {
			lowerPrivilege(defaultUser);
		}

		pool = ptr(new StandardApplicationPool(
			rootDir + "/bin/passenger-spawn-server",
			"", ruby
		));
		pool->setMax(maxPoolSize);
		pool->setMaxPerApp(maxInstancesPerApp);
		pool->setMaxIdleTime(poolIdleTime);

		reporter = ptr(new ApplicationPoolStatusReporter(pool, userSwitching,
				S_IRUSR | S_IWUSR));

		// Tell the web server that we're done initializing.
		syscalls::close(feedbackPipe);
	}

	~Server() {
		TRACE_POINT();
		this_thread::disable_syscall_interruption dsi;
		this_thread::disable_interruption di;

		P_DEBUG("Shutting down helper server...");
		clients.clear();
		P_TRACE(2, "All threads have been shut down.");
		syscalls::close(serverSocket);
		syscalls::close(adminPipe);
	}

	/**
	 * Starts this server by starting the client handlers threads.
	 *
	 * @see startCientHandlerThreads
	 */
	void start() {
		TRACE_POINT();
		char buf;

		startClientHandlerThreads();

		try {
			// Wait until the web server has exited.
			syscalls::read(adminPipe, &buf, 1);
		} catch (const boost::thread_interrupted &) {
			// Do nothing.
		}
	}
};

/**
 * Ignores the SIGPIPE signal that in general is raised when a computer program attempts
 * to write to a pipe without a processes connected to the other end. This is used to
 * prevent Nginx from getting killed by the default signal handler when it attempts to
 * write the server password to the HelperServer in the situation that the HelperServer
 * failed to start.
 */
static void
ignoreSigpipe() {
	struct sigaction action;
	action.sa_handler = SIG_IGN;
	action.sa_flags   = 0;
	sigemptyset(&action.sa_mask);
	sigaction(SIGPIPE, &action, NULL);
}

/**
 * Extracts and returns the password from the given <tt>adminPipe</tt>. This password is
 * used to determine which processes may connect with this server's Unix socket, as unix
 * sockets would normally allow any process to connect to it. In this case, we strictly
 * want Nginx to be able to connect to it, and it is for this reason that we maintain a
 * password system.
 *
 * @param adminPipe The pipe used to read the password for this server from.
 * @return The password for this server.
 */
static string
receivePassword(int adminPipe) {
	TRACE_POINT();
	MessageChannel channel(adminPipe);
	char buf[HELPER_SERVER_PASSWORD_SIZE];

	if (!channel.readRaw(buf, HELPER_SERVER_PASSWORD_SIZE)) {
		throw IOException("Could not read password from the admin pipe.");
	}
	return string(buf, HELPER_SERVER_PASSWORD_SIZE);
}

/**
 * Initializes and starts the helper server that is responsible for handling communication
 * between Nginx and the backend Rails processes.
 *
 * @see Server
 * @see Client
 */
int
main(int argc, char *argv[]) {
	TRACE_POINT();
	try {
		setup_syscall_interruption_support();
		ignoreSigpipe();

		string password;
		string rootDir  = argv[1];
		string ruby      = argv[2];
		int adminPipe    = atoi(argv[3]);
		int feedbackPipe = atoi(argv[4]);
		int logLevel     = atoi(argv[5]);
		int maxPoolSize  = atoi(argv[6]);
		int maxInstancesPerApp = atoi(argv[7]);
		int poolIdleTime       = atoi(argv[8]);
		bool userSwitching = strcmp(argv[9], "1") == 0;
		string defaultUser = argv[10];
		uid_t workerUid    = (uid_t) atoll(argv[11]);
		gid_t workerGid    = (gid_t) atoll(argv[12]);
		string passengerTempDir = argv[13];

		setLogLevel(logLevel);
		P_DEBUG("Passenger helper server started on PID " << getpid());

		setPassengerTempDir(passengerTempDir);

		password = receivePassword(adminPipe);
		P_TRACE(2, "Password received.");

		Server(password, rootDir, ruby, adminPipe, feedbackPipe, maxPoolSize,
			maxInstancesPerApp, poolIdleTime, userSwitching,
			defaultUser, workerUid, workerGid).start();
	} catch (const tracable_exception &e) {
		P_ERROR(e.what() << "\n" << e.backtrace());
		return 1;
	} catch (const exception &e) {
		P_ERROR(e.what());
		return 1;
	} catch (...) {
		P_ERROR("Unknown exception thrown in main thread.");
		throw;
	}

	P_TRACE(2, "Helper server exited.");
	return 0;
}

max_stars_repo_name: sjlombardo/passenger

max_issues_repo_name: tadman/passenger

max_forks_repo_name: tadman/passenger


text:
// ReadPDBfile.cpp

/* ---------------------------------------------------------
   standard libraries
   --------------------------------------------------------- */
// #include<debug.h>
// #include <stdio.h>
// #include <stdlib.h> // strtod?, stod
// #include <assert.h>
#include <string.h> // string.
// #include <cctype>
#include <algorithm> // remove_if, count
#include <iostream>
#include <fstream> // ifstream
#include <boost/algorithm/string.hpp>

#include <system.hpp>

// #include <ctime>
// #include <list>        // std::list
// #include <vector>
// #include <iterator> // istream_iterator

/* ---------------------------------------------------------
   headers
   --------------------------------------------------------- */
#include "debug.h"
#include "ReadPDBfile.hpp"

using namespace std;

/* ---------------------------------------------------------
   functions
   --------------------------------------------------------- */
int ReadPDBfile(char filename[40],int total_atoms,Atom *aa)
{
    // char filename
    // string fn
    // string line
    // ifstream pdbfile

    string fn(filename);
    cout << "Reading: " << fn.c_str() << endl;

    string line;
    string atomtype;
    // int at_end;
    ifstream pdbfile(fn.c_str());

    // While reading, count the atoms.
    int num_atoms;
    num_atoms = 0;
    // ,total_atoms;
    // total_atoms = -1;

    if (pdbfile.is_open())
    {
        cout << "pdbfile is now open." << endl;

        if (total_atoms == -1)
        {
            while(getline(pdbfile,line))
            {
                if (boost::algorithm::starts_with(line,"ATOM") == 1)
                {
                    num_atoms += 1;
                    // Atom a;
                }
            }
            pdbfile.close();
            total_atoms = num_atoms;
            cout << "pdbfile is now closed." << endl;

            return total_atoms;
        }
        else // total_atoms != -1.
        {
            while(getline(pdbfile,line))
            {
                // SPACE LINE
                if(line.find_first_not_of(' ') == std::string::npos)
                {
                    continue;
                }

                if (boost::algorithm::starts_with(line,"ATOM") == 1)
                {

                    // Atom a;

                    /* std::string str_index = line.substr(5,6);      // int */
                    /* std::string str_chain = line.substr(21,1); */
                    /* std::string str_resid = line.substr(23,3);     // int */
                    string str_x = line.substr(30,8);         // float
                    string str_y = line.substr(38,8);         // float
                    string str_z = line.substr(46,8);         // float
                    aa[num_atoms].x = atof(str_x.c_str());
                    aa[num_atoms].y = atof(str_y.c_str());
                    aa[num_atoms].z = atof(str_z.c_str());

                    // printf("index: %d\n",num_atoms);
                    aa[num_atoms].index = num_atoms;
                    aa[num_atoms].restype = line.substr(17,3); // GLY,ILE

                    // Need to remove whitespace from atomtype.
                    // aa[num_atoms].atomtype = line.substr(13,3);// CA,CG1,OD1
                    atomtype = line.substr(13,3);// CA,CG1,OD1
                    // remove_if(atomtype.begin(),atomtype.end(),isspace);
                    // atomtype.erase(remove_if(atomtype.begin(),atomtype.end(),isspace),atomtype.end());
                    // aa[num_atoms].atomtype = atomtype;
                    atomtype.erase(remove_if(atomtype.begin(),
                                             atomtype.end(),
                                             [](char x){return isspace(x);}),
                                   atomtype.end());
                    aa[num_atoms].atomtype = atomtype;
                    // std::cout << atomtype << " " << atomtype.length() << '\n';
                    // std::cout

                    // For Chain:
                    aa[num_atoms].chain = line.substr(21,1); // like "A"
                    // For Residue:
                    aa[num_atoms].resid = atoi(line.substr(23,3).c_str()); // 4,603 for 2KHO

                    try
                    {
                        aa[num_atoms].general_atomtype = line.substr(77,1); // C,N,O,F
                    }
                    catch (const std::out_of_range & e)
                    {
                        // std::cout<< e.what(); // message to console: vector::_M_range_check
                    }

                    // Count the Atoms:
                    num_atoms += 1;
                }
            }
            pdbfile.close();
            total_atoms = num_atoms;
            cout << "pdbfile is now closed." << endl;
        }
    }
    else
    {
        cout << "Unable to open pdbfile";
    }

    cout << "The number of atoms found was: " << num_atoms << endl;
    return total_atoms;
}

vAtoms ReadPDBfile(char filename[40])
{
    // char filename
    // string fn
    // string line
    // ifstream pdbfile
    vAtoms aa;

    string fn(filename);
    cout << "Reading: " << fn.c_str() << endl;

    string line;
    string atomtype;
    ifstream pdbfile(fn.c_str());

    // While reading, count the atoms.
    int num_atoms;
    num_atoms = 0;

    if (pdbfile.is_open())
    {
        cout << "pdbfile is now open." << endl;

        while(getline(pdbfile,line))
        {
            if (boost::algorithm::starts_with(line,"ATOM") == 1)
            {
                Atom a;
                // aa[num_atoms].push_back(a);

                /* std::string str_index = line.substr(5,6);      // int */
                /* std::string str_chain = line.substr(21,1); */
                /* std::string str_resid = line.substr(23,3);     // int */
                string str_x = line.substr(30,8);         // float
                string str_y = line.substr(38,8);         // float
                string str_z = line.substr(46,8);         // float
                // aa[num_atoms].x = atof(str_x.c_str());
                // aa[num_atoms].y = atof(str_y.c_str());
                // aa[num_atoms].z = atof(str_z.c_str());

                a.x = atof(str_x.c_str());
                a.y = atof(str_y.c_str());
                a.z = atof(str_z.c_str());

                // printf("index: %d\n",num_atoms);
                a.index = num_atoms;
                a.restype = line.substr(17,3); // GLY,ILE

                // Need to remove whitespace from atomtype.
                // aa[num_atoms].atomtype = line.substr(13,3);// CA,CG1,OD1
                atomtype = line.substr(13,3);// CA,CG1,OD1
                // remove_if(atomtype.begin(),atomtype.end(),isspace);
                // atomtype.erase(remove_if(atomtype.begin(),atomtype.end(),isspace),atomtype.end());
                // aa[num_atoms].atomtype = atomtype;
                atomtype.erase(remove_if(atomtype.begin(),
                                         atomtype.end(),
                                         [](char x){return isspace(x);}),
                               atomtype.end());
                a.atomtype = atomtype;
                // std::cout << atomtype << " " << atomtype.length() << '\n';
                // std::cout

                // For Chain:
                a.chain = line.substr(21,1); // like "A"
                // For Residue:
                a.resid = atoi(line.substr(23,3).c_str()); // 4,603 for 2KHO

                try
                {
                    a.general_atomtype = line.substr(77,1); // C,N,O,F
                }
                catch (const std::out_of_range & e)
                {
                    // std::cout<< e.what(); // message to console: vector::_M_range_check
                }

                aa.push_back(a);
                // Count the Atoms:
                num_atoms += 1;
            }

        }
        pdbfile.close();
        cout << "pdbfile is now closed." << endl;
    }
    else
    {
        cout << "Unable to open pdbfile";
    }

    cout << "The number of atoms found was: " << num_atoms << endl;
    return aa;
}

vAtoms ReadPDBfile(std::string fn)
{
    // char filename
    // string fn
    // string line
    // ifstream pdbfile
    vAtoms aa;

    // string fn(filename);
    // cout << "Reading: " << fn.c_str() << endl;
    cout << "Reading: " << fn << endl;

    string line;
    string atomtype;
    // ifstream pdbfile(fn.c_str());
    ifstream pdbfile(fn);

    // While reading, count the atoms.
    int num_atoms;
    num_atoms = 0;

    if (pdbfile.is_open())
    {
        cout << "pdbfile is now open." << endl;

        while(getline(pdbfile,line))
        {
            if (boost::algorithm::starts_with(line,"ATOM") == 1)
            {
                Atom a;
                // aa[num_atoms].push_back(a);

                /* std::string str_index = line.substr(5,6);      // int */
                /* std::string str_chain = line.substr(21,1); */
                /* std::string str_resid = line.substr(23,3);     // int */
                string str_x = line.substr(30,8);         // float
                string str_y = line.substr(38,8);         // float
                string str_z = line.substr(46,8);         // float
                // aa[num_atoms].x = atof(str_x.c_str());
                // aa[num_atoms].y = atof(str_y.c_str());
                // aa[num_atoms].z = atof(str_z.c_str());

                a.x = atof(str_x.c_str());
                a.y = atof(str_y.c_str());
                a.z = atof(str_z.c_str());

                // printf("index: %d\n",num_atoms);
                a.index = num_atoms;
                a.restype = line.substr(17,3); // GLY,ILE

                // Need to remove whitespace from atomtype.
                // aa[num_atoms].atomtype = line.substr(13,3);// CA,CG1,OD1
                atomtype = line.substr(13,3);// CA,CG1,OD1
                // remove_if(atomtype.begin(),atomtype.end(),isspace);
                // atomtype.erase(remove_if(atomtype.begin(),atomtype.end(),isspace),atomtype.end());
                // aa[num_atoms].atomtype = atomtype;
                atomtype.erase(remove_if(atomtype.begin(),
                                         atomtype.end(),
                                         [](char x){return isspace(x);}),
                               atomtype.end());
                a.atomtype = atomtype;
                // std::cout << atomtype << " " << atomtype.length() << '\n';
                // std::cout

                // For Chain:
                a.chain = line.substr(21,1); // like "A"
                // For Residue:
                a.resid = atoi(line.substr(23,3).c_str()); // 4,603 for 2KHO

                try
                {
                    a.general_atomtype = line.substr(77,1); // C,N,O,F
                }
                catch (const std::out_of_range & e)
                {
                    // std::cout<< e.what(); // message to console: vector::_M_range_check
                }

                aa.push_back(a);
                // Count the Atoms:
                num_atoms += 1;
            }

        }
        pdbfile.close();
        cout << "pdbfile is now closed." << endl;
    }
    else
    {
        cout << "Unable to open pdbfile";
    }

    cout << "The number of atoms found was: " << num_atoms << endl;
    return aa;
}

ext: cpp


text:
/**
 * @file walker.hpp
 * @brief Definition of the "walker" class.
 *
 * @author Maxim <john.jasper.doe@gmail.com>
 * @date 2020
 */

#ifndef WALKER_HPP_
#define WALKER_HPP_

#include "checker.hpp"

#include <boost/filesystem.hpp>

/** @brief Namespace of the projet "BAYAN" */
namespace bayan {
/** @brief Namespace of the projet "Core" */
namespace core {

/**
 * @brief The walker class
 */
class walker {
  checker checker_;

public:
  walker() = default;

  void run();
  void print() noexcept;

protected:
  template <class DIR_ITER>
  void find_all(const boost::filesystem::path& path) noexcept;
};

} /* core:: */
} /* bayan:: */

#endif /* WALKER_HPP_ */

ext: hpp


text:
//  Boost Sort library tests for integer_sort and float_sort details.

//  Copyright Steven Ross 2014. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)

//  See http://www.boost.org/libs/sort for library home page.

#include <boost/cstdint.hpp>
#include <boost/sort/spreadsort/detail/spreadsort_common.hpp>
#include <boost/sort/spreadsort/detail/integer_sort.hpp>
#include <boost/sort/spreadsort/detail/float_sort.hpp>
#include <boost/sort/spreadsort/detail/string_sort.hpp>
#include <boost/sort/spreadsort/float_sort.hpp>
// Include unit test framework
#include <boost/test/included/test_exec_monitor.hpp>
#include <boost/test/test_tools.hpp>
#include <vector>

#include <iostream>

using namespace std;
using namespace boost::sort::spreadsort;
using namespace boost::sort::spreadsort::detail;

namespace {

struct int_right_shift {
  int operator()(const int x, const unsigned offset) const {
    return x >> offset;
  }
};

struct float_right_shift {
  int operator()(const float x, const unsigned offset) const {
    return float_mem_cast<float, int>(x) >> offset;
  }
};

const int max_int_bits = sizeof(boost::uintmax_t) * 8;
const int max_size_bits = sizeof(size_t) * 8;
const boost::uintmax_t one = 1;

// spreadsort won't recurse for inputs smaller than min_count.
const int int_min_log_count =
  (std::min)((int)int_log_finishing_count,
             (int)int_log_mean_bin_size + int_log_min_split_count);
const int float_min_log_count =
  (std::min)((int)float_log_finishing_count,
             (int)float_log_mean_bin_size + float_log_min_split_count);
const unsigned absolute_min_count = (std::min)(1 << int_min_log_count,
                                               1 << float_min_log_count);

// Verify that roughlog2 is floor(log base 2) + 1.
void roughlog2_test()
{
  for (boost::uintmax_t i = 0; i < max_int_bits; ++i) {
    BOOST_CHECK(detail::rough_log_2_size(one << i) == i + 1);
    BOOST_CHECK(detail::rough_log_2_size((one << i) - 1) == i);
  }
}

// Test the worst-case performance handling, and assure that is using the
// correct formula for the worst-case number of radix iterations.
template<unsigned log_mean_bin_size, unsigned log_min_split_count,
         unsigned log_finishing_count>
void get_min_count_test()
{
  const unsigned min_log_size = log_mean_bin_size + log_min_split_count;
  size_t prev_min_count = absolute_min_count;
  for (int log_range = 0; log_range <= max_int_bits; ++log_range) {
    size_t min_count = get_min_count<log_mean_bin_size, log_min_split_count,
                                     log_finishing_count>(log_range);
    BOOST_CHECK(min_count >= prev_min_count);
    prev_min_count = min_count;
    // When the range is really small, the radix sort will complete in one
    // iteration and worst-case handling doesn't apply.  The code below
    // guarantees the worst-case number of radix sorting iteration.
    if (log_range > min_log_size) {
      BOOST_CHECK(min_count >= (1 << min_log_size));
      int iterations = rough_log_2_size(min_count) - min_log_size;
      BOOST_CHECK(iterations >= 1);
      int base_iterations = max_splits - log_min_split_count;
      int covered_log_range = 0;
      if (iterations > base_iterations) {
        covered_log_range += max_splits * (iterations - base_iterations);
      } else {
        base_iterations = iterations;
      }
      // sum of n to n + x = ((x + 1) * (n + (n + x)))/2 + log_mean_bin_size
      covered_log_range +=
        (base_iterations * (log_min_split_count * 2 + base_iterations - 1))/2 +
        log_mean_bin_size;
      BOOST_CHECK(covered_log_range >= log_range);
      BOOST_CHECK(covered_log_range - max_splits < log_range);
    }
  }
}

// Test the decision of how many pieces to split up the radix sort into
// (roughly 2^(log_range - log_divisor)) to make sure the results are logical.
void get_log_divisor_test()
{
  for (int log_range = 0; log_range <= max_int_bits; ++log_range) {
    int prev_log_divisor = max_int_bits +
      (std::max)((int)int_log_mean_bin_size, (int)float_log_mean_bin_size);
    for (int log_count = 0; log_count < max_size_bits; ++log_count) {
      size_t count = (one << log_count) - 1;
      BOOST_CHECK(rough_log_2_size(count) == (unsigned)log_count);
      int log_divisor =
        get_log_divisor<int_log_mean_bin_size>(count, log_range);
      // Only process counts >= int_log_finishing_count in this function.
      if (count >= absolute_min_count)
        BOOST_CHECK(log_divisor <= log_range);
      // More pieces should be used the larger count is.
      BOOST_CHECK(log_divisor <= prev_log_divisor);
      prev_log_divisor = log_divisor;
      BOOST_CHECK(log_divisor >= 0);
      if (log_range > log_count) {
        BOOST_CHECK(log_range - log_divisor <= max_splits);
      } else if (log_range <= max_finishing_splits) {
        BOOST_CHECK(log_divisor == 0);
      }
    }
  }
}

// Verify that is_sorted_or_find_extremes returns true if the data is sorted,
// and otherwise returns the actual min and max.
void is_sorted_or_find_extremes_test()
{
  vector<int> input;
  input.push_back(3);
  input.push_back(5);
  input.push_back(1);
  // Test a sorted input.
  vector<int> sorted_input(input);
  std::sort(sorted_input.begin(), sorted_input.end());
  vector<int>::iterator max, min;
  BOOST_CHECK(detail::is_sorted_or_find_extremes(sorted_input.begin(),
                                                 sorted_input.end(), max, min));
  // Test an unsorted input.
  BOOST_CHECK(!detail::is_sorted_or_find_extremes(input.begin(), input.end(),
                                                  max, min));
  BOOST_CHECK(*min == 1);
  BOOST_CHECK(*max == 5);
  // Test the comparison function version.
  BOOST_CHECK(detail::is_sorted_or_find_extremes(sorted_input.begin(),
                                                 sorted_input.end(), max, min,
                                                 std::less<int>()));
  BOOST_CHECK(!detail::is_sorted_or_find_extremes(sorted_input.begin(),
                                                  sorted_input.end(),
                                                  max, min,
                                                  std::greater<int>()));
  BOOST_CHECK(*min == 5);
  BOOST_CHECK(*max == 1);

  // Test with floats
  vector<float> float_input;
  float_input.push_back(.3f);
  float_input.push_back(4.0f);
  float_input.push_back(.1f);
  vector<float> sorted_float_input(float_input);
  std::sort(sorted_float_input.begin(), sorted_float_input.end());
  // Test cast_float_iter
  int cast_min = detail::cast_float_iter<int, vector<float>::iterator>(
                     sorted_float_input.begin());
  int cast_max = detail::cast_float_iter<int, vector<float>::iterator>(
                     sorted_float_input.end() - 1);
  BOOST_CHECK(cast_min == float_right_shift()(.1f, 0));
  BOOST_CHECK(cast_max == float_right_shift()(4.0f, 0));
  // Test a sorted input
  int div_max, div_min;
  BOOST_CHECK(detail::is_sorted_or_find_extremes(sorted_float_input.begin(),
                                                 sorted_float_input.end(),
                                                 div_max, div_min));
  // Test an unsorted input.
  BOOST_CHECK(!detail::is_sorted_or_find_extremes(float_input.begin(),
                                                  float_input.end(),
                                                  div_max, div_min));
  BOOST_CHECK(div_min == cast_min);
  BOOST_CHECK(div_max == cast_max);

  // Test with a right_shift functor.
  BOOST_CHECK(detail::is_sorted_or_find_extremes(sorted_float_input.begin(),
                                                 sorted_float_input.end(),
                                                 div_max, div_min,
                                                 float_right_shift()));
  // Test an unsorted input.
  BOOST_CHECK(!detail::is_sorted_or_find_extremes(float_input.begin(),
                                                  float_input.end(), div_max,
                                                  div_min,
                                                  float_right_shift()));
  BOOST_CHECK(div_min == float_right_shift()(.1f, 0));
  BOOST_CHECK(div_max == float_right_shift()(4.0f, 0));
}

// Make sure bins are created correctly.
void size_bins_test() {
  size_t bin_sizes[1 << detail::max_finishing_splits];
  bin_sizes[0] = 1;
  bin_sizes[2] = 7;
  const int old_bin_value = 7;
  std::vector<int> old_bins;
  old_bins.push_back(old_bin_value);
  std::vector<vector<int>::iterator> bin_cache;
  bin_cache.push_back(old_bins.begin());
  unsigned cache_offset = 1;
  unsigned cache_end;
  const unsigned bin_count = 2;
  std::vector<int>::iterator *new_cache_start =
    size_bins(bin_sizes, bin_cache, cache_offset, cache_end, bin_count);
  BOOST_CHECK((new_cache_start - &bin_cache[0]) == cache_offset);
  BOOST_CHECK(bin_sizes[0] == 0);
  BOOST_CHECK(bin_sizes[1] == 0);
  BOOST_CHECK(bin_sizes[2] == 7);  // shouldn't modify past bin_count
  BOOST_CHECK(cache_end == 3);
  BOOST_CHECK(bin_cache.size() == cache_end);
  BOOST_CHECK(old_bins[0] == old_bin_value);
}

// Test the specialized 3-way swap loops.
void swap_loop_test() {
  size_t bin_sizes[1 << detail::max_finishing_splits];
  bin_sizes[0] = bin_sizes[1] = 2;
  bin_sizes[2] = 1;

  // test integer swap loop
  vector<int> ints;
  const int int_div_min = 3;
  const int int_log_divisor = 1;
  const unsigned int_offset = int_div_min << int_log_divisor;
  ints.push_back(2 + int_offset);
  ints.push_back(1 + int_offset); // stays in place
  ints.push_back(4 + int_offset);
  ints.push_back(3 + int_offset);
  ints.push_back(0 + int_offset);
  vector<vector<int>::iterator> int_bin_vector;
  int_bin_vector.push_back(ints.begin());
  int_bin_vector.push_back(int_bin_vector[0] + bin_sizes[0]);
  int_bin_vector.push_back(int_bin_vector[1] + bin_sizes[1]);
  vector<int>::iterator next_int_bin_start = int_bin_vector[0];
  vector<int>::iterator *int_bins = &int_bin_vector[0];
  int_right_shift integer_right_shift;
  swap_loop(int_bins, next_int_bin_start, 0, integer_right_shift, bin_sizes,
            int_log_divisor, int_div_min);
  for (unsigned i = 0; i < ints.size(); ++i) {
    BOOST_CHECK(ints[i] == int(int_offset + i));
  }
  BOOST_CHECK(next_int_bin_start == ints.begin() + bin_sizes[0]);

  // test float swap loop
  vector<float> floats;
  const int float_four_as_int = float_mem_cast<float, int>(4.0f);
  const int float_log_divisor =
    rough_log_2_size(float_mem_cast<float, int>(5.0f) - float_four_as_int);
  const int float_div_min = float_four_as_int >> float_log_divisor;
  floats.push_back(6.0f);
  floats.push_back(5.0f); // stays in place
  floats.push_back(8.0f);
  floats.push_back(7.0f);
  floats.push_back(4.0f);
  vector<vector<float>::iterator> float_bin_vector;
  float_bin_vector.push_back(floats.begin());
  float_bin_vector.push_back(float_bin_vector[0] + bin_sizes[0]);
  float_bin_vector.push_back(float_bin_vector[1] + bin_sizes[1]);
  vector<float>::iterator next_float_bin_start = float_bin_vector[0];
  vector<float>::iterator *float_bins = &float_bin_vector[0];
  float_swap_loop(float_bins, next_float_bin_start, 0, bin_sizes,
                  float_log_divisor, float_div_min);
  for (unsigned i = 0; i < floats.size(); ++i) {
    BOOST_CHECK(floats[i] == 4.0f + i);
  }
  BOOST_CHECK(next_float_bin_start == floats.begin() + bin_sizes[0]);
}

} // end anonymous namespace

// test main
int test_main( int, char*[] )
{
  roughlog2_test();
  get_min_count_test<int_log_mean_bin_size, int_log_min_split_count,
                    int_log_finishing_count>();
  get_min_count_test<float_log_mean_bin_size, float_log_min_split_count,
                    float_log_finishing_count>();
  get_log_divisor_test();
  is_sorted_or_find_extremes_test();
  size_bins_test();
  swap_loop_test();
  return 0;
}


text: #include <boost/multi_index/global_fun.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2011, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Ioan Sucan */

#include "ompl/base/PlannerTerminationCondition.h"
#include "ompl/util/Time.h"
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/lambda/bind.hpp>
#include <utility>

namespace ompl
{
    namespace base
    {

        /// @cond IGNORE
        class PlannerTerminationCondition::PlannerTerminationConditionImpl
        {
        public:
            PlannerTerminationConditionImpl(const PlannerTerminationConditionFn &fn, double period) :
            fn_(fn),
            period_(period),
            terminate_(false),
            thread_(NULL),
            evalValue_(false),
            signalThreadStop_(false)
            {
                if (period_ > 0.0)
                    startEvalThread();
            }

            ~PlannerTerminationConditionImpl()
            {
                stopEvalThread();
            }

            bool eval() const
            {
                if (terminate_)
                    return true;
                if (period_ > 0.0)
                    return evalValue_;
                return fn_();
            }

            void terminate() const
            {
                // it is ok to have unprotected write here
                terminate_ = true;
            }

        private:

            /** \brief Start the thread evaluating termination conditions if not already started */
            void startEvalThread()
            {
                if (!thread_)
                {
                    signalThreadStop_ = false;
                    evalValue_ = false;
                    thread_ = new boost::thread(boost::bind(&PlannerTerminationConditionImpl::periodicEval, this));
                }
            }

            /** \brief Stop the thread evaluating termination conditions if not already stopped */
            void stopEvalThread()
            {
                signalThreadStop_ = true;
                if (thread_)
                {
                    thread_->join();
                    delete thread_;
                    thread_ = NULL;
                }
            }

            /** \brief Worker function that runs in a separate thread (calls computeEval())*/
            void periodicEval()
            {
                // we want to check for termination at least once every ms;
                // even though we may evaluate the condition itself more rarely

                unsigned int count = 1;
                time::duration s = time::seconds(period_);
                if (period_ > 0.001)
                {
                    count = 0.5 + period_ / 0.001;
                    s = time::seconds(period_ / (double) count);
                }

                while (!terminate_ && !signalThreadStop_)
                {
                    evalValue_ = fn_();
                    for (unsigned int i = 0 ; i < count ; ++i)
                    {
                        if (terminate_ || signalThreadStop_)
                            break;
                        boost::this_thread::sleep(s);
                    }
                }
            }

            /** \brief Function pointer to the piece of code that decides whether a termination condition has been met */
            PlannerTerminationConditionFn fn_;

            /** \brief Interval of time (seconds) to wait between calls to computeEval() */
            double                        period_;

            /** \brief Flag indicating whether the user has externally requested that the condition for termination should become true */
            mutable bool                  terminate_;

            /** \brief Thread for periodicEval() */
            boost::thread                *thread_;

            /** \brief Cached value returned by fn_() */
            bool                          evalValue_;

            /** \brief Flag used to signal the condition evaluation thread to stop. */
            bool                          signalThreadStop_;
        };

        /// @endcond
    }
}

ompl::base::PlannerTerminationCondition::PlannerTerminationCondition(const PlannerTerminationConditionFn &fn) :
impl_(new PlannerTerminationConditionImpl(fn, -1.0))
{
}

ompl::base::PlannerTerminationCondition::PlannerTerminationCondition(const PlannerTerminationConditionFn &fn, double period) :
impl_(new PlannerTerminationConditionImpl(fn, period))
{
}

void ompl::base::PlannerTerminationCondition::terminate() const
{
    impl_->terminate();
}

bool ompl::base::PlannerTerminationCondition::eval() const
{
    return impl_->eval();
}

ompl::base::PlannerTerminationCondition ompl::base::plannerNonTerminatingCondition()
{
    return PlannerTerminationCondition(boost::lambda::constant(false));
}

ompl::base::PlannerTerminationCondition ompl::base::plannerAlwaysTerminatingCondition()
{
    return PlannerTerminationCondition(boost::lambda::constant(true));
}

/// @cond IGNORE
namespace ompl
{
    namespace base
    {
        static bool plannerOrTerminationConditionAux(const PlannerTerminationCondition &c1, const PlannerTerminationCondition &c2)
        {
            return c1() || c2();
        }

        static bool plannerAndTerminationConditionAux(const PlannerTerminationCondition &c1, const PlannerTerminationCondition &c2)
        {
            return c1() && c2();
        }

        // return true if a certain point in time has passed
        static bool timePassed(const time::point &endTime)
        {
            return time::now() > endTime;
        }
    }
}
/// @endcond

ompl::base::PlannerTerminationCondition ompl::base::plannerOrTerminationCondition(const PlannerTerminationCondition &c1, const PlannerTerminationCondition &c2)
{
    return PlannerTerminationCondition(boost::bind(&plannerOrTerminationConditionAux, c1, c2));
}

ompl::base::PlannerTerminationCondition ompl::base::plannerAndTerminationCondition(const PlannerTerminationCondition &c1, const PlannerTerminationCondition &c2)
{
    return PlannerTerminationCondition(boost::bind(&plannerAndTerminationConditionAux, c1, c2));
}

ompl::base::PlannerTerminationCondition ompl::base::timedPlannerTerminationCondition(double duration)
{
    return timedPlannerTerminationCondition(time::seconds(duration));
}

ompl::base::PlannerTerminationCondition ompl::base::timedPlannerTerminationCondition(time::duration duration)
{
    return PlannerTerminationCondition(boost::bind(&timePassed, time::now() + duration));
}

ompl::base::PlannerTerminationCondition ompl::base::timedPlannerTerminationCondition(double duration, double interval)
{
    if (interval > duration)
        interval = duration;
    return PlannerTerminationCondition(boost::bind(&timePassed, time::now() + time::seconds(duration)), interval);
}

ompl::base::PlannerTerminationCondition ompl::base::exactSolnPlannerTerminationCondition(ompl::base::ProblemDefinitionPtr pdef)
{
    return PlannerTerminationCondition(boost::bind(&ProblemDefinition::hasExactSolution, pdef));
}

namespace ompl
{
    namespace base
    {
        IterationTerminationCondition::IterationTerminationCondition(unsigned int numIterations)
          : maxCalls_(numIterations),
            timesCalled_(0u)
        {
        }

        bool IterationTerminationCondition::eval()
        {
            ++timesCalled_;

            return (timesCalled_ > maxCalls_);
        }

        void IterationTerminationCondition::reset()
        {
            timesCalled_ = 0u;
        }

        IterationTerminationCondition::operator PlannerTerminationCondition()
        {
            return PlannerTerminationCondition( boost::bind(&IterationTerminationCondition::eval, this) );
        }
    }
}

max_stars_repo_name: ivaROS/ivaOmplCore

max_issues_repo_name: ivaROS/ivaOmplCore

max_forks_repo_name: ivaROS/ivaOmplCore


text:
/*
 *  Copyright (c) 2014-present, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */

#include <sstream>
#include <vector>

#include <boost/property_tree/ptree.hpp>

#include <osquery/config.h>
#include <osquery/dispatcher.h>
#include <osquery/enroll.h>
#include <osquery/flags.h>
#include <osquery/registry.h>

#include "osquery/core/conversions.h"
#include "osquery/core/json.h"
#include "osquery/remote/requests.h"
#include "osquery/remote/serializers/json.h"
#include "osquery/remote/utility.h"

namespace pt = boost::property_tree;

namespace osquery {

CLI_FLAG(uint64,
         config_tls_max_attempts,
         3,
         "Number of attempts to retry a TLS config/enroll request");

/// Config retrieval TLS endpoint (path) using TLS hostname.
CLI_FLAG(string,
         config_tls_endpoint,
         "",
         "TLS/HTTPS endpoint for config retrieval");

/// Config polling/updating, only applies to TLS configurations.
CLI_FLAG(uint64,
         config_tls_refresh,
         0,
         "Optional interval in seconds to re-read configuration");

DECLARE_bool(tls_secret_always);
DECLARE_string(tls_enroll_override);
DECLARE_bool(tls_node_api);

class TLSConfigPlugin;

class TLSConfigPlugin : public ConfigPlugin,
                        std::enable_shared_from_this<TLSConfigPlugin> {
 public:
  Status setUp() override;
  Status genConfig(std::map<std::string, std::string>& config) override;

 protected:
  /// Calculate the URL once and cache the result.
  std::string uri_;
};

class TLSConfigRefreshRunner : public InternalRunnable {
 public:
  /// A simple wait/interruptible lock.
  void start();
};

REGISTER(TLSConfigPlugin, "config", "tls");

Status TLSConfigPlugin::setUp() {
  uri_ = TLSRequestHelper::makeURI(FLAGS_config_tls_endpoint);

  // If the initial configuration includes a non-0 refresh, start an additional
  // service that sleeps and periodically regenerates the configuration.
  if (FLAGS_config_tls_refresh >= 1) {
    Dispatcher::addService(std::make_shared<TLSConfigRefreshRunner>());
  }

  return Status(0, "OK");
}

Status TLSConfigPlugin::genConfig(std::map<std::string, std::string>& config) {
  std::string json;

  auto s = TLSRequestHelper::go<JSONSerializer>(
      uri_, json, FLAGS_config_tls_max_attempts);
  if (!s.ok()) {
    return s;
  }

  if (FLAGS_tls_node_api) {
    // The node API embeds configuration data (JSON escaped).
    pt::ptree tree;
    try {
      std::stringstream input;
      input << json;
      pt::read_json(input, tree);
    } catch (const pt::json_parser::json_parser_error& /* e */) {
      VLOG(1) << "Could not parse JSON from TLS node API";
    }

    // Re-encode the config key into JSON.
    config["tls_plugin"] = unescapeUnicode(tree.get("config", ""));
  } else {
    config["tls_plugin"] = json;
  }
  return s;
}

void TLSConfigRefreshRunner::start() {
  while (!interrupted()) {
    // Cool off and time wait the configured period.
    // Apply this interruption initially as at t=0 the config was read.
    pauseMilli(FLAGS_config_tls_refresh * 1000);
    // Since the pause occurs before the logic, we need to check for an
    // interruption request.
    if (interrupted()) {
      return;
    }

    // Access the configuration.
    auto plugin = Registry::get("config", "tls");
    if (plugin != nullptr) {
      auto config_plugin = std::dynamic_pointer_cast<ConfigPlugin>(plugin);

      // The config instance knows the TLS plugin is selected.
      std::map<std::string, std::string> config;
      if (config_plugin->genConfig(config)) {
        Config::getInstance().update(config);
      }
    }
  }
}
}


text:
/*
 * Author: Konstantin Schauwecker
 * Year:   2012
 */

// This is a minimalistic example on how to use the extended
// FAST feature detector and the sparse stereo matcher.

#include <opencv2/opencv.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <vector>
#include <iostream>
#include <sparsestereo/exception.h>
#include <sparsestereo/extendedfast.h>
#include <sparsestereo/stereorectification.h>
#include <sparsestereo/sparsestereo-inl.h>
#include <sparsestereo/census-inl.h>
#include <sparsestereo/imageconversion.h>
#include <sparsestereo/censuswindow.h>

using namespace std;
using namespace cv;
using namespace sparsestereo;
using namespace boost;
using namespace boost::posix_time;

int main(int argc, char** argv) {
	try {
		// Stereo matching parameters
		double uniqueness = 0.7;
		int maxDisp = 70;
		int leftRightStep = 2;

		// Feature detection parameters
		double adaptivity = 1.0;
		int minThreshold = 10;

		// Parse arguments
		if(argc != 3 && argc != 4) {
			cout << "Usage: " << argv[0] << " LEFT-IMG RIGHT-IMG [CALIBRARION-FILE]" << endl;
			return 1;
		}
		char* leftFile = argv[1];
		char* rightFile = argv[2];
		char* calibFile = argc == 4 ? argv[3] : NULL;

		// Read input images
		cv::Mat_<unsigned char> leftImg, rightImg;
		leftImg = imread(leftFile, CV_LOAD_IMAGE_GRAYSCALE);
		rightImg = imread(rightFile, CV_LOAD_IMAGE_GRAYSCALE);

		if(leftImg.data == NULL || rightImg.data == NULL)
			throw sparsestereo::Exception("Unable to open input images!");

		// Load rectification data
		StereoRectification* rectification = NULL;
		if(calibFile != NULL)
			rectification = new StereoRectification(CalibrationResult(calibFile));

		// The stereo matcher. SSE Optimized implementation is only available for a 5x5 window
		SparseStereo<CensusWindow<5>, short> stereo(maxDisp, 1, uniqueness,
			rectification, false, false, leftRightStep);

		// Feature detectors for left and right image
		FeatureDetector* leftFeatureDetector = new ExtendedFAST(true, minThreshold, adaptivity, false, 2);
		FeatureDetector* rightFeatureDetector = new ExtendedFAST(false, minThreshold, adaptivity, false, 2);

		ptime lastTime = microsec_clock::local_time();
		vector<SparseMatch> correspondences;

		// Objects for storing final and intermediate results
		cv::Mat_<char> charLeft(leftImg.rows, leftImg.cols),
			charRight(rightImg.rows, rightImg.cols);
		Mat_<unsigned int> censusLeft(leftImg.rows, leftImg.cols),
			censusRight(rightImg.rows, rightImg.cols);
		vector<KeyPoint> keypointsLeft, keypointsRight;

		// For performance evaluation we do the stereo matching 100 times
		for(int i=0; i< 100; i++) {
			// Featuredetection. This part can be parallelized with OMP
			#pragma omp parallel sections default(shared) num_threads(2)
			{
				#pragma omp section
				{
					ImageConversion::unsignedToSigned(leftImg, &charLeft);
					Census::transform5x5(charLeft, &censusLeft);
					keypointsLeft.clear();
					leftFeatureDetector->detect(leftImg, keypointsLeft);
				}
				#pragma omp section
				{
					ImageConversion::unsignedToSigned(rightImg, &charRight);
					Census::transform5x5(charRight, &censusRight);
					keypointsRight.clear();
					rightFeatureDetector->detect(rightImg, keypointsRight);
				}
			}

			// Stereo matching. Not parallelized (overhead too large)
			correspondences.clear();
			stereo.match(censusLeft, censusRight, keypointsLeft, keypointsRight, &correspondences);
		}

		// Print statistics
		time_duration elapsed = (microsec_clock::local_time() - lastTime);
		cout << "Time for 100x stereo matching: " << elapsed.total_microseconds()/1.0e6 << "s" << endl
			<< "Features detected in left image: " << keypointsLeft.size() << endl
			<< "Features detected in right image: " << keypointsRight.size() << endl
			<< "Percentage of matched features: " << (100.0 * correspondences.size() / keypointsLeft.size()) << "%" << endl;

		// Highlight matches as colored boxes
		Mat_<Vec3b> screen(leftImg.rows, leftImg.cols);
		cvtColor(leftImg, screen, CV_GRAY2BGR);

		for(int i=0; i<(int)correspondences.size(); i++) {
			double scaledDisp = (double)correspondences[i].disparity() / maxDisp;
			Vec3b color;
			if(scaledDisp > 0.5)
				color = Vec3b(0, (1 - scaledDisp)*512, 255);
			else color = Vec3b(0, 255, scaledDisp*512);

			rectangle(screen, correspondences[i].imgLeft->pt - Point2f(2,2),
				correspondences[i].imgLeft->pt + Point2f(2, 2),
				(Scalar) color, CV_FILLED);
		}

		// Display image and wait
		namedWindow("Stereo");
		imshow("Stereo", screen);
		waitKey();

		// Clean up
		delete leftFeatureDetector;
		delete rightFeatureDetector;
		if(rectification != NULL)
			delete rectification;

		return 0;
	}
	catch (const std::exception& e) {
		cerr << "Fatal exception: " << e.what();
		return 1;
	}
}

max_stars_repo_name: jaxnb/NaviGator

max_issues_repo_name: jaxnb/NaviGator

max_forks_repo_name: ericgorday/NaviGator


text:
#ifndef __AST_BITVEC_HPP_DEFINED__
#define __AST_BITVEC_HPP_DEFINED__

#include <boost/lexical_cast.hpp>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>
#include <string>
#include <vector>

#include <assert.h>
#include <ilasynth/ast/node.hpp>
#include <ilasynth/type.hpp>
#include <z3++.h>

#include <ilasynth/ast.hpp>

namespace ilasynth {
class Abstraction;
class FuncReduction;

// ---------------------------------------------------------------------- //
// Bitvector expressions are derived from this class.
class BitvectorExpr : public Node {
public:
  // constructor.
  BitvectorExpr(int width);
  // constructor for ChoiceExpr.
  BitvectorExpr(NodeType t);
  // destructor.
  virtual ~BitvectorExpr();
};

// ---------------------------------------------------------------------- //
// Bitvector variables.
class BitvectorVar : public BitvectorExpr {
public:
  // constructor.
  BitvectorVar(const std::string& n, int width);
  // destructor.
  virtual ~BitvectorVar();
  // clone.
  virtual Node* clone() const;
  // equality method.
  virtual bool equal(const Node* that) const;
  // stream output.
  virtual std::ostream& write(std::ostream& out) const;
};

// ---------------------------------------------------------------------- //
// Bitvector constants.
class BitvectorConst : public BitvectorExpr {
protected:
  mp_int_t value;

public:
  // constructor with longs.
  BitvectorConst(const mp_int_t& v, int width);
  // constructor with ints.
  BitvectorConst(unsigned int v, int width);
  // copy constructor.
  BitvectorConst(const BitvectorConst& other);
  // destructor.
  virtual ~BitvectorConst();
  // clone
  virtual Node* clone() const;
  // equality method.
  virtual bool equal(const Node* that) const;
  // get value.
  const mp_int_t& val() const { return value; }
  // return value.
  virtual py::object getValue() const;
  // stream output.
  virtual std::ostream& write(std::ostream& out) const;
  // get the value as a string.
  std::string vstr() const { return boost::lexical_cast<std::string>(value); }
};

// ---------------------------------------------------------------------- //
// Bitvector operators.
class BitvectorOp : public BitvectorExpr {
public:
  // Number of operands.
  enum Arity { UNARY, BINARY, TERNARY, NARY } arity;

  // What is the operation?
  enum Op {
    // invalid
    INVALID,
    // unary
    NEGATE,
    COMPLEMENT,
    LROTATE,
    RROTATE,
    Z_EXT,
    S_EXT,
    EXTRACT,
    // binary.
    ADD,
    SUB,
    AND,
    OR,
    XOR,
    XNOR,
    NAND,
    NOR,
    SDIV,
    UDIV,
    SREM,
    UREM,
    SMOD,
    SHL,
    LSHR,
    ASHR,
    MUL,
    CONCAT,
    GET_BIT,
    READMEM,
    READMEMBLOCK,
    // ternary
    IF,
    APPLY_FUNC
  } op;

  static const std::string operatorNames[];

private:
  // the operands themselves.
  nptr_vec_t args;
  std::vector<int> params;

  // Don't forget to update these helper functions below.
  static bool isUnary(Op op) { return op >= NEGATE && op <= EXTRACT; }
  static bool isBinary(Op op) { return op >= ADD && op <= READMEMBLOCK; }
  static bool isTernary(Op op) { return op >= IF && op <= IF; }
  static bool isNary(Op op) { return op >= APPLY_FUNC && op <= APPLY_FUNC; }
  // helper functions to determine result and argument types.
  static int getUnaryResultWidth(Op op, const nptr_t& n);
  static int getBinaryResultWidth(Op op, const nptr_t& n1, const nptr_t& n2);
  static int getBinaryResultWidth(Op op, const nptr_t& n1, const nptr_t& n2,
                                  int param);
  static int getBinaryResultWidth(Op op, const nptr_t& n1, int param);
  static int getNaryResultWidth(Op op, nptr_vec_t& args);
  static int getNaryResultWidth(Op op, nptr_vec_t& args,
                                std::vector<int>& params);

  static bool checkUnaryOpWidth(Op op, const nptr_t& n, int width);
  static int checkBinaryOpWidth(Op op, const nptr_t& n1, const nptr_t& n2,
                                int width);
  static int checkBinaryOpWidth(Op op, const nptr_t& n1, const nptr_t& n2,
                                int param, int width);
  static int checkBinaryOpWidth(Op op, const nptr_t& n1, int param, int width);
  static int checkNaryOpWidth(Op op, nptr_vec_t& args, int width);
  static int checkNaryOpWidth(Op op, nptr_vec_t& args, std::vector<int>& params,
                              int width);

public:
  // constructors.
  // Unary op
  BitvectorOp(Op op, const nptr_t& n1);
  BitvectorOp(Op op, const nptr_t& n1, int param);
  BitvectorOp(Op op, const nptr_t& n1, int p1, int p2);
  // Binary op
  BitvectorOp(Op op, const nptr_t& n1, const nptr_t& n2);
  // Binary op with params (read-block)
  BitvectorOp(Op op, const nptr_t& n1, const nptr_t& n2, int blocks,
              endianness_t e);
  // Ternary op
  BitvectorOp(Op op, nptr_vec_t& args_);
  // copy-constructor with a fresh set of args.
  BitvectorOp(const BitvectorOp* other, nptr_vec_t& args_);
  // destructors.
  virtual ~BitvectorOp();

  // clone.
  virtual Node* clone() const;

  // equality method.
  virtual bool equal(const Node* that) const;

  // stream output.
  virtual std::ostream& write(std::ostream& out) const;

  // number of operands.
  virtual unsigned nArgs() const;

  // operand i.
  virtual nptr_t arg(unsigned i) const;

  Op getOp() const { return op; }

  // number of params
  unsigned nParams() const;

  // the ith param.
  int param(unsigned i) const;

  friend class FuncReduction;
};
} // namespace ilasynth
#endif

max_stars_repo_name: Bo-Yuan-Huang/ItSy


text:
/*
Copyright 2017 Glen Joseph Fernandes
(glenjofe@gmail.com)

Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \
    !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
#include <boost/align/is_aligned.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>

class type {
public:
    static unsigned instances;

    type()
        : value_(0.0) {
        ++instances;
    }

    ~type() {
        --instances;
    }

    void set(long double value) {
        value_ = value;
    }

    long double get() const {
        return value_;
    }

private:
    type(const type&);
    type& operator=(const type&);

    long double value_;
};

unsigned type::instances = 0;

int main()
{
    {
        boost::local_shared_ptr<int[]> result =
            boost::make_local_shared_noinit<int[]>(3);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<int[3]> result =
            boost::make_local_shared_noinit<int[3]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<int[][2]> result =
            boost::make_local_shared_noinit<int[][2]>(2);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<int[2][2]> result =
            boost::make_local_shared_noinit<int[2][2]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<const int[]> result =
            boost::make_local_shared_noinit<const int[]>(3);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<const int[3]> result =
            boost::make_local_shared_noinit<const int[3]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<const int[][2]> result =
            boost::make_local_shared_noinit<const int[][2]>(2);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<const int[2][2]> result =
            boost::make_local_shared_noinit<const int[2][2]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<int>::value));
    }
    {
        boost::local_shared_ptr<type[]> result =
            boost::make_local_shared_noinit<type[]>(3);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 3);
        boost::weak_ptr<type[]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<type[3]> result =
            boost::make_local_shared_noinit<type[3]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 3);
        boost::weak_ptr<type[3]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<type[][2]> result =
            boost::make_local_shared_noinit<type[][2]>(2);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 4);
        boost::weak_ptr<type[][2]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<type[2][2]> result =
            boost::make_local_shared_noinit<type[2][2]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 4);
        boost::weak_ptr<type[2][2]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<const type[]> result =
            boost::make_local_shared_noinit<const type[]>(3);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 3);
        boost::weak_ptr<const type[]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<const type[3]> result =
            boost::make_local_shared_noinit<const type[3]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 3);
        boost::weak_ptr<const type[3]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<const type[][2]> result =
            boost::make_local_shared_noinit<const type[][2]>(2);
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 4);
        boost::weak_ptr<const type[][2]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    {
        boost::local_shared_ptr<const type[2][2]> result =
            boost::make_local_shared_noinit<const type[2][2]>();
        BOOST_TEST(result.get() != 0);
        BOOST_TEST(result.local_use_count() == 1);
        BOOST_TEST(boost::alignment::is_aligned(result.get(),
            boost::alignment_of<type>::value));
        BOOST_TEST(type::instances == 4);
        boost::weak_ptr<const type[2][2]> other = result;
        result.reset();
        BOOST_TEST(type::instances == 0);
    }
    return boost::report_errors();
}
#else
int main()
{
    return 0;
}
#endif


text:
#include <cctbx/boost_python/flex_fwd.h>
#include <boost/python/enum.hpp>
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/list.hpp>
#include <scitbx/array_family/flex_types.h>
#include <scitbx/array_family/shared.h>
#include <scitbx/math/mean_and_variance.h>
#include <scitbx/array_family/boost_python/shared_wrapper.h>
#include <cctbx/examples/merging/xscale_prototype_core.h>
#include <cctbx/examples/merging/postrefine_base.h>
#include <Eigen/Sparse>
#include <boost/python/return_internal_reference.hpp>
#include <boost/math/tools/precision.hpp>

using namespace boost::python;
namespace cctbx{ namespace merging {

double d_product (double const&A, double const&B, double const&dA, double const&dB){
  return dA * B + A * dB;
}

static const double logmax = boost::math::tools::log_max_value<double>()/2.;
static const double logmin = boost::math::tools::log_min_value<double>()/2.;

static boost::python::tuple
task6c_f_g(intensity_data::vecd const& x,
           const int& N_I, const int& N_G,
           const intensity_data & FSIM,
           bool compute_curv) {
  double f = 0.;
  const double* Iptr = x.begin(); // indices into the array of parameters
  const double* Gptr = Iptr + N_I;
  const double* Bptr = Gptr + N_G;

  intensity_data::vecd g(x.size(),0);
  intensity_data::vecd c(x.size(),0);
  double* Iptrg = g.begin(); // indices into the array of derivatives
  double* Gptrg = Iptrg + N_I;
  double* Bptrg = Gptrg + N_G;
  double* Iptrc = c.begin(); // indices into the array of curvatures
  double* Gptrc = Iptrc + N_I;
  double* Bptrc = Gptrc + N_G;

  for (size_t i = 0; i<FSIM.raw_obs.size(); ++i){
      double weight = 1./FSIM.exp_var[i];
      double Gitem  = Gptr[ FSIM.frame[i] ];
      double Bargument = -2.* Bptr[ FSIM.frame[i] ] * FSIM.stol_sq[i];

      if (logmax < Bargument){
        throw SCITBX_ERROR("exp argument greater than logmax");
      }
      if (logmin > Bargument){
        throw SCITBX_ERROR("exp argument less than logmin");
      }

      double Bitem  = std::exp(Bargument); // :=exp(beta)
      double Iitem  = Iptr[ FSIM.miller[i] ];

      double residual = - FSIM.raw_obs[i] +
                        Gitem *
                        Bitem *
                        Iitem;

      f += weight * residual * residual;

      Gptrg[ FSIM.frame[i] ] += weight * residual * Bitem * Iitem;
      Iptrg[ FSIM.miller[i] ]+= weight * residual * Bitem * Gitem;

      double d_Bitem_d_B =    Bitem * ( -2. * FSIM.stol_sq[i] );
      double d_residual_d_B = Gitem * Iitem * d_Bitem_d_B;

      Bptrg[ FSIM.frame[i] ] += weight * residual * d_residual_d_B;

      if (compute_curv) {
        Gptrc[ FSIM.frame[i] ] +=  weight * Bitem * Bitem * Iitem * Iitem;
        Iptrc[ FSIM.miller[i] ]+=  weight * Bitem * Bitem * Gitem * Gitem;
        Bptrc[ FSIM.frame[i] ] +=  weight * d_residual_d_B * d_residual_d_B;
      }
  }

  return (boost::python::make_tuple(f/2., g, c));
}

void f_g_error(std::string const& message){
  throw SCITBX_ERROR(message);
}

namespace boost_python { namespace {

  void
  large_scale_merging_init_module() {
    using namespace boost::python;

    def("task6c_f_g", &cctbx::merging::task6c_f_g);
    def("f_g_error", &cctbx::merging::f_g_error);

    typedef return_value_policy<return_by_value> rbv;
    typedef default_call_policies dcp;

    typedef cctbx::merging::intensity_data cmid;
    class_<cmid>("intensity_data", init<>())
      .add_property("frame",
                    make_getter(&cmid::frame, rbv()),
                    make_setter(&cmid::frame, dcp()))
      .add_property("miller",
                    make_getter(&cmid::miller, rbv()),
                    make_setter(&cmid::miller, dcp()))
      .add_property("raw_obs",
                    make_getter(&cmid::raw_obs, rbv()),
                    make_setter(&cmid::raw_obs, dcp()))
      .add_property("exp_var",
                    make_getter(&cmid::exp_var, rbv()),
                    make_setter(&cmid::exp_var, dcp()))
      .add_property("stol_sq",
                    make_getter(&cmid::stol_sq, rbv()),
                    make_setter(&cmid::stol_sq, dcp()))
      .add_property("origHKL",
                    make_getter(&cmid::origHKL, rbv()),
                    make_setter(&cmid::origHKL, dcp()))
      .def("estimate_G", &cmid::estimate_G,(arg("Nframes"),arg("inv_d_sq_max")=0.,arg("inv_d_sq_min")=0.))
      .def("estimate_I", &cmid::estimate_I,(arg("Gframes"),arg("inv_d_sq_max")=0.,arg("inv_d_sq_min")=0.))
      .def("reset_mem", &cmid::reset_mem)
    ;

    enum_<ParameterFlags>("ParameterFlags")
      .value("PartialityDeff", PartialityDeff)
      .value("PartialityEtaDeff", PartialityEtaDeff)
      .value("Bfactor", Bfactor)
      .value("Deff", Deff)
      .value("Eta", Eta)
      .value("Rxy", Rxy)
    ;

    typedef scaling_common_functions scf;
    class_<scf >(
      "scaling_common_functions", no_init)
      .def("set_cpp_data",&scf::set_cpp_data,
        (arg("fsim")))
      .def("set_parameter_flags", &scf::set_parameter_flags)
      .def("set_wavelength", &scf::set_wavelength)
      .def("set_domain_size", &scf::set_domain_size)
      .def("set_Astar_matrix", &scf::set_Astar_matrix)
      .def("get_rh_rs_ratio", &scf::get_rh_rs_ratio)
    ;

    typedef scitbx::example::non_linear_ls_eigen_wrapper nllsew;
    typedef xscale6e wt6e;
    class_<wt6e,
           bases<nllsew, scf  > >(
      "xscale6e", no_init)
      .def(init<int>(arg("n_parameters")))
      .def("access_cpp_build_up_directly_eigen_eqn",&wt6e::access_cpp_build_up_directly_eigen_eqn,
        (arg("objective_only"),arg("current_values")))
      .def("reset_mem", &wt6e::reset_mem)
    ;

    typedef postrefine_base prb;
    class_<prb,
           bases<wt6e  > >(
      "postrefine_base", no_init)
      .def(init<int>(arg("n_parameters")))
      .def("access_cpp_build_up_directly_eigen_eqn",&prb::access_cpp_build_up_directly_eigen_eqn,
        (arg("objective_only"),arg("current_values")))
    ;

  }

}}
}} // namespace xfel::boost_python::<anonymous>

BOOST_PYTHON_MODULE(cctbx_large_scale_merging_ext)
{
  cctbx::merging::boost_python::large_scale_merging_init_module();

}