<commit_before>/*
 * assembler32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

static fstream f;
static string buf;
static set<string> exported;
static map<string, uword_t> symbols;
static map<string, set<uword_t>> references;
static set<uword_t> relatives;
static uword_t mem_size = 0;
static uword_t* mem = new uword_t[MEM_WORDS];
static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  for (char c = f.get(); f.good(); c = f.get()) {
    if (c == '/') { // comment found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
      // ignoring comment
      for (c = f.get(); c != '\r' && c != '\n' && f.good(); c = f.get());
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      currentLine++;
    }
    else if (c == '\r' || c == '\n') { // line break found
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      if (buf.size()) { // token was read
        currentTokenLine = currentLine++;
        return;
      }
      currentLine++;
    }
    else if (c == ' ' || c == '\t') { // white space found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
    }
    else { // concatenating the character read
      buf += c;
    }
  }

  currentTokenLine = currentLine;
}

inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

inline static uword_t parseField() {
  uword_t field = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // hex notation means absolute address
    sscanf(buf.c_str(), "%i", &field);
  }
  else { // symbol means an address that needs to be relocated later
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf.find("+") != buf.npos) {
      string offset = buf.substr(buf.find("+") + 1, buf.size());
      buf = buf.substr(0, buf.find("+"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    if (sym == symbols.end()) { // symbol not found. leave a reference
      references[buf].emplace(mem_size);
    }
    else { // symbol found. the field is the address of the symbol
      field = sym->second;
    }
  }
  return field;
}

int assembler32(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  f.open(argv[1]);

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  f.close();

  // resolve references
  for (auto map_it = references.begin(); map_it != references.end();) {
    // external symbols
    auto sym = symbols.find(map_it->first);
    if (sym == symbols.end()) {
      ++map_it;
      continue;
    }

    // resolve
    for (auto it = map_it->second.begin(); it != map_it->second.end(); ++it) {
      mem[*it] += sym->second;
    }

    references.erase(map_it++);
  }

  f.open(argv[2], fstream::out | fstream::binary);

  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      f.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      f.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      f.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        f.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    f.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    f.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  f.close();

  delete[] mem;

  return 0;
}
<commit_msg>Fixing bug<commit_after>/*
 * assembler32.cpp
 *
 *  Created on: Jul 23, 2014
 *      Author: Pimenta
 */

#include <cstdint>
#include <cstdio>
#include <fstream>
#include <map>
#include <set>
#include <string>
#include <sstream>

using namespace std;

typedef uint32_t uword_t;

#ifndef MEM_WORDS
#define MEM_WORDS 0x2000
#endif

static fstream f;
static string buf;
static set<string> exported;
static map<string, uword_t> symbols;
static map<string, set<uword_t>> references;
static set<uword_t> relatives;
static uword_t mem_size = 0;
static uword_t* mem = new uword_t[MEM_WORDS];
static int currentLine = 1, lastTokenLine = 1, currentTokenLine = 1;

inline static void readToken() {
  buf = "";
  lastTokenLine = currentTokenLine;

  for (char c = f.get(); f.good(); c = f.get()) {
    if (c == '/') { // comment found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
      // ignoring comment
      for (c = f.get(); c != '\r' && c != '\n' && f.good(); c = f.get());
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      currentLine++;
    }
    else if (c == '\r' || c == '\n') { // line break found
      if (c == '\r') { // checking for CR or CRLF line endings
        c = f.get();
        if (f.good() && c != '\n') {
          f.unget();
        }
      }
      if (buf.size()) { // token was read
        currentTokenLine = currentLine++;
        return;
      }
      currentLine++;
    }
    else if (c == ' ' || c == '\t') { // white space found
      if (buf.size()) { // token was read
        currentTokenLine = currentLine;
        return;
      }
    }
    else { // concatenating the character read
      buf += c;
    }
  }

  currentTokenLine = currentLine;
}

inline static uword_t parseData() {
  uword_t data = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // for hex notation
    sscanf(buf.c_str(), "%i", &data);
  }
  else { // for decimal notation
    stringstream ss;
    ss << buf;
    ss >> data;
  }
  return data;
}

inline static uword_t parseField() {
  uword_t field = 0;
  if (buf[0] == '0' && buf[1] == 'x') { // hex notation means absolute address
    sscanf(buf.c_str(), "%i", &field);
  }
  else { // symbol means an address that needs to be relocated later
    relatives.emplace(mem_size);

    // looking for array offset
    if (buf.find("+") != buf.npos) {
      string offset = buf.substr(buf.find("+") + 1, buf.size());
      buf = buf.substr(0, buf.find("+"));
      stringstream ss;
      ss << offset;
      ss >> field;
    }

    auto sym = symbols.find(buf);
    if (sym == symbols.end()) { // symbol not found. leave a reference
      references[buf].emplace(mem_size);
    }
    else { // symbol found. the field is the address of the symbol
      field = sym->second;
    }
  }
  return field;
}

int assembler32(int argc, char* argv[]) {
  if (argc != 3) {
    fprintf(stderr, "Usage mode: subleq-asm <assembly_file> <object_file>\n");
    return 0;
  }

  f.open(argv[1]);

  readToken(); // reading ".export"

  // reading export section
  for (readToken(); buf != ".data"; readToken()) {
    exported.insert(buf);
  }

  // reading data section
  for (readToken(); buf != ".text";) {
    symbols[buf.substr(0, buf.size() - 1)] = mem_size;
    readToken();
    if (buf == ".array") { // uninitialized array
      readToken();
      mem_size += parseData();
      readToken(); // next symbol
    }
    else if (buf == ".iarray") { // initialized array
      for (readToken(); currentTokenLine == lastTokenLine; readToken()) {
        mem[mem_size++] = parseData();
      }
    }
    else if (buf == ".ptr") { // pointer
      readToken();
      mem[mem_size] = parseField();
      mem_size++;
      readToken(); // next symbol
    }
    else { // initialized word
      mem[mem_size++] = parseData();
      readToken(); // next symbol
    }
  }

  // reading text section
  int field = 0;
  for (readToken(); buf.size();) {
    // field 2 omitted
    if (field == 2 && currentTokenLine != lastTokenLine) {
      relatives.emplace(mem_size);
      mem[mem_size] = mem_size + 1;
      mem_size++;
      field = (field + 1)%3;
    }
    // symbol found
    else if (buf[buf.size() - 1] == ':') {
      symbols[buf.substr(0, buf.size() - 1)] = mem_size;
      if (buf == "start:")
        exported.emplace("start");
      readToken();
    }
    // field 0, 1, or field 2 specified
    else {
      mem[mem_size] = parseField();
      mem_size++;
      field = (field + 1)%3;
      readToken();
    }
  }

  f.close();

  // resolve references
  for (auto map_it = references.begin(); map_it != references.end();) {
    // external symbols
    auto sym = symbols.find(map_it->first);
    if (sym == symbols.end()) {
      ++map_it;
      continue;
    }

    // resolve
    for (auto it = map_it->second.begin(); it != map_it->second.end(); ++it) {
      mem[*it] += sym->second;
    }

    references.erase(map_it++);
  }

  f.open(argv[2], fstream::out | fstream::binary);

  {
    uword_t tmp;

    // write number of exported symbols
    tmp = exported.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write exported symbols
    for (auto& exp : exported) {
      // string
      f.write(exp.c_str(), exp.size() + 1);

      // address
      tmp = symbols[exp];
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write number of symbols of pending references
    tmp = references.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write symbols of pending references
    for (auto& sym : references) {
      // string
      f.write(sym.first.c_str(), sym.first.size() + 1);

      // write number of references to current symbol
      tmp = sym.second.size();
      f.write((const char*)&tmp, sizeof(uword_t));

      // write references to current symbol
      for (auto ref : sym.second) {
        tmp = ref;
        f.write((const char*)&tmp, sizeof(uword_t));
      }
    }

    // write number of relative addresses
    tmp = relatives.size();
    f.write((const char*)&tmp, sizeof(uword_t));

    // write relative addresses
    for (auto addr : relatives) {
      tmp = addr;
      f.write((const char*)&tmp, sizeof(uword_t));
    }

    // write assembled code size
    f.write((const char*)&mem_size, sizeof(uword_t));

    // write assembled code
    f.write((const char*)mem, sizeof(uword_t)*mem_size);
  }

  f.close();

  delete[] mem;

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Tentative compile fix.<commit_after><|endoftext|>


<commit_before>/* For copyright information please refer to files in the COPYRIGHT directory
 */
#include "debug.hpp"
#include "locks.hpp"
#include "filesystem.hpp"
#include "utils.hpp"
#include "irods_log.hpp"
#include "initServer.hpp"
#include "irods_server_properties.hpp"

int lockMutex( mutex_type **mutex ) {
    std::string mutex_name;
    irods::error ret = getMutexName( mutex_name );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "lockMutex: call to getMutexName failed" );
        return -1;
    }

    try {
        *mutex = new boost::interprocess::named_mutex( boost::interprocess::open_or_create, mutex_name.c_str() );
    } catch ( const boost::interprocess::interprocess_exception& ) {
        rodsLog( LOG_ERROR, "boost::interprocess::named_mutex threw a boost::interprocess::interprocess_exception." );
        return -1;
    }
    ( *mutex )->lock();
    return 0;
}

void unlockMutex( mutex_type **mutex ) {
    ( *mutex )->unlock();
    delete *mutex;
}

/* This function can be used during initialization to remove a previously held mutex that has not been released.
 * This should only be used when there is no other process using the mutex */
void resetMutex() {
    std::string mutex_name;
    irods::error ret = getMutexName( mutex_name );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "resetMutex: call to getMutexName failed" );
    }

    boost::interprocess::named_mutex::remove( mutex_name.c_str() );
}

irods::error getMutexName( std::string &mutex_name ) {
    std::string mutex_name_salt;
    irods::error ret = irods::server_properties::getInstance().get_property<std::string>( RE_CACHE_SALT_KW, mutex_name_salt );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "getMutexName: failed to retrieve re cache salt from server_properties\n%s", ret.result().c_str() );
        return PASS( ret );
    }

    getResourceName( mutex_name, mutex_name_salt.c_str() );
    mutex_name = "re_cache_mutex_" + mutex_name;

    return SUCCESS();
}
<commit_msg>[#2212] CID26297:<commit_after>/* For copyright information please refer to files in the COPYRIGHT directory
 */
#include "debug.hpp"
#include "locks.hpp"
#include "filesystem.hpp"
#include "utils.hpp"
#include "irods_log.hpp"
#include "initServer.hpp"
#include "irods_server_properties.hpp"

int lockMutex( mutex_type **mutex ) {
    std::string mutex_name;
    irods::error ret = getMutexName( mutex_name );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "lockMutex: call to getMutexName failed" );
        return -1;
    }

    try {
        *mutex = new boost::interprocess::named_mutex( boost::interprocess::open_or_create, mutex_name.c_str() );
    } catch ( const boost::interprocess::interprocess_exception& ) {
        rodsLog( LOG_ERROR, "boost::interprocess::named_mutex threw a boost::interprocess::interprocess_exception." );
        return -1;
    }
    try {
        ( *mutex )->lock();
    } catch ( const boost::interprocess::interprocess_exception& ) {
        rodsLog( LOG_ERROR, "lock threw a boost::interprocess::interprocess_exception." );
        return -1;
    }
    return 0;
}

void unlockMutex( mutex_type **mutex ) {
    ( *mutex )->unlock();
    delete *mutex;
}

/* This function can be used during initialization to remove a previously held mutex that has not been released.
 * This should only be used when there is no other process using the mutex */
void resetMutex() {
    std::string mutex_name;
    irods::error ret = getMutexName( mutex_name );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "resetMutex: call to getMutexName failed" );
    }

    boost::interprocess::named_mutex::remove( mutex_name.c_str() );
}

irods::error getMutexName( std::string &mutex_name ) {
    std::string mutex_name_salt;
    irods::error ret = irods::server_properties::getInstance().get_property<std::string>( RE_CACHE_SALT_KW, mutex_name_salt );
    if ( !ret.ok() ) {
        rodsLog( LOG_ERROR, "getMutexName: failed to retrieve re cache salt from server_properties\n%s", ret.result().c_str() );
        return PASS( ret );
    }

    getResourceName( mutex_name, mutex_name_salt.c_str() );
    mutex_name = "re_cache_mutex_" + mutex_name;

    return SUCCESS();
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <RTcmix.h>
#include "minc_internal.h"
#include "MincValue.h"
#include <handle.h>
#include <rtcmix_types.h>
#include <prototypes.h>
#include <PField.h>

static Arg * minc_list_to_arglist(const char *funcname, const MincValue *inList, const int inListLen, Arg *inArgs, int *pNumArgs)
{
	int oldNumArgs = *pNumArgs;
	int n = 0, newNumArgs = oldNumArgs + inListLen;
	// Create expanded array
	Arg *newArgs = new Arg[newNumArgs];
	if (newArgs == NULL)
		return NULL;
	if (inArgs != NULL) {
		// Copy existing args to new array
		for (; n < oldNumArgs; ++n) {
			newArgs[n] = inArgs[n];
		}
	}
	for (int i = 0; n < newNumArgs; ++i, ++n) {
		switch (inList[i].dataType()) {
			case MincVoidType:
				minc_die("call_external_function: %s(): invalid argument type", funcname);
				delete [] newArgs;
				return NULL;
			case MincFloatType:
				newArgs[n] = (MincFloat) inList[i];
				break;
			case MincStringType:
				newArgs[n] = (MincString)inList[i];
				break;
			case MincHandleType:
				newArgs[n] = (Handle) (MincHandle)inList[i];
				break;
			case MincListType:
				if ((MincList *)inList[i] == NULL) {
					minc_die("can't pass a null list (arg %d) to RTcmix function %s()", n, funcname);
					return NULL;
				}
				if (((MincList *)inList[i])->len <= 0) {
					minc_die("can't pass an empty list (arg %d) to RTcmix function %s()", n, funcname);
					delete [] newArgs;
					return NULL;
				}
				else {
					minc_die("for now, no nested lists can be passed to RTcmix function %s()", funcname);
					delete [] newArgs;
					return NULL;
				}
                break;
            case MincMapType:
                minc_die("for now, maps cannot be passed to RTcmix function %s()", funcname);
                delete [] newArgs;
                return NULL;
            case MincStructType:
                minc_die("for now, structs cannot be passed to RTcmix function %s()", funcname);
                delete [] newArgs;
                return NULL;
		}
	}
	*pNumArgs = newNumArgs;
	return newArgs;
}

int
call_external_function(const char *funcname, const MincValue arglist[],
	const int nargs, MincValue *return_value)
{
	int result, numArgs = nargs;
	Arg retval;

	Arg *rtcmixargs = new Arg[nargs];
	if (rtcmixargs == NULL)
		return MEMORY_ERROR;

	// Convert arglist for passing to RTcmix function.
	for (int i = 0; i < nargs; i++) {
		switch (arglist[i].dataType()) {
		case MincFloatType:
			rtcmixargs[i] = (MincFloat)arglist[i];
			break;
		case MincStringType:
			rtcmixargs[i] = (MincString)arglist[i];
			break;
		case MincHandleType:
			rtcmixargs[i] = (Handle) (MincHandle)arglist[i];
#ifdef EMBEDDED
			if ((Handle)rtcmixargs[i] == NULL) {
				minc_die("can't pass a null handle (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
#endif
			break;
		case MincListType:
			{
			MincList *list = (MincList *)arglist[i];
			if (list == NULL) {
				minc_die("can't pass a null list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			if (list->len <= 0) {
				minc_die("can't pass an empty list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			// If list is final argument to function, treat its contents as additional function arguments
			if (i == nargs-1) {
				int argCount = i;
				Arg *newargs = minc_list_to_arglist(funcname, list->data, list->len, rtcmixargs, &argCount);
				delete [] rtcmixargs;
				if (newargs == NULL)
					return PARAM_ERROR;
				rtcmixargs = newargs;
				numArgs = argCount;
			}
			// If list contains only floats, convert and pass it along.
			else {
				Array *newarray = (Array *) emalloc(sizeof(Array));
				if (newarray == NULL)
					return MEMORY_ERROR;
				assert(sizeof(*newarray->data) == sizeof(double));	// because we cast MincFloat to double here
				newarray->data = (double *) float_list_to_array(list);
				if (newarray->data != NULL) {
					newarray->len = list->len;
					rtcmixargs[i] = newarray;
				}
				else {
					minc_die("can't pass a mixed-type list (arg %d) to RTcmix function %s()", i, funcname);
					free(newarray);
					return PARAM_ERROR;
				}
			}
			}
			break;
       case MincMapType:
            minc_die("%s(): arg %d: maps not supported as function arguments", funcname, i);
            return PARAM_ERROR;
            break;
       case MincStructType:
            minc_die("%s(): arg %d: structs not supported as function arguments", funcname, i);
            return PARAM_ERROR;
            break;
		default:
			minc_die("%s(): arg %d: invalid argument type", funcname, i);
			return PARAM_ERROR;
			break;
		}
	}

	result = RTcmix::dispatch(funcname, rtcmixargs, numArgs, &retval);

	// Convert return value from RTcmix function.
	switch (retval.type()) {
	case DoubleType:
		*return_value = (MincFloat) retval;
		break;
	case StringType:
		*return_value = (MincString) retval;
		break;
	case HandleType:
		*return_value = (MincHandle) (Handle) retval;
		break;
	case ArrayType:
#ifdef NOMORE
// don't think functions will return non-opaque arrays to Minc, but if they do,
// these should be converted to MincListType
		return_value->type = MincArrayType;
		{
			Array *array = (Array *) retval;
			return_value->val.array.len = array->len;
			return_value->val.array.data = array->data;
		}
#endif
		break;
	default:
		break;
	}

	delete [] rtcmixargs;

	return result;
}

void printargs(const char *funcname, const Arg arglist[], const int nargs)
{
	RTcmix::printargs(funcname, arglist, nargs);
}

static Handle _createPFieldHandle(PField *pfield)
{
	Handle handle = (Handle) malloc(sizeof(struct _handle));
	handle->type = PFieldType;
	handle->ptr = (void *) pfield;
	pfield->ref();
	handle->refcount = 0;
	return handle;
}

static double plus_binop(double x, double y)
{
	return x + y;
}
static double minus_binop(double x, double y)
{
	return x - y;
}
static double mult_binop(double x, double y)
{
	return x * y;
}
static double divide_binop(double x, double y)
{
	return (y != 0.0) ? x / y : 999999999999999999.9;
}
static double mod_binop(double x, double y)
{
	return (int) x % (int) y;
}
static double pow_binop(double x, double y)
{
	return pow(x, y);
}

PField *createBinopPField(PField *pfield1, PField *pfield2, OpKind op)
{
	PFieldBinaryOperator::Operator binop = NULL;

	// Create appropriate binary operator PField

	switch (op) {
	case OpPlus:
		binop = plus_binop;
		break;
	case OpMinus:
		binop = minus_binop;
		break;
	case OpMul:
		binop = mult_binop;
		break;
	case OpDiv:
		binop = divide_binop;
		break;
	case OpMod:
		binop = mod_binop;
		break;
	case OpPow:
		binop = pow_binop;
		break;
	case OpNeg:
	default:
		minc_internal_error("invalid binary handle operator");
		return NULL;
	}

	// create new Binop PField, return it cast to MincHandle

	return new PFieldBinaryOperator(pfield1, pfield2, binop);
}

MincHandle minc_binop_handle_float(const MincHandle mhandle,
	const MincFloat val, OpKind op)
{
	DPRINT("minc_binop_handle_float (handle=%p, val=%f\n", mhandle, val);

	// Extract PField from MincHandle.
	Handle handle = (Handle) mhandle;
	assert(handle->type == PFieldType);
	PField *pfield1 = (PField *) handle->ptr;

	// Create ConstPField for MincFloat.
	PField *pfield2 = new ConstPField(val);

	// Create PField using appropriate operator.
	PField *outpfield = createBinopPField(pfield1, pfield2, op);

	return (MincHandle) _createPFieldHandle(outpfield);
}

MincHandle minc_binop_float_handle(const MincFloat val,
	const MincHandle mhandle, OpKind op)
{
	DPRINT("minc_binop_float_handle (val=%f, handle=%p\n", val, mhandle);

	// Create ConstPField for MincFloat.
	PField *pfield1 = new ConstPField(val);

	// Extract PField from MincHandle.
	Handle handle = (Handle) mhandle;
	assert(handle->type == PFieldType);
	PField *pfield2 = (PField *) handle->ptr;

	// Create PField using appropriate operator.
	PField *outpfield = createBinopPField(pfield1, pfield2, op);

	return (MincHandle) _createPFieldHandle(outpfield);
}

MincHandle minc_binop_handles(const MincHandle mhandle1,
	const MincHandle mhandle2, OpKind op)
{
	DPRINT("minc_binop_handles (handle1=%p, handle2=%p\n", mhandle1, mhandle2);

	// Extract PFields from MincHandles

	Handle handle1 = (Handle) mhandle1;
	Handle handle2 = (Handle) mhandle2;
	assert(handle1->type == PFieldType);
	assert(handle2->type == PFieldType);
	PField *pfield1 = (PField *) handle1->ptr;
	PField *pfield2 = (PField *) handle2->ptr;
	PField *opfield = createBinopPField(pfield1, pfield2, op);

	// create Handle for new PField, return it cast to MincHandle

	return (MincHandle) _createPFieldHandle(opfield);
}

<commit_msg>handle operator functions redone to 1) not crash with null handles and 2) not assert when wrong type of handle given to pfield code.<commit_after>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <RTcmix.h>
#include "minc_internal.h"
#include "MincValue.h"
#include <handle.h>
#include <rtcmix_types.h>
#include <prototypes.h>
#include <PField.h>

static Arg * minc_list_to_arglist(const char *funcname, const MincValue *inList, const int inListLen, Arg *inArgs, int *pNumArgs)
{
	int oldNumArgs = *pNumArgs;
	int n = 0, newNumArgs = oldNumArgs + inListLen;
	// Create expanded array
	Arg *newArgs = new Arg[newNumArgs];
	if (newArgs == NULL)
		return NULL;
	if (inArgs != NULL) {
		// Copy existing args to new array
		for (; n < oldNumArgs; ++n) {
			newArgs[n] = inArgs[n];
		}
	}
	for (int i = 0; n < newNumArgs; ++i, ++n) {
		switch (inList[i].dataType()) {
			case MincVoidType:
				minc_die("call_external_function: %s(): invalid argument type", funcname);
				delete [] newArgs;
				return NULL;
			case MincFloatType:
				newArgs[n] = (MincFloat) inList[i];
				break;
			case MincStringType:
				newArgs[n] = (MincString)inList[i];
				break;
			case MincHandleType:
				newArgs[n] = (Handle) (MincHandle)inList[i];
				break;
			case MincListType:
				if ((MincList *)inList[i] == NULL) {
					minc_die("can't pass a null list (arg %d) to RTcmix function %s()", n, funcname);
					return NULL;
				}
				if (((MincList *)inList[i])->len <= 0) {
					minc_die("can't pass an empty list (arg %d) to RTcmix function %s()", n, funcname);
					delete [] newArgs;
					return NULL;
				}
				else {
					minc_die("for now, no nested lists can be passed to RTcmix function %s()", funcname);
					delete [] newArgs;
					return NULL;
				}
                break;
            case MincMapType:
                minc_die("for now, maps cannot be passed to RTcmix function %s()", funcname);
                delete [] newArgs;
                return NULL;
            case MincStructType:
                minc_die("for now, structs cannot be passed to RTcmix function %s()", funcname);
                delete [] newArgs;
                return NULL;
		}
	}
	*pNumArgs = newNumArgs;
	return newArgs;
}

int
call_external_function(const char *funcname, const MincValue arglist[],
	const int nargs, MincValue *return_value)
{
	int result, numArgs = nargs;
	Arg retval;

	Arg *rtcmixargs = new Arg[nargs];
	if (rtcmixargs == NULL)
		return MEMORY_ERROR;

	// Convert arglist for passing to RTcmix function.
	for (int i = 0; i < nargs; i++) {
		switch (arglist[i].dataType()) {
		case MincFloatType:
			rtcmixargs[i] = (MincFloat)arglist[i];
			break;
		case MincStringType:
			rtcmixargs[i] = (MincString)arglist[i];
			break;
		case MincHandleType:
			rtcmixargs[i] = (Handle) (MincHandle)arglist[i];
#ifdef EMBEDDED
			if ((Handle)rtcmixargs[i] == NULL) {
				minc_die("can't pass a null handle (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
#endif
			break;
		case MincListType:
			{
			MincList *list = (MincList *)arglist[i];
			if (list == NULL) {
				minc_die("can't pass a null list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			if (list->len <= 0) {
				minc_die("can't pass an empty list (arg %d) to RTcmix function %s()", i, funcname);
				return PARAM_ERROR;
			}
			// If list is final argument to function, treat its contents as additional function arguments
			if (i == nargs-1) {
				int argCount = i;
				Arg *newargs = minc_list_to_arglist(funcname, list->data, list->len, rtcmixargs, &argCount);
				delete [] rtcmixargs;
				if (newargs == NULL)
					return PARAM_ERROR;
				rtcmixargs = newargs;
				numArgs = argCount;
			}
			// If list contains only floats, convert and pass it along.
			else {
				Array *newarray = (Array *) emalloc(sizeof(Array));
				if (newarray == NULL)
					return MEMORY_ERROR;
				assert(sizeof(*newarray->data) == sizeof(double));	// because we cast MincFloat to double here
				newarray->data = (double *) float_list_to_array(list);
				if (newarray->data != NULL) {
					newarray->len = list->len;
					rtcmixargs[i] = newarray;
				}
				else {
					minc_die("can't pass a mixed-type list (arg %d) to RTcmix function %s()", i, funcname);
					free(newarray);
					return PARAM_ERROR;
				}
			}
			}
			break;
       case MincMapType:
            minc_die("%s(): arg %d: maps not supported as function arguments", funcname, i);
            return PARAM_ERROR;
            break;
       case MincStructType:
            minc_die("%s(): arg %d: structs not supported as function arguments", funcname, i);
            return PARAM_ERROR;
            break;
		default:
			minc_die("%s(): arg %d: invalid argument type", funcname, i);
			return PARAM_ERROR;
			break;
		}
	}

	result = RTcmix::dispatch(funcname, rtcmixargs, numArgs, &retval);

	// Convert return value from RTcmix function.
	switch (retval.type()) {
	case DoubleType:
		*return_value = (MincFloat) retval;
		break;
	case StringType:
		*return_value = (MincString) retval;
		break;
	case HandleType:
		*return_value = (MincHandle) (Handle) retval;
		break;
	case ArrayType:
#ifdef NOMORE
// don't think functions will return non-opaque arrays to Minc, but if they do,
// these should be converted to MincListType
		return_value->type = MincArrayType;
		{
			Array *array = (Array *) retval;
			return_value->val.array.len = array->len;
			return_value->val.array.data = array->data;
		}
#endif
		break;
	default:
		break;
	}

	delete [] rtcmixargs;

	return result;
}

void printargs(const char *funcname, const Arg arglist[], const int nargs)
{
	RTcmix::printargs(funcname, arglist, nargs);
}

static Handle _createPFieldHandle(PField *pfield)
{
	Handle handle = (Handle) malloc(sizeof(struct _handle));
	handle->type = PFieldType;
	handle->ptr = (void *) pfield;
	pfield->ref();
	handle->refcount = 0;
	return handle;
}

static double plus_binop(double x, double y)
{
	return x + y;
}
static double minus_binop(double x, double y)
{
	return x - y;
}
static double mult_binop(double x, double y)
{
	return x * y;
}
static double divide_binop(double x, double y)
{
	return (y != 0.0) ? x / y : 999999999999999999.9;
}
static double mod_binop(double x, double y)
{
	return (int) x % (int) y;
}
static double pow_binop(double x, double y)
{
	return pow(x, y);
}

PField *createBinopPField(PField *pfield1, PField *pfield2, OpKind op)
{
	PFieldBinaryOperator::Operator binop = NULL;

	// Create appropriate binary operator PField

	switch (op) {
	case OpPlus:
		binop = plus_binop;
		break;
	case OpMinus:
		binop = minus_binop;
		break;
	case OpMul:
		binop = mult_binop;
		break;
	case OpDiv:
		binop = divide_binop;
		break;
	case OpMod:
		binop = mod_binop;
		break;
	case OpPow:
		binop = pow_binop;
		break;
	case OpNeg:
	default:
		minc_internal_error("invalid binary handle operator");
		return NULL;
	}

	// create new Binop PField, return it cast to MincHandle

	return new PFieldBinaryOperator(pfield1, pfield2, binop);
}

MincHandle minc_binop_handle_float(const MincHandle mhandle,
	const MincFloat val, OpKind op)
{
	DPRINT("minc_binop_handle_float (handle=%p, val=%f\n", mhandle, val);

    if (mhandle == NULL) {
        minc_warn("Null handle in binary operation");
        return (MincHandle)0;
    }
	// Extract PField from MincHandle.
	Handle handle = (Handle) mhandle;
    if (handle->type != PFieldType) {
        minc_die("Illegal handle type for this operation");
        return (MincHandle)0;
    }
	PField *pfield1 = (PField *) handle->ptr;

	// Create ConstPField for MincFloat.
	PField *pfield2 = new ConstPField(val);

	// Create PField using appropriate operator.
	PField *outpfield = createBinopPField(pfield1, pfield2, op);

	return (MincHandle) _createPFieldHandle(outpfield);
}

MincHandle minc_binop_float_handle(const MincFloat val,
	const MincHandle mhandle, OpKind op)
{
	DPRINT("minc_binop_float_handle (val=%f, handle=%p\n", val, mhandle);

    if (mhandle == NULL) {
        minc_warn("Null handle in binary operation");
        return (MincHandle)0;
    }

    // Create ConstPField for MincFloat.
	PField *pfield1 = new ConstPField(val);

	// Extract PField from MincHandle.
	Handle handle = (Handle) mhandle;
    if (handle->type != PFieldType) {
        minc_die("Illegal handle type for this operation");
        return (MincHandle)0;
    }
	PField *pfield2 = (PField *) handle->ptr;

	// Create PField using appropriate operator.
	PField *outpfield = createBinopPField(pfield1, pfield2, op);

	return (MincHandle) _createPFieldHandle(outpfield);
}

MincHandle minc_binop_handles(const MincHandle mhandle1,
	const MincHandle mhandle2, OpKind op)
{
	DPRINT("minc_binop_handles (handle1=%p, handle2=%p\n", mhandle1, mhandle2);

    if (mhandle1 == NULL || mhandle2 == NULL) {
        minc_warn("Null handle(s) in binary operation");
        return (MincHandle)0;
    }
	// Extract PFields from MincHandles

	Handle handle1 = (Handle) mhandle1;
	Handle handle2 = (Handle) mhandle2;
    if (handle1->type != PFieldType || handle2->type != PFieldType) {
        minc_die("Illegal handle type(s) for this operation");
        return (MincHandle)0;
    }
	PField *pfield1 = (PField *) handle1->ptr;
	PField *pfield2 = (PField *) handle2->ptr;
	PField *opfield = createBinopPField(pfield1, pfield2, op);

	// create Handle for new PField, return it cast to MincHandle

	return (MincHandle) _createPFieldHandle(opfield);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP

#include <mapnik/segment.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/vertex_adapters.hpp>
#include <mapnik/path.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/transform_path_adapter.hpp>

#include <algorithm>
#include <deque>

#pragma GCC diagnostic push
#include <mapnik/warning_ignore_agg.hpp>
#include "agg_conv_contour.h"
#pragma GCC diagnostic pop

namespace mapnik {

struct render_building_symbolizer
{
    using vertex_adapter_type = geometry::polygon_vertex_adapter<double>;
    using transform_path_type = transform_path_adapter<view_transform, vertex_adapter_type>;
    //using roof_type = agg::conv_transform<transform_path_type>;

    template <typename F1, typename F2, typename F3, typename F4>
    static void apply(feature_impl const& feature,
                      proj_transform const& prj_trans,
                      view_transform const& view_trans,
                      double height,
                      double shadow_angle,
                      double shadow_length,
                      F1 const & face_func,
                      F2 const & frame_func,
                      F3 const & roof_func,
                      F4 const & shadow_func)
    {
        auto const& geom = feature.get_geometry();
        if (geom.is<geometry::polygon<double>>())
        {
            auto const& poly = geom.get<geometry::polygon<double>>();
            vertex_adapter_type va(poly);
            transform_path_type transformed(view_trans, va, prj_trans);
            make_building(transformed, height, shadow_angle, shadow_length,
                face_func, frame_func, roof_func, shadow_func);
        }
        else if (geom.is<geometry::multi_polygon<double>>())
        {
            auto const& multi_poly = geom.get<geometry::multi_polygon<double>>();
            for (auto const& poly : multi_poly)
            {
                vertex_adapter_type va(poly);
                transform_path_type transformed(view_trans, va, prj_trans);
                make_building(transformed, height, shadow_angle, shadow_length,
                    face_func, frame_func, roof_func, shadow_func);
            }
        }
    }

private:
    template <typename GeomVertexAdapter, typename F1, typename F2, typename F3, typename F4>
    static void make_building(GeomVertexAdapter & geom,
            double height,
            double shadow_angle,
            double shadow_length,
            F1 const& face_func,
            F2 const& frame_func,
            F3 const& roof_func,
            F4 const& shadow_func)
    {
        path_type frame(path_type::types::LineString);
        path_type roof(path_type::types::Polygon);
        std::deque<segment_t> face_segments;
        double ring_begin_x, ring_begin_y;
        double x0 = 0;
        double y0 = 0;
        double x,y;
        geom.rewind(0);
        for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
             cm = geom.vertex(&x, &y))
        {
            if (cm == SEG_MOVETO)
            {
                frame.move_to(x,y);
                ring_begin_x = x;
                ring_begin_y = y;
            }
            else if (cm == SEG_LINETO)
            {
                frame.line_to(x,y);
                face_segments.emplace_back(x0,y0,x,y);
            }
            else if (cm == SEG_CLOSE)
            {
                frame.close_path();
                if (!face_segments.empty())
                {
                    face_segments.emplace_back(x0, y0, ring_begin_x, ring_begin_y);
                }
            }
            x0 = x;
            y0 = y;
        }

        if (shadow_length > 0)
        {
            shadow_angle = util::normalize_angle(shadow_angle * (M_PI / 180.0));
            for (auto const& seg : face_segments)
            {
                double dx = std::get<2>(seg) - std::get<0>(seg);
                double dy = std::get<3>(seg) - std::get<1>(seg);
                double seg_normal_angle = std::atan2(-dx, -dy);

                double angle_diff = std::abs(seg_normal_angle - shadow_angle);
                double min_angle_diff = std::min((2 * M_PI) - angle_diff, angle_diff);

                if (min_angle_diff <= (M_PI / 2.0))
                {
                    path_type shadow(path_type::types::Polygon);
                    shadow.move_to(std::get<0>(seg), std::get<1>(seg));
                    shadow.line_to(std::get<2>(seg), std::get<3>(seg));
                    shadow.line_to(std::get<2>(seg) + shadow_length * std::cos(shadow_angle),
                                   std::get<3>(seg) - shadow_length * std::sin(shadow_angle));
                    shadow.line_to(std::get<0>(seg) + shadow_length * std::cos(shadow_angle),
                                   std::get<1>(seg) - shadow_length * std::sin(shadow_angle));
                    shadow_func(shadow);
                }
            }
        }

        for (auto const& seg : face_segments)
        {
            path_type faces(path_type::types::Polygon);
            faces.move_to(std::get<0>(seg),std::get<1>(seg));
            faces.line_to(std::get<2>(seg),std::get<3>(seg));
            faces.line_to(std::get<2>(seg),std::get<3>(seg) - height);
            faces.line_to(std::get<0>(seg),std::get<1>(seg) - height);

            face_func(faces);

            frame.move_to(std::get<0>(seg),std::get<1>(seg));
            frame.line_to(std::get<0>(seg),std::get<1>(seg) - height);
        }

        geom.rewind(0);
        for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
             cm = geom.vertex(&x, &y))
        {
            if (cm == SEG_MOVETO)
            {
                frame.move_to(x,y - height);
                roof.move_to(x,y - height);
            }
            else if (cm == SEG_LINETO)
            {
                frame.line_to(x,y - height);
                roof.line_to(x,y - height);
            }
            else if (cm == SEG_CLOSE)
            {
                frame.close_path();
                roof.close_path();
            }
        }

        frame_func(frame);
        roof_func(roof);
    }
};

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
<commit_msg>clean-up<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP

#include <mapnik/segment.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/vertex_adapters.hpp>
#include <mapnik/path.hpp>
#include <mapnik/util/math.hpp>
#include <mapnik/transform_path_adapter.hpp>

#include <algorithm>
#include <deque>

#pragma GCC diagnostic push
#include <mapnik/warning_ignore_agg.hpp>
#include "agg_conv_contour.h"
#pragma GCC diagnostic pop

namespace mapnik {

struct render_building_symbolizer
{
    using vertex_adapter_type = geometry::polygon_vertex_adapter<double>;
    using transform_path_type = transform_path_adapter<view_transform, vertex_adapter_type>;

    template <typename F1, typename F2, typename F3, typename F4>
    static void apply(feature_impl const& feature,
                      proj_transform const& prj_trans,
                      view_transform const& view_trans,
                      double height,
                      double shadow_angle,
                      double shadow_length,
                      F1 const & face_func,
                      F2 const & frame_func,
                      F3 const & roof_func,
                      F4 const & shadow_func)
    {
        auto const& geom = feature.get_geometry();
        if (geom.is<geometry::polygon<double>>())
        {
            auto const& poly = geom.get<geometry::polygon<double>>();
            vertex_adapter_type va(poly);
            transform_path_type transformed(view_trans, va, prj_trans);
            make_building(transformed, height, shadow_angle, shadow_length,
                face_func, frame_func, roof_func, shadow_func);
        }
        else if (geom.is<geometry::multi_polygon<double>>())
        {
            auto const& multi_poly = geom.get<geometry::multi_polygon<double>>();
            for (auto const& poly : multi_poly)
            {
                vertex_adapter_type va(poly);
                transform_path_type transformed(view_trans, va, prj_trans);
                make_building(transformed, height, shadow_angle, shadow_length,
                    face_func, frame_func, roof_func, shadow_func);
            }
        }
    }

private:
    template <typename GeomVertexAdapter, typename F1, typename F2, typename F3, typename F4>
    static void make_building(GeomVertexAdapter & geom,
            double height,
            double shadow_angle,
            double shadow_length,
            F1 const& face_func,
            F2 const& frame_func,
            F3 const& roof_func,
            F4 const& shadow_func)
    {
        path_type frame(path_type::types::LineString);
        path_type roof(path_type::types::Polygon);
        std::deque<segment_t> face_segments;
        double ring_begin_x, ring_begin_y;
        double x0 = 0;
        double y0 = 0;
        double x,y;
        geom.rewind(0);
        for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
             cm = geom.vertex(&x, &y))
        {
            if (cm == SEG_MOVETO)
            {
                frame.move_to(x,y);
                ring_begin_x = x;
                ring_begin_y = y;
            }
            else if (cm == SEG_LINETO)
            {
                frame.line_to(x,y);
                face_segments.emplace_back(x0,y0,x,y);
            }
            else if (cm == SEG_CLOSE)
            {
                frame.close_path();
                if (!face_segments.empty())
                {
                    face_segments.emplace_back(x0, y0, ring_begin_x, ring_begin_y);
                }
            }
            x0 = x;
            y0 = y;
        }

        if (shadow_length > 0)
        {
            shadow_angle = util::normalize_angle(shadow_angle * (M_PI / 180.0));
            for (auto const& seg : face_segments)
            {
                double dx = std::get<2>(seg) - std::get<0>(seg);
                double dy = std::get<3>(seg) - std::get<1>(seg);
                double seg_normal_angle = std::atan2(-dx, -dy);

                double angle_diff = std::abs(seg_normal_angle - shadow_angle);
                double min_angle_diff = std::min((2 * M_PI) - angle_diff, angle_diff);

                if (min_angle_diff <= (M_PI / 2.0))
                {
                    path_type shadow(path_type::types::Polygon);
                    shadow.move_to(std::get<0>(seg), std::get<1>(seg));
                    shadow.line_to(std::get<2>(seg), std::get<3>(seg));
                    shadow.line_to(std::get<2>(seg) + shadow_length * std::cos(shadow_angle),
                                   std::get<3>(seg) - shadow_length * std::sin(shadow_angle));
                    shadow.line_to(std::get<0>(seg) + shadow_length * std::cos(shadow_angle),
                                   std::get<1>(seg) - shadow_length * std::sin(shadow_angle));
                    shadow_func(shadow);
                }
            }
        }

        for (auto const& seg : face_segments)
        {
            path_type faces(path_type::types::Polygon);
            faces.move_to(std::get<0>(seg),std::get<1>(seg));
            faces.line_to(std::get<2>(seg),std::get<3>(seg));
            faces.line_to(std::get<2>(seg),std::get<3>(seg) - height);
            faces.line_to(std::get<0>(seg),std::get<1>(seg) - height);

            face_func(faces);

            frame.move_to(std::get<0>(seg),std::get<1>(seg));
            frame.line_to(std::get<0>(seg),std::get<1>(seg) - height);
        }

        geom.rewind(0);
        for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
             cm = geom.vertex(&x, &y))
        {
            if (cm == SEG_MOVETO)
            {
                frame.move_to(x,y - height);
                roof.move_to(x,y - height);
            }
            else if (cm == SEG_LINETO)
            {
                frame.line_to(x,y - height);
                roof.line_to(x,y - height);
            }
            else if (cm == SEG_CLOSE)
            {
                frame.close_path();
                roof.close_path();
            }
        }

        frame_func(frame);
        roof_func(roof);
    }
};

} // namespace mapnik

#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
<|endoftext|>


<commit_before>// -*- c++ -*-
// Program to extract word cooccurrence counts from a memory-mapped word-aligned bitext
// stores the counts lexicon in the format for mm2dTable<uint32_t> (ug_mm_2d_table.h)
// (c) 2010-2012 Ulrich Germann

#include <queue>
#include <iomanip>
#include <vector>
#include <iterator>
#include <sstream>

#include <boost/program_options.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <boost/math/distributions/binomial.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>

#include "moses/TranslationModel/UG/generic/program_options/ug_get_options.h"
// #include "ug_translation_finder.h"
// #include "ug_sorters.h"
// #include "ug_corpus_sampling.h"
#include "ug_mm_2d_table.h"
#include "ug_mm_ttrack.h"
#include  "ug_corpus_token.h"

using namespace std;
using namespace ugdiss;
using namespace boost::math;

typedef mm2dTable<id_type,id_type,uint32_t,uint32_t> LEX_t;
typedef SimpleWordId Token;

id_type first_rare_id=500;
vector<vector<uint32_t> >      JFREQ; // joint count table for frequent L1 words
vector<map<id_type,uint32_t> > JRARE; // joint count table for rare     L1 words
vector<vector<uint32_t> >      CFREQ; // cooc count table for frequent L1 words
vector<map<id_type,uint32_t> > CRARE; // cooc count table for rare     L1 words

mmTtrack<Token> T1,T2;
mmTtrack<char>     Tx;
TokenIndex      V1,V2;

string bname,cfgFile,L1,L2,oname,cooc;

// DECLARATIONS
void interpret_args(int ac, char* av[]);

void
processSentence(id_type sid)
{
  Token const* s1 = T1.sntStart(sid);
  Token const* e1 = T1.sntEnd(sid);
  Token const* s2 = T2.sntStart(sid);
  Token const* e2 = T2.sntEnd(sid);
  char const* p  = Tx.sntStart(sid);
  char const* q  = Tx.sntEnd(sid);
  ushort r,c;
  bitvector check1(T1.sntLen(sid)), check2(T2.sntLen(sid));
  check1.set();
  check2.set();
  vector<ushort> cnt1(V1.ksize(),0);
  vector<ushort> cnt2(V2.ksize(),0);
  boost::unordered_set<pair<id_type,id_type> > mycoocs;

  for (Token const* x = s1; x < e1; ++x) ++cnt1[x->id()];
  for (Token const* x = s2; x < e2; ++x) ++cnt2[x->id()];

  // count links
  while (p < q)
    {
      p = binread(p,r);
      p = binread(p,c);
      check1.reset(r);
      check2.reset(c);
      id_type id1 = (s1+r)->id();
      id_type id2 = (s2+c)->id();
      if (id1 < first_rare_id)
	JFREQ[id1][id2]++;
      else
	JRARE[id1][id2]++;
      if (cooc.size())
	mycoocs.insert(pair<id_type,id_type>(id1,id2));
    }
  // count unaliged words
  for (size_t i = check1.find_first(); i < check1.size(); i = check1.find_next(i))
    {
      id_type id1 = (s1+i)->id();
      if (id1 < first_rare_id) JFREQ[id1][0]++;
      else                     JRARE[id1][0]++;
    }
  for (size_t i = check2.find_first(); i < check2.size(); i = check2.find_next(i))
    JFREQ[0][(s2+i)->id()]++;

  if (cooc.size())
    {
      typedef boost::unordered_set<pair<id_type,id_type> >::iterator iter;
      for (iter m = mycoocs.begin(); m != mycoocs.end(); ++m)
	if (m->first < first_rare_id)
	  CFREQ[m->first][m->second] += cnt1[m->first] * cnt2[m->second];
	else
	  CRARE[m->first][m->second] += cnt1[m->first] * cnt2[m->second];
    }
}

// void
// count_coocs(id_type sid)
// {
//   Token const* s1 = T1.sntStart(sid);
//   Token const* e1 = T1.sntEnd(sid);

//   Token const* s2 = T2.sntStart(sid);
//   Token const* e2 = T2.sntEnd(sid);

//   for (Token const* x = s1; x < e1; ++x)
//     {
//       if (x->id() < first_rare_id)
// 	{
// 	  vector<uint32_t>& v = CFREQ[x->id()];
// 	  for (Token const* y = s2; y < e2; ++y)
// 	    ++v[y->id()];
// 	}
//       else
// 	{
// 	  map<id_type,uint32_t>& m = CRARE[x->id()];
// 	  for (Token const* y = s2; y < e2; ++y)
// 	    ++m[y->id()];
// 	}
//     }
// }

void
writeTable(string ofname, vector<vector<uint32_t> >& FREQ,
	   vector<map<id_type,uint32_t> >& RARE)
{
  ofstream out(ofname.c_str());
  filepos_type idxOffset=0;

  vector<uint32_t> m1; // marginals L1
  vector<uint32_t> m2; // marginals L2
  m1.resize(max(first_rare_id,V1.getNumTokens()),0);
  m2.resize(V2.getNumTokens(),0);
  vector<id_type> index(V1.getNumTokens()+1,0);
  numwrite(out,idxOffset); // blank for the time being
  numwrite(out,id_type(m1.size()));
  numwrite(out,id_type(m2.size()));

  id_type cellCount=0;
  id_type stop = min(first_rare_id,id_type(m1.size()));
  for (id_type id1 = 0; id1 < stop; ++id1)
    {
      index[id1]  = cellCount;
      vector<uint32_t> const& v = FREQ[id1];
      for (id_type id2 = 0; id2 < id_type(v.size()); ++id2)
        {
          if (!v[id2]) continue;
          cellCount++;
          numwrite(out,id2);
          out.write(reinterpret_cast<char const*>(&v[id2]),sizeof(uint32_t));
          m1[id1] += v[id2];
          m2[id2] += v[id2];
        }
    }
  for (id_type id1 = stop; id1 < id_type(m1.size()); ++id1)
    {
      index[id1]  = cellCount;
      map<id_type,uint32_t> const& M = RARE[id1];
      for (map<id_type,uint32_t>::const_iterator m = M.begin(); m != M.end(); ++m)
        {
          if (m->second == 0) continue;
          cellCount++;
          numwrite(out,m->first);
          out.write(reinterpret_cast<char const*>(&m->second),sizeof(float));
          m1[id1] += m->second;
          m2[m->first] += m->second;
        }
    }
  index[m1.size()] = cellCount;
  idxOffset    = out.tellp();
  for (size_t i = 0; i < index.size(); ++i)
    numwrite(out,index[i]);
  out.write(reinterpret_cast<char const*>(&m1[0]),m1.size()*sizeof(float));
  out.write(reinterpret_cast<char const*>(&m2[0]),m2.size()*sizeof(float));

  // re-write the file header
  out.seekp(0);
  numwrite(out,idxOffset);
  out.close();
}

int
main(int argc, char* argv[])
{
  interpret_args(argc,argv);
  char c = *bname.rbegin();
  if (c != '/' && c != '.') bname += '.';
  T1.open(bname+L1+".mct");
  T2.open(bname+L2+".mct");
  Tx.open(bname+L1+"-"+L2+".mam");
  V1.open(bname+L1+".tdx");
  V2.open(bname+L2+".tdx");

  JFREQ.resize(first_rare_id,vector<uint32_t>(V2.ksize(),0));
  JRARE.resize(V1.ksize());

  CFREQ.resize(first_rare_id,vector<uint32_t>(V2.ksize(),0));
  CRARE.resize(V1.ksize());

  for (size_t sid = 0; sid < T1.size(); ++sid)
    {
      if (sid%10000 == 0) cerr << sid << endl;
      processSentence(sid);
    }

  if (oname.size()) writeTable(oname,JFREQ,JRARE);
  if (cooc.size())  writeTable(cooc,CFREQ,CRARE);
  exit(0);
}

void
interpret_args(int ac, char* av[])
{
  namespace po=boost::program_options;
  po::variables_map vm;
  po::options_description o("Options");
  po::options_description h("Hidden Options");
  po::positional_options_description a;

  o.add_options()
    ("help,h",    "print this message")
    ("cfg,f", po::value<string>(&cfgFile),"config file")
    ("oname,o", po::value<string>(&oname),"output file name")
    ("cooc,c", po::value<string>(&cooc),
     "file name for raw co-occurrence counts")
    ;

  h.add_options()
    ("bname", po::value<string>(&bname), "base name")
    ("L1",    po::value<string>(&L1),"L1 tag")
    ("L2",    po::value<string>(&L2),"L2 tag")
    ;
  a.add("bname",1);
  a.add("L1",1);
  a.add("L2",1);
  get_options(ac,av,h.add(o),a,vm,"cfg");

  if (vm.count("help") || bname.empty() || (oname.empty() && cooc.empty()))
    {
      cout << "usage:\n\t" << av[0] << " <basename> <L1 tag> <L2 tag> [-o <output file>] [-c <output file>]\n" << endl;
      cout << "at least one of -o / -c must be specified." << endl;
      cout << o << endl;
      exit(0);
    }
}

<commit_msg>Completely rewritten. Now multi-threaded.<commit_after>// -*- c++ -*-
// Program to extract word cooccurrence counts from a memory-mapped
// word-aligned bitext stores the counts lexicon in the format for
// mm2dTable<uint32_t> (ug_mm_2d_table.h)
//
// (c) 2010-2012 Ulrich Germann

// to do: multi-threading

#include <queue>
#include <iomanip>
#include <vector>
#include <iterator>
#include <sstream>
#include <algorithm>

#include <boost/program_options.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <boost/math/distributions/binomial.hpp>
#include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp>

#include "moses/TranslationModel/UG/generic/program_options/ug_get_options.h"
#include "ug_mm_2d_table.h"
#include "ug_mm_ttrack.h"
#include "ug_corpus_token.h"

using namespace std;
using namespace ugdiss;
using namespace boost::math;

typedef mm2dTable<id_type,id_type,uint32_t,uint32_t> LEX_t;
typedef SimpleWordId Token;

// DECLARATIONS
void interpret_args(int ac, char* av[]);

mmTtrack<Token> T1,T2;
mmTtrack<char>     Tx;
TokenIndex      V1,V2;

typedef pair<id_type,id_type> wpair;
struct Count
{
  uint32_t a;
  uint32_t c;
  Count() : a(0), c(0) {};
  Count(uint32_t ax, uint32_t cx) : a(ax), c(cx) {}
};

bool
operator<(pair<id_type,Count> const& a,
	  pair<id_type,Count> const& b)
{
  return a.first < b.first;
}

typedef boost::unordered_map<wpair,Count> countmap_t;
typedef vector<vector<pair<id_type,Count> > > countlist_t;

vector<countlist_t> XLEX;

class Counter
{
public:
  countmap_t  CNT;
  countlist_t & LEX;
  size_t  offset;
  size_t    skip;
  Counter(countlist_t& lex, size_t o, size_t s)
    : LEX(lex), offset(o), skip(s) {}
  void processSentence(id_type sid);
  void operator()();
};

string bname,cfgFile,L1,L2,oname,cooc;
int    verbose;
size_t truncat;
size_t num_threads;

void
Counter::
operator()()
{
  for (size_t sid = offset; sid < min(truncat,T1.size()); sid += skip)
    processSentence(sid);

  LEX.resize(V1.ksize());
  for (countmap_t::const_iterator c = CNT.begin(); c != CNT.end(); ++c)
    {
      pair<id_type,Count> foo(c->first.second,c->second);
      LEX.at(c->first.first).push_back(foo);
    }
  typedef vector<pair<id_type,Count> > v_t;
  BOOST_FOREACH(v_t& v, LEX)
    sort(v.begin(),v.end());
}

struct lexsorter
{
  vector<countlist_t> const& v;
  id_type wid;
  lexsorter(vector<countlist_t> const& vx, id_type widx)
    : v(vx),wid(widx) {}
  bool operator()(pair<uint32_t,uint32_t> const& a,
		  pair<uint32_t,uint32_t> const& b) const
  {
    return (v.at(a.first).at(wid).at(a.second).first >
	    v.at(b.first).at(wid).at(b.second).first);
  }
};

void
writeTableHeader(ostream& out)
{
  filepos_type idxOffset=0;
  numwrite(out,idxOffset); // blank for the time being
  numwrite(out,id_type(V1.ksize()));
  numwrite(out,id_type(V2.ksize()));
}

void writeTable(ostream* aln_out, ostream* coc_out)
{
  vector<uint32_t> m1a(V1.ksize(),0); // marginals L1
  vector<uint32_t> m2a(V2.ksize(),0); // marginals L2
  vector<uint32_t> m1c(V1.ksize(),0); // marginals L1
  vector<uint32_t> m2c(V2.ksize(),0); // marginals L2
  vector<id_type> idxa(V1.ksize()+1,0);
  vector<id_type> idxc(V1.ksize()+1,0);
  if (aln_out) writeTableHeader(*aln_out);
  if (coc_out) writeTableHeader(*coc_out);
  size_t CellCountA=0,CellCountC=0;
  for (size_t id1 = 0; id1 < V1.ksize(); ++id1)
    {
      idxa[id1] = CellCountA;
      idxc[id1] = CellCountC;
      lexsorter sorter(XLEX,id1);
      vector<pair<uint32_t,uint32_t> > H; H.reserve(num_threads);
      for (size_t i = 0; i < num_threads; ++i)
	{
	  if (id1 < XLEX.at(i).size() && XLEX[i][id1].size())
	    H.push_back(pair<uint32_t,uint32_t>(i,0));
	}
      if (!H.size()) continue;
      make_heap(H.begin(),H.end(),sorter);
      while (H.size())
	{
	  id_type  id2 = XLEX[H[0].first][id1][H[0].second].first;
	  uint32_t aln = XLEX[H[0].first][id1][H[0].second].second.a;
	  uint32_t coc = XLEX[H[0].first][id1][H[0].second].second.c;
	  pop_heap(H.begin(),H.end(),sorter);
	  ++H.back().second;
	  if (H.back().second == XLEX[H.back().first][id1].size())
	    H.pop_back();
	  else
	    push_heap(H.begin(),H.end(),sorter);
	  while (H.size() &&
		 XLEX[H[0].first][id1].at(H[0].second).first == id2)
	    {
	      aln += XLEX[H[0].first][id1][H[0].second].second.a;
	      coc += XLEX[H[0].first][id1][H[0].second].second.c;
	      pop_heap(H.begin(),H.end(),sorter);
	      ++H.back().second;
	      if (H.back().second == XLEX[H.back().first][id1].size())
		H.pop_back();
	      else
		push_heap(H.begin(),H.end(),sorter);
	    }
	  if (aln_out)
	    {
	      ++CellCountA;
	      numwrite(*aln_out,id2);
	      numwrite(*aln_out,aln);
	      m1a[id1] += aln;
	      m2a[id2] += aln;
	    }
	  if (coc_out && coc)
	    {
	      ++CellCountC;
	      numwrite(*coc_out,id2);
	      numwrite(*coc_out,coc);
	      m1c[id1] += coc;
	      m2c[id2] += coc;
	    }
	}
    }
  idxa.back() = CellCountA;
  idxc.back() = CellCountC;
  if (aln_out)
    {
      filepos_type idxOffsetA = aln_out->tellp();
      BOOST_FOREACH(id_type foo, idxa)
	numwrite(*aln_out,foo);
      aln_out->write(reinterpret_cast<char const*>(&m1a[0]),m1a.size()*4);
      aln_out->write(reinterpret_cast<char const*>(&m2a[0]),m2a.size()*4);
      aln_out->seekp(0);
      numwrite(*aln_out,idxOffsetA);
    }
  if (coc_out)
    {
      filepos_type idxOffsetC = coc_out->tellp();
      BOOST_FOREACH(id_type foo, idxc)
	numwrite(*coc_out,foo);
      coc_out->write(reinterpret_cast<char const*>(&m1c[0]),m1c.size()*4);
      coc_out->write(reinterpret_cast<char const*>(&m2c[0]),m2c.size()*4);
      coc_out->seekp(0);
      numwrite(*coc_out,idxOffsetC);
    }
}

void
Counter::
processSentence(id_type sid)
{
  Token const* s1 = T1.sntStart(sid);
  Token const* e1 = T1.sntEnd(sid);
  Token const* s2 = T2.sntStart(sid);
  Token const* e2 = T2.sntEnd(sid);
  vector<ushort> cnt1(V1.ksize(),0);
  vector<ushort> cnt2(V2.ksize(),0);
  for (Token const* x = s1; x < e1; ++x)
    ++cnt1.at(x->id());
  for (Token const* x = s2; x < e2; ++x)
    ++cnt2.at(x->id());

  boost::unordered_set<wpair> seen;
  bitvector check1(T1.sntLen(sid)); check1.set();
  bitvector check2(T2.sntLen(sid)); check2.set();

  // count links
  char const*   p = Tx.sntStart(sid);
  char const*   q = Tx.sntEnd(sid);
  ushort r,c;
  // cout << sid << " " << q-p << endl;
  while (p < q)
    {
      p = binread(p,r);
      p = binread(p,c);
      // cout << sid << " " << r << "-" << c << endl;
      assert(r < check1.size());
      assert(c < check2.size());
      assert(s1+r < e1);
      assert(s2+c < e2);
      check1.reset(r);
      check2.reset(c);
      id_type id1 = (s1+r)->id();
      id_type id2 = (s2+c)->id();
      wpair k(id1,id2);
      Count& cnt = CNT[k];
      cnt.a++;
      if (seen.insert(k).second)
	cnt.c += cnt1[id1] * cnt2[id2];
    }
  // count unaliged words
  for (size_t i = check1.find_first();
       i < check1.size();
       i = check1.find_next(i))
    CNT[wpair((s1+i)->id(),0)].a++;
  for (size_t i = check2.find_first();
       i < check2.size();
       i = check2.find_next(i))
    CNT[wpair(0,(s2+i)->id())].a++;
}

// void
// writeTable(string ofname,
// 	   vector<vector<uint32_t> >& FREQ,
// 	   vector<map<id_type,uint32_t> >& RARE)
// {
//   ofstream out(ofname.c_str());
//   filepos_type idxOffset=0;

//   vector<uint32_t> m1; // marginals L1
//   vector<uint32_t> m2; // marginals L2
//   m1.resize(max(first_rare_id,V1.getNumTokens()),0);
//   m2.resize(V2.getNumTokens(),0);
//   vector<id_type> index(V1.getNumTokens()+1,0);
//   numwrite(out,idxOffset); // blank for the time being
//   numwrite(out,id_type(m1.size()));
//   numwrite(out,id_type(m2.size()));

//   id_type cellCount=0;
//   id_type stop = min(first_rare_id,id_type(m1.size()));
//   for (id_type id1 = 0; id1 < stop; ++id1)
//     {
//       index[id1]  = cellCount;
//       vector<uint32_t> const& v = FREQ[id1];
//       for (id_type id2 = 0; id2 < id_type(v.size()); ++id2)
//         {
//           if (!v[id2]) continue;
//           cellCount++;
//           numwrite(out,id2);
//           out.write(reinterpret_cast<char const*>(&v[id2]),sizeof(uint32_t));
//           m1[id1] += v[id2];
//           m2[id2] += v[id2];
//         }
//     }
//   for (id_type id1 = stop; id1 < id_type(m1.size()); ++id1)
//     {
//       index[id1]  = cellCount;
//       map<id_type,uint32_t> const& M = RARE[id1];
//       for (map<id_type,uint32_t>::const_iterator m = M.begin(); m != M.end(); ++m)
//         {
//           if (m->second == 0) continue;
//           cellCount++;
//           numwrite(out,m->first);
//           out.write(reinterpret_cast<char const*>(&m->second),sizeof(float));
//           m1[id1] += m->second;
//           m2[m->first] += m->second;
//         }
//     }
//   index[m1.size()] = cellCount;
//   idxOffset    = out.tellp();
//   for (size_t i = 0; i < index.size(); ++i)
//     numwrite(out,index[i]);
//   out.write(reinterpret_cast<char const*>(&m1[0]),m1.size()*sizeof(float));
//   out.write(reinterpret_cast<char const*>(&m2[0]),m2.size()*sizeof(float));

//   // re-write the file header
//   out.seekp(0);
//   numwrite(out,idxOffset);
//   out.close();
// }

int
main(int argc, char* argv[])
{
  interpret_args(argc,argv);
  char c = *bname.rbegin();
  if (c != '/' && c != '.') bname += '.';
  T1.open(bname+L1+".mct");
  T2.open(bname+L2+".mct");
  Tx.open(bname+L1+"-"+L2+".mam");
  V1.open(bname+L1+".tdx");
  V2.open(bname+L2+".tdx");
  if (!truncat) truncat = T1.size();
  XLEX.resize(num_threads);
  vector<boost::shared_ptr<boost::thread> > workers(num_threads);
  for (size_t i = 0; i < num_threads; ++i)
    workers[i].reset(new boost::thread(Counter(XLEX[i],i,num_threads)));
  for (size_t i = 0; i < workers.size(); ++i)
    workers[i]->join();
  // cerr << "done counting" << endl;
  ofstream aln_out,coc_out;
  if (oname.size()) aln_out.open(oname.c_str());
  if (cooc.size())  coc_out.open(cooc.c_str());
  writeTable(oname.size() ? &aln_out : NULL,
	     cooc.size()  ? &coc_out : NULL);
  if (oname.size()) aln_out.close();
  if (cooc.size())  coc_out.close();
}

void
interpret_args(int ac, char* av[])
{
  namespace po=boost::program_options;
  po::variables_map vm;
  po::options_description o("Options");
  po::options_description h("Hidden Options");
  po::positional_options_description a;

  o.add_options()
    ("help,h",    "print this message")
    ("cfg,f", po::value<string>(&cfgFile),"config file")
    ("oname,o", po::value<string>(&oname),"output file name")
    ("cooc,c", po::value<string>(&cooc),
     "file name for raw co-occurrence counts")
    ("verbose,v", po::value<int>(&verbose)->default_value(0)->implicit_value(1),
     "verbosity level")
    ("threads,t", po::value<size_t>(&num_threads)->default_value(4),
     "count in <N> parallel threads")
    ("truncate,n", po::value<size_t>(&truncat)->default_value(0),
     "truncate corpus to <N> sentences (for debugging)")
    ;

  h.add_options()
    ("bname", po::value<string>(&bname), "base name")
    ("L1",    po::value<string>(&L1),"L1 tag")
    ("L2",    po::value<string>(&L2),"L2 tag")
    ;
  a.add("bname",1);
  a.add("L1",1);
  a.add("L2",1);
  get_options(ac,av,h.add(o),a,vm,"cfg");

  if (vm.count("help") || bname.empty() || (oname.empty() && cooc.empty()))
    {
      cout << "usage:\n\t" << av[0] << " <basename> <L1 tag> <L2 tag> [-o <output file>] [-c <output file>]\n" << endl;
      cout << "at least one of -o / -c must be specified." << endl;
      cout << o << endl;
      exit(0);
    }
  num_threads = min(num_threads,24UL);
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageMIPFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to Abdalmajeid M. Alyassin who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageMIPFilter.h"
#include <math.h>
#include <stdlib.h>

//----------------------------------------------------------------------------
// Description:
// Constructor sets default values
vtkImageMIPFilter::vtkImageMIPFilter()
{
  this->ProjectionRange[0] = 0;
  this->ProjectionRange[1] = 0;
  this->MinMaxIP = 1;
  this->MIPX = 0; this->MIPY = 0; this->MIPZ = 1;
  this->SetAxes(VTK_IMAGE_X_AXIS, VTK_IMAGE_Y_AXIS,VTK_IMAGE_Z_AXIS);

  this->ExecuteDimensionality = 3;
  // Input is 3D, output is 2D
  this->Dimensionality = 3;
}

//----------------------------------------------------------------------------
void vtkImageMIPFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkImageFilter::PrintSelf(os,indent);
  os << indent << "MinMaxIP : (" << this->MinMaxIP << ")\n";

  os << indent << "MIP Direction: x-y, x-z, or y-z plane : ("
     << this->GetMIPX() << ", " << this->GetMIPY() << ", "
     << this->GetMIPZ() << ")\n";
}

//----------------------------------------------------------------------------
// Description:
// This templated function executes the filter for any type of data.
template <class T>
void vtkImageMIPFilterExecute(vtkImageMIPFilter *self,
				   vtkImageRegion *inRegion, T *inPtr,
				   vtkImageRegion *outRegion, T *outPtr)
{
  int min0, max0, min1, max1;
  int idx0, idx1,idx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1;
  T *inPtr0, *inPtr1, *inPtr2;
  T *outPtr0, *outPtr1,startvalue;
  int prorange[2], minmaxip;
  int defmin;
  int mipx,mipy,mipz;
  int  mipflag(int m1,int m2, int m3);

  // Get information to march through data
  inRegion->GetIncrements(inInc0, inInc1, inInc2);
  outRegion->GetIncrements(outInc0, outInc1);
  outRegion->GetExtent(min0, max0, min1, max1);
  self->GetProjectionRange(prorange[0],prorange[1]);
  minmaxip = self->GetMinMaxIP();
  mipx = self->GetMIPX();
  mipy = self->GetMIPY();
  mipz = self->GetMIPZ();
  if (!mipflag(mipx,mipy,mipz)){ return;}

   //  Loop first through projection range then along the other two axes
	inPtr1  = inPtr ;
        outPtr1 = outPtr;

    if ( minmaxip == 1) {
       if (mipz) {
       cout << " MIPZ is on !!!" << endl;

	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		inPtr2  = inPtr0;
		for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
		    if (*inPtr2 > *outPtr0) *outPtr0 = *inPtr2;
      	               inPtr2 += inInc2;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
    	    inPtr1  += inInc1;
	}
      }
      else if (mipy) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPXZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr1 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr2;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		inPtr1  = inPtr0;
                for (idx1 = min1; idx1 <= max1; ++idx1){
		    if (*inPtr1 > *outPtr0) *outPtr0 = *inPtr1;
    	            inPtr1  += inInc1;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
      	    inPtr2  += inInc2;
	}
      }
      else if (mipx) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPYZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr0 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr1 = outPtr0;
    	    inPtr1  = inPtr2;
            for (idx1 = min1; idx1 <= max1; ++idx1){
		*outPtr1 = 0;
		inPtr0   = inPtr1;
                for (idx0 = min0; idx0 <= max0; ++idx0){
		    if (*inPtr0 > *outPtr1) *outPtr1 = *inPtr0;
    	            inPtr0  += inInc0;
		}
		outPtr1 += outInc1;
      	        inPtr1  += inInc1;
	    }
	    outPtr0 += outInc0;
      	    inPtr2  += inInc2;
	}
      }
   }
   else if ( minmaxip == 0) {
        defmin = sizeof(startvalue);
        startvalue = (T)pow(2.0,double(8*defmin -1)) - 1;
      if ( mipz ) {
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		// need to find optimum minimum !!! interesting
		*outPtr0 = startvalue;
		inPtr2  = inPtr0;
		for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
		    if (*inPtr2 < *outPtr0) *outPtr0 = *inPtr2;
      	               inPtr2 += inInc2;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
    	    inPtr1  += inInc1;
        }
      }
      else if (mipy) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPXZ is on !!!" << endl;
        inPtr2  = inPtr ;
        outPtr1 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr2;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = startvalue;
		inPtr1  = inPtr0;
                for (idx1 = min1; idx1 <= max1; ++idx1){
		    if (*inPtr1 < *outPtr0) *outPtr0 = *inPtr1;
    	            inPtr1  += inInc1;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
      	    inPtr2  += inInc2;
	}
      }
      else if (mipx) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPYZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr0 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr1 = outPtr0;
    	    inPtr1  = inPtr2;
            for (idx1 = min1; idx1 <= max1; ++idx1){
		*outPtr1 = startvalue;
		inPtr0  = inPtr1;
                for (idx0 = min0; idx0 <= max0; ++idx0){
		    if (*inPtr0 < *outPtr1) *outPtr1 = *inPtr0;
    	            inPtr0  += inInc0;
		}
		outPtr1 += outInc1;
      	        inPtr1  += inInc1;
	    }
	    outPtr0 += outInc0;
      	    inPtr2  += inInc2;
	}

      }
   }
   else {
	cerr << "Not Valid value for MinMaxIP, must be either 0 or 1" << endl;
        return;
   }

}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function: int mipflag(int mipx,int mipy,int mipz)
checks that only one flag is set to do MIP.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int mipflag(int mipx,int mipy,int mipz) {
  // check that only one flag for MIP is on ...
  if ( mipx) {
     if ( mipy | mipz ) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else if ( mipy) {
     if ( mipx | mipz) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else if ( mipz) {
     if ( mipx | mipy) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else {
	cerr << "Please set either (MIPX, MIPY, or MIPZ) On for MIP!!!" << endl;
        return 0;
  }
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a input and output region, and executes the filter
// algorithm to fill the output from the input.
// It just executes a switch statement to call the correct function for
// the regions data types.
void vtkImageMIPFilter::Execute(vtkImageRegion *inRegion,
				  vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetScalarPointer();
  void *outPtr = outRegion->GetScalarPointer();

  vtkDebugMacro(<< "Execute: inRegion = " << inRegion
		<< ", outRegion = " << outRegion);

  // this filter expects that input is the same type as output.
  if (inRegion->GetScalarType() != outRegion->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inRegion->GetScalarType()
                  << ", must match out ScalarType " << outRegion->GetScalarType());
    return;
    }

  switch (inRegion->GetScalarType())
    {
    case VTK_FLOAT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_INT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (int *)(outPtr));
      break;
    case VTK_SHORT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (short *)(outPtr));
      break;
    case VTK_UNSIGNED_SHORT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (unsigned short *)(outPtr));
      break;
    case VTK_UNSIGNED_CHAR:
      vtkImageMIPFilterExecute(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (unsigned char *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a region that holds the boundary of this filters
// input, and changes the region to hold the boundary of this filters
// output.
void
vtkImageMIPFilter::ComputeOutputImageInformation(vtkImageRegion *inRegion,
						 vtkImageRegion *outRegion)
{
  int extent[6];

  // reduce extent from 3 to 2 D.
  inRegion->GetImageExtent(3, extent);
  extent[4] = 0; extent[5] =0;
  outRegion->SetImageExtent(3, extent);
}

//----------------------------------------------------------------------------
// Description:
// This method computes the extent of the input region necessary to generate
// an output region.  Before this method is called "region" should have the
// extent of the output region.  After this method finishes, "region" should
// have the extent of the required input region.
void vtkImageMIPFilter::ComputeRequiredInputRegionExtent(
                                                    vtkImageRegion *outRegion,
			                            vtkImageRegion *inRegion)
{
  int extent[6];
  int imageExtent[6];

  outRegion->GetExtent(3, extent);

  inRegion->GetImageExtent(3, imageExtent);

  extent[4] = this->ProjectionRange[0];
  extent[5] = this->ProjectionRange[1];

  inRegion->SetExtent(3, extent);
}

<commit_msg>minor pc fix<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageMIPFilter.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$
  Thanks:    Thanks to Abdalmajeid M. Alyassin who developed this class.

Copyright (c) 1993-1995 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageMIPFilter.h"
#include <math.h>
#include <stdlib.h>

//----------------------------------------------------------------------------
// Description:
// Constructor sets default values
vtkImageMIPFilter::vtkImageMIPFilter()
{
  this->ProjectionRange[0] = 0;
  this->ProjectionRange[1] = 0;
  this->MinMaxIP = 1;
  this->MIPX = 0; this->MIPY = 0; this->MIPZ = 1;
  this->SetAxes(VTK_IMAGE_X_AXIS, VTK_IMAGE_Y_AXIS,VTK_IMAGE_Z_AXIS);

  this->ExecuteDimensionality = 3;
  // Input is 3D, output is 2D
  this->Dimensionality = 3;
}

//----------------------------------------------------------------------------
void vtkImageMIPFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkImageFilter::PrintSelf(os,indent);
  os << indent << "MinMaxIP : (" << this->MinMaxIP << ")\n";

  os << indent << "MIP Direction: x-y, x-z, or y-z plane : ("
     << this->GetMIPX() << ", " << this->GetMIPY() << ", "
     << this->GetMIPZ() << ")\n";
}

// prototype for local function
int  mipflag(int m1, int m2, int m3);

//----------------------------------------------------------------------------
// Description:
// This templated function executes the filter for any type of data.
template <class T>
void vtkImageMIPFilterExecute(vtkImageMIPFilter *self,
				   vtkImageRegion *inRegion, T *inPtr,
				   vtkImageRegion *outRegion, T *outPtr)
{
  int min0, max0, min1, max1;
  int idx0, idx1,idx2;
  int inInc0, inInc1, inInc2;
  int outInc0, outInc1;
  T *inPtr0, *inPtr1, *inPtr2;
  T *outPtr0, *outPtr1,startvalue;
  int prorange[2], minmaxip;
  int defmin;
  int mipx,mipy,mipz;

  // Get information to march through data
  inRegion->GetIncrements(inInc0, inInc1, inInc2);
  outRegion->GetIncrements(outInc0, outInc1);
  outRegion->GetExtent(min0, max0, min1, max1);
  self->GetProjectionRange(prorange[0],prorange[1]);
  minmaxip = self->GetMinMaxIP();
  mipx = self->GetMIPX();
  mipy = self->GetMIPY();
  mipz = self->GetMIPZ();
  if (!mipflag(mipx,mipy,mipz)){ return;}

   //  Loop first through projection range then along the other two axes
	inPtr1  = inPtr ;
        outPtr1 = outPtr;

    if ( minmaxip == 1) {
       if (mipz) {
       cout << " MIPZ is on !!!" << endl;

	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		inPtr2  = inPtr0;
		for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
		    if (*inPtr2 > *outPtr0) *outPtr0 = *inPtr2;
      	               inPtr2 += inInc2;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
    	    inPtr1  += inInc1;
	}
      }
      else if (mipy) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPXZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr1 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr2;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		inPtr1  = inPtr0;
                for (idx1 = min1; idx1 <= max1; ++idx1){
		    if (*inPtr1 > *outPtr0) *outPtr0 = *inPtr1;
    	            inPtr1  += inInc1;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
      	    inPtr2  += inInc2;
	}
      }
      else if (mipx) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPYZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr0 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr1 = outPtr0;
    	    inPtr1  = inPtr2;
            for (idx1 = min1; idx1 <= max1; ++idx1){
		*outPtr1 = 0;
		inPtr0   = inPtr1;
                for (idx0 = min0; idx0 <= max0; ++idx0){
		    if (*inPtr0 > *outPtr1) *outPtr1 = *inPtr0;
    	            inPtr0  += inInc0;
		}
		outPtr1 += outInc1;
      	        inPtr1  += inInc1;
	    }
	    outPtr0 += outInc0;
      	    inPtr2  += inInc2;
	}
      }
   }
   else if ( minmaxip == 0) {
        defmin = sizeof(startvalue);
        startvalue = (T)pow(2.0,double(8*defmin -1)) - 1;
      if ( mipz ) {
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		// need to find optimum minimum !!! interesting
		*outPtr0 = startvalue;
		inPtr2  = inPtr0;
		for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
		    if (*inPtr2 < *outPtr0) *outPtr0 = *inPtr2;
      	               inPtr2 += inInc2;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
    	    inPtr1  += inInc1;
        }
      }
      else if (mipy) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPXZ is on !!!" << endl;
        inPtr2  = inPtr ;
        outPtr1 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr0 = outPtr1;
    	    inPtr0  = inPtr2;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = startvalue;
		inPtr1  = inPtr0;
                for (idx1 = min1; idx1 <= max1; ++idx1){
		    if (*inPtr1 < *outPtr0) *outPtr0 = *inPtr1;
    	            inPtr1  += inInc1;
		}
		outPtr0 += outInc0;
      	        inPtr0  += inInc0;
	    }
	    outPtr1 += outInc1;
      	    inPtr2  += inInc2;
	}
      }
      else if (mipx) {
        // clear output image ...
        outPtr1 = outPtr;
	for (idx1 = min1; idx1 <= max1; ++idx1){
    	    outPtr0 = outPtr1;
    	    for (idx0 = min0; idx0 <= max0; ++idx0){
		*outPtr0 = 0;
		 outPtr0 += outInc0;
	    }
	    outPtr1 += outInc1;
	}
        cout << " MIPYZ is on !!!" << endl;
	inPtr2  = inPtr ;
        outPtr0 = outPtr;
	for (idx2 = prorange[0];idx2 <= prorange[1];idx2++){
    	    outPtr1 = outPtr0;
    	    inPtr1  = inPtr2;
            for (idx1 = min1; idx1 <= max1; ++idx1){
		*outPtr1 = startvalue;
		inPtr0  = inPtr1;
                for (idx0 = min0; idx0 <= max0; ++idx0){
		    if (*inPtr0 < *outPtr1) *outPtr1 = *inPtr0;
    	            inPtr0  += inInc0;
		}
		outPtr1 += outInc1;
      	        inPtr1  += inInc1;
	    }
	    outPtr0 += outInc0;
      	    inPtr2  += inInc2;
	}

      }
   }
   else {
	cerr << "Not Valid value for MinMaxIP, must be either 0 or 1" << endl;
        return;
   }

}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function: int mipflag(int mipx,int mipy,int mipz)
checks that only one flag is set to do MIP.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int mipflag(int mipx,int mipy,int mipz) {
  // check that only one flag for MIP is on ...
  if ( mipx) {
     if ( mipy | mipz ) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else if ( mipy) {
     if ( mipx | mipz) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else if ( mipz) {
     if ( mipx | mipy) {
        cerr << "Please set only on flag for MIP!!!" << endl;
        return 0;
     }
     else return 1;
  }
  else {
	cerr << "Please set either (MIPX, MIPY, or MIPZ) On for MIP!!!" << endl;
        return 0;
  }
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a input and output region, and executes the filter
// algorithm to fill the output from the input.
// It just executes a switch statement to call the correct function for
// the regions data types.
void vtkImageMIPFilter::Execute(vtkImageRegion *inRegion,
				  vtkImageRegion *outRegion)
{
  void *inPtr = inRegion->GetScalarPointer();
  void *outPtr = outRegion->GetScalarPointer();

  vtkDebugMacro(<< "Execute: inRegion = " << inRegion
		<< ", outRegion = " << outRegion);

  // this filter expects that input is the same type as output.
  if (inRegion->GetScalarType() != outRegion->GetScalarType())
    {
    vtkErrorMacro(<< "Execute: input ScalarType, " << inRegion->GetScalarType()
                  << ", must match out ScalarType " << outRegion->GetScalarType());
    return;
    }

  switch (inRegion->GetScalarType())
    {
    case VTK_FLOAT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (float *)(inPtr),
			  outRegion, (float *)(outPtr));
      break;
    case VTK_INT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (int *)(inPtr),
			  outRegion, (int *)(outPtr));
      break;
    case VTK_SHORT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (short *)(inPtr),
			  outRegion, (short *)(outPtr));
      break;
    case VTK_UNSIGNED_SHORT:
      vtkImageMIPFilterExecute(this,
			  inRegion, (unsigned short *)(inPtr),
			  outRegion, (unsigned short *)(outPtr));
      break;
    case VTK_UNSIGNED_CHAR:
      vtkImageMIPFilterExecute(this,
			  inRegion, (unsigned char *)(inPtr),
			  outRegion, (unsigned char *)(outPtr));
      break;
    default:
      vtkErrorMacro(<< "Execute: Unknown ScalarType");
      return;
    }
}

//----------------------------------------------------------------------------
// Description:
// This method is passed a region that holds the boundary of this filters
// input, and changes the region to hold the boundary of this filters
// output.
void
vtkImageMIPFilter::ComputeOutputImageInformation(vtkImageRegion *inRegion,
						 vtkImageRegion *outRegion)
{
  int extent[6];

  // reduce extent from 3 to 2 D.
  inRegion->GetImageExtent(3, extent);
  extent[4] = 0; extent[5] =0;
  outRegion->SetImageExtent(3, extent);
}

//----------------------------------------------------------------------------
// Description:
// This method computes the extent of the input region necessary to generate
// an output region.  Before this method is called "region" should have the
// extent of the output region.  After this method finishes, "region" should
// have the extent of the required input region.
void vtkImageMIPFilter::ComputeRequiredInputRegionExtent(
                                                    vtkImageRegion *outRegion,
			                            vtkImageRegion *inRegion)
{
  int extent[6];
  int imageExtent[6];

  outRegion->GetExtent(3, extent);

  inRegion->GetImageExtent(3, imageExtent);

  extent[4] = this->ProjectionRange[0];
  extent[5] = this->ProjectionRange[1];

  inRegion->SetExtent(3, extent);
}

<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(1)

// Heap solution.
class Solution {
public:
    int nthUglyNumber(int n) {
        long long ugly_number = 0;
        priority_queue<long long , vector<long long>, greater<long long>> heap;

        heap.emplace(1);
        for (int i = 0; i < n; ++i) {
            ugly_number = heap.top();
            heap.pop();
            if (ugly_number % 2 == 0) {
                heap.emplace(ugly_number * 2);
            } else if (ugly_number % 3 == 0) {
                heap.emplace(ugly_number * 2);
                heap.emplace(ugly_number * 3);
            } else {
                heap.emplace(ugly_number * 2);
                heap.emplace(ugly_number * 3);
                heap.emplace(ugly_number * 5);
            }
        }
        return ugly_number;
    }
};

// BST solution.
class Solution2 {
public:
    int nthUglyNumber(int n) {
        long long ugly_number = 0;
        set<long long> bst;

        bst.emplace(1);
        for (int i = 0; i < n; ++i) {
            ugly_number = *bst.cbegin();
            bst.erase(bst.cbegin());
            if (ugly_number % 2 == 0) {
                bst.emplace(ugly_number * 2);
            } else if (ugly_number % 3 == 0) {
                bst.emplace(ugly_number * 2);
                bst.emplace(ugly_number * 3);
            } else {
                bst.emplace(ugly_number * 2);
                bst.emplace(ugly_number * 3);
                bst.emplace(ugly_number * 5);
            }
        }
        return ugly_number;
    }
};
<commit_msg>Update ugly-number-ii.cpp<commit_after>// Time:  O(n)
// Space: O(n)

// DP solution. (20ms)
class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> uglies{1};

        int f2 = 2, f3 = 3, f5 = 5;
        int idx2 = 0, idx3 = 0, idx5 = 0;

        while (uglies.size() < n) {
            int min_val = min(min(f2, f3), f5);
            uglies.emplace_back(min_val);

            if (min_val == f2) {
                f2 = 2 * uglies[++idx2];
            }
            if (min_val == f3) {
                f3 = 3 * uglies[++idx3];
            }
            if (min_val == f5) {
                f5 = 5 * uglies[++idx5];
            }
        }

        return uglies[n - 1];
    }
};

// Time:  O(n)
// Space: O(1)
// Heap solution. (148ms)
class Solution2 {
public:
    int nthUglyNumber(int n) {
        long long ugly_number = 0;
        priority_queue<long long , vector<long long>, greater<long long>> heap;

        heap.emplace(1);
        for (int i = 0; i < n; ++i) {
            ugly_number = heap.top();
            heap.pop();
            if (ugly_number % 2 == 0) {
                heap.emplace(ugly_number * 2);
            } else if (ugly_number % 3 == 0) {
                heap.emplace(ugly_number * 2);
                heap.emplace(ugly_number * 3);
            } else {
                heap.emplace(ugly_number * 2);
                heap.emplace(ugly_number * 3);
                heap.emplace(ugly_number * 5);
            }
        }
        return ugly_number;
    }
};

// BST solution.
class Solution3 {
public:
    int nthUglyNumber(int n) {
        long long ugly_number = 0;
        set<long long> bst;

        bst.emplace(1);
        for (int i = 0; i < n; ++i) {
            ugly_number = *bst.cbegin();
            bst.erase(bst.cbegin());
            if (ugly_number % 2 == 0) {
                bst.emplace(ugly_number * 2);
            } else if (ugly_number % 3 == 0) {
                bst.emplace(ugly_number * 2);
                bst.emplace(ugly_number * 3);
            } else {
                bst.emplace(ugly_number * 2);
                bst.emplace(ugly_number * 3);
                bst.emplace(ugly_number * 5);
            }
        }
        return ugly_number;
    }
};
<|endoftext|>