<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_version.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "command_strings.h"
#include "daemon.h"
#include "safe_sock.h"
#include "condor_distribution.h"
#include "daemon_list.h"
#include "dc_collector.h"
#include "my_hostname.h"

void
usage( const char *cmd , const char * opt)
{
	fprintf(stderr,"Usage: %s [options] <update-command> [<classad-filename>]\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"    -help             Display options\n");
	fprintf(stderr,"    -version          Display Condor version\n");
	fprintf(stderr,"    -pool <hostname>  Use this central manager\n");
	fprintf(stderr,"    -debug            Show extra debugging info\n");
	fprintf(stderr,"    -tcp              Ship classad via TCP (default is UDP)\n");
	fprintf(stderr,"    -multiple         Publish multiple ads, separated by blank lines\n");

	if (opt && ( !strcmp(opt,"all") || !strcmp(opt,"cmd"))) {
		fprintf(stderr,"\nAnd <update-command> is one of:\n");
		static const char * const aPre[] = {"UPDATE_", "MERGE_", "INVALIDATE_"};
		for (int jj = 0; jj < (int)COUNTOF(aPre); ++jj) {
			for (int id = UPDATE_STARTD_AD; id < UPDATE_STARTD_AD + 100; ++id) {
				const char * cmdname = getCollectorCommandString(id);
				if (cmdname && starts_with(cmdname, aPre[jj])) {
					fprintf(stderr,"    %s\n",cmdname);
				}
			}
		}
	}

	fprintf(stderr, "\nIf <classad-filename> does not exist or is -, classads will be read from standard input\n");
	fprintf(stderr,"Example: %s -debug UPDATE_STORAGE_AD adfile\n\n",cmd);
}

// this class is used to help parse one or more ClassAd's from a FILE*
class ToolClassAdFileParseHelper : public ClassAdFileParseHelper
{
 public:
	// Some compilers whine when you have virtual methods but not an
	// explicit virtual destructor
	virtual ~ToolClassAdFileParseHelper() {}
	ToolClassAdFileParseHelper(bool multi, FILE* errout) : multiple(multi), out(errout) {};

	// return 0 to skip (is_comment), 1 to parse line, 2 for end-of-classad, -1 for abort
	virtual int PreParse(std::string & line, ClassAd & /*ad*/, FILE* /*file*/) {
		// if this line matches the ad delimitor, tell the parser to stop parsing
		if (multiple && (line.empty() || (line[0] == '\n')))
			return 2; //end-of-classad

		// check for blank lines or lines whose first character is #
		// tell the parse to skip those lines, otherwise tell the parser to
		// parse the line.
		for (size_t ix = 0; ix < line.size(); ++ix) {
			if (line[ix] == '#' || line[ix] == '\n')
				return 0; // skip this line, but don't stop parsing.
			if (line[ix] != ' ' && line[ix] != '\t')
				return 1; // parse this line
		}
		return 1; // parse this line.
	}

	// return 0 to skip and continue, 1 to re-parse line, 2 to quit parsing with success, -1 to abort parsing.
	virtual int OnParseError(std::string & line, ClassAd & /*ad*/, FILE* file) {
		// print out where we barfed to the log file
		dprintf(D_ALWAYS,"failed to create classad; bad expr = '%s'\n", line.c_str());

		if ( ! multiple) return -1; // abort

		// skip the remainder of the ad by reading until we see eof or a blank line.
		line = "";
		while ( ! line.empty() && line[0] != '\n') {
			if (feof(file))
				break;
			if ( ! readLine(line, file, false))
				break;
		}
		return -1; // abort
	}

 private:
	bool multiple;
	FILE * out;
	std::string delim;
};

void
version()
{
	printf( "%s\n%s\n", CondorVersion(), CondorPlatform() );
}

int main( int argc, char *argv[] )
{
	const char *filename=0;
	char *pool=0;
	int command=-1;
	int i;
	bool with_ack = false;
	bool allow_multiple = false;
	bool many_connections = false;

	myDistro->Init( argc, argv );
	config();

	bool use_tcp = param_boolean( "UPDATE_COLLECTOR_WITH_TCP", true );

	for( i=1; i<argc; i++ ) {
		if(!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) {
			usage(argv[0], argv[i+1] ? argv[i+1] : "cmd");
			exit(0);
		} else if(!strcmp(argv[i],"-pool")) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"-pool requires an argument.\n\n");
				usage(argv[0], NULL);
				exit(1);
			}
			pool = argv[i];
		} else if(!strncmp(argv[i],"-tcp",strlen(argv[i]))) {
			use_tcp = true;
		} else if(!strncmp(argv[i],"-udp",strlen(argv[i]))) {
			use_tcp = false;
		} else if(!strncmp(argv[i],"-multiple",strlen(argv[i]))) {
				// We don't set allow_multiple=true by default, because
				// existing users (e.g. glideinWMS) have stray blank lines
				// in the input file.
			allow_multiple = true;
		} else if(!strcmp(argv[i],"-version")) {
			version();
			exit(0);
		} else if(!strcmp(argv[i],"-debug")) {
				// dprintf to console
			dprintf_set_tool_debug("TOOL", 0);
		} else if(argv[i][0]!='-' || !strcmp(argv[i],"-")) {
			if(command==-1) {
				command = getCollectorCommandNum(argv[i]);
				if(command==-1) {
					fprintf(stderr,"Unknown command name %s\n\n",argv[i]);
					usage(argv[0], "all");
					exit(1);
				}
			} else if(!filename) {
				filename = argv[i];
			} else {
				fprintf(stderr,"Extra argument: %s\n\n",argv[i]);
				usage(argv[0], NULL);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-many-connections", strlen(argv[i]))) {
			many_connections = true;
		} else {
			fprintf(stderr,"Unknown argument: %s\n\n",argv[i]);
			usage(argv[0], NULL);
			exit(1);
		}
	}

	FILE *file;
	ClassAdList ads;
	Daemon *collector;
	Sock *sock;

	switch( command ) {
	case UPDATE_STARTD_AD_WITH_ACK:
		with_ack = true;
		break;
	}

	if( with_ack ) {
		use_tcp =  true;
	}

	if(!filename || !strcmp(filename,"-")) {
		file = stdin;
		filename = "(stdin)";
	} else {
		file = safe_fopen_wrapper_follow(filename,"r");
	}
	if(!file) {
		fprintf(stderr,"couldn't open %s: %s\n",filename,strerror(errno));
		return 1;
	}

	// create class that we can use to influence the behavior of Classad::InsertFromFile
	ToolClassAdFileParseHelper parse_helper(allow_multiple, stderr);

	for (;;) {
		ClassAd *ad = new ClassAd();
		int error;
		bool eof;
		int cAttrs = ad->InsertFromFile(file, eof, error, &parse_helper);
		if (error < 0) {
			fprintf(stderr,"couldn't parse ClassAd in %s\n", filename);
			delete ad;
			return 1;
		}
		if (cAttrs > 0) {
			ads.Insert(ad);
		} else {
			delete ad;
		}
		if (eof) {
			break;
		}
		if( !allow_multiple && ads.Length() > 0 ) {
			fprintf(stderr,"ERROR: multiple ads in %s\n", filename);
			delete ad;
			return 1;
		}
	}

	if(ads.Length() == 0) {
		fprintf(stderr,"%s is empty\n",filename);
		return 1;
	}

	CollectorList * collectors;
	if ( pool ) {
		collector = new Daemon( DT_COLLECTOR, pool, 0 );
		collectors = new CollectorList();
		collectors->append (collector);
	} else {
		collectors = CollectorList::create();
	}

	bool had_error = false;

	collectors->rewind();
	while (collectors->next(collector)) {

		dprintf(D_FULLDEBUG,"locating collector %s...\n", collector->name());

		if(!collector->locate(Daemon::LOCATE_FOR_LOOKUP)) {
			fprintf(stderr,"couldn't locate collector: %s\n",collector->error());
			had_error = true;
			continue;
		}

		dprintf(D_FULLDEBUG,"collector is %s located at %s\n",
				collector->hostname(),collector->addr());

		sock = NULL;

		ClassAd *ad;
		int success_count = 0;
		int failure_count = 0;
		ads.Rewind();
		while( (ad=ads.Next()) ) {

				// If there's no "MyAddress", generate one..
			if( !ad->Lookup( ATTR_MY_ADDRESS ) ) {
				MyString tmp;
				tmp.formatstr( "<%s:0>", my_ip_string() );
				ad->Assign( ATTR_MY_ADDRESS, tmp.Value() );
			}

			if ( use_tcp ) {
				if( !sock ) {
					sock = collector->startCommand(command,Stream::reli_sock,20);
				}
				else {
						// Use existing connection.
					sock->encode();
					sock->put(command);
				}
			} else {
					// We must open a new UDP socket each time.
				delete sock;
				sock = collector->startCommand(command,Stream::safe_sock,20);
			}

			int result = 0;
			if ( sock ) {
				result += putClassAd( sock, *ad );
				result += sock->end_of_message();
			}
			if ( result != 2 ) {
				fprintf(stderr,"failed to send classad to %s\n",collector->addr());
				had_error = true;
				failure_count++;
				delete sock;
				sock = NULL;
				continue;
			}

			if( with_ack ) {
				sock->decode();
				int ok = 0;
				if( !sock->get(ok) || !sock->end_of_message() ) {
					fprintf(stderr,"failed to get ack from %s\n",collector->addr());
					had_error = true;
					failure_count++;
					delete sock;
					sock = NULL;
					continue;
				}

					// ack protocol does not allow for multiple updates,
					// so close the socket now
				delete sock;
				sock = NULL;
			}

			success_count++;
			if (many_connections) {
				sock = NULL;
			}
		}
		if( sock ) {
			CondorVersionInfo const *ver = sock->get_peer_version();
			if( !ver || ver->built_since_version(7,7,3) ) {
					// graceful hangup so the collector knows we are done
				sock->encode();
				int hangup_cmd = DC_NOP;
				sock->put(hangup_cmd);
				sock->end_of_message();
			}

			delete sock;
			sock = NULL;
		}

		printf("Sent %d of %d ad%s to %s.\n",
			   success_count,
			   success_count + failure_count,
			   success_count+failure_count == 1 ? "" : "s",
			   collector->name());
	}

	if (many_connections) {
		sleep(3600);
	}
	delete collectors;

	return (had_error)?1:0;
}
<commit_msg>Fix double-delete in condor_advertise<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

#include "condor_common.h"
#include "condor_classad.h"
#include "condor_version.h"
#include "condor_debug.h"
#include "condor_config.h"
#include "command_strings.h"
#include "daemon.h"
#include "safe_sock.h"
#include "condor_distribution.h"
#include "daemon_list.h"
#include "dc_collector.h"
#include "my_hostname.h"

void
usage( const char *cmd , const char * opt)
{
	fprintf(stderr,"Usage: %s [options] <update-command> [<classad-filename>]\n",cmd);
	fprintf(stderr,"Where options are:\n");
	fprintf(stderr,"    -help             Display options\n");
	fprintf(stderr,"    -version          Display Condor version\n");
	fprintf(stderr,"    -pool <hostname>  Use this central manager\n");
	fprintf(stderr,"    -debug            Show extra debugging info\n");
	fprintf(stderr,"    -tcp              Ship classad via TCP (default is UDP)\n");
	fprintf(stderr,"    -multiple         Publish multiple ads, separated by blank lines\n");

	if (opt && ( !strcmp(opt,"all") || !strcmp(opt,"cmd"))) {
		fprintf(stderr,"\nAnd <update-command> is one of:\n");
		static const char * const aPre[] = {"UPDATE_", "MERGE_", "INVALIDATE_"};
		for (int jj = 0; jj < (int)COUNTOF(aPre); ++jj) {
			for (int id = UPDATE_STARTD_AD; id < UPDATE_STARTD_AD + 100; ++id) {
				const char * cmdname = getCollectorCommandString(id);
				if (cmdname && starts_with(cmdname, aPre[jj])) {
					fprintf(stderr,"    %s\n",cmdname);
				}
			}
		}
	}

	fprintf(stderr, "\nIf <classad-filename> does not exist or is -, classads will be read from standard input\n");
	fprintf(stderr,"Example: %s -debug UPDATE_STORAGE_AD adfile\n\n",cmd);
}

// this class is used to help parse one or more ClassAd's from a FILE*
class ToolClassAdFileParseHelper : public ClassAdFileParseHelper
{
 public:
	// Some compilers whine when you have virtual methods but not an
	// explicit virtual destructor
	virtual ~ToolClassAdFileParseHelper() {}
	ToolClassAdFileParseHelper(bool multi, FILE* errout) : multiple(multi), out(errout) {};

	// return 0 to skip (is_comment), 1 to parse line, 2 for end-of-classad, -1 for abort
	virtual int PreParse(std::string & line, ClassAd & /*ad*/, FILE* /*file*/) {
		// if this line matches the ad delimitor, tell the parser to stop parsing
		if (multiple && (line.empty() || (line[0] == '\n')))
			return 2; //end-of-classad

		// check for blank lines or lines whose first character is #
		// tell the parse to skip those lines, otherwise tell the parser to
		// parse the line.
		for (size_t ix = 0; ix < line.size(); ++ix) {
			if (line[ix] == '#' || line[ix] == '\n')
				return 0; // skip this line, but don't stop parsing.
			if (line[ix] != ' ' && line[ix] != '\t')
				return 1; // parse this line
		}
		return 1; // parse this line.
	}

	// return 0 to skip and continue, 1 to re-parse line, 2 to quit parsing with success, -1 to abort parsing.
	virtual int OnParseError(std::string & line, ClassAd & /*ad*/, FILE* file) {
		// print out where we barfed to the log file
		dprintf(D_ALWAYS,"failed to create classad; bad expr = '%s'\n", line.c_str());

		if ( ! multiple) return -1; // abort

		// skip the remainder of the ad by reading until we see eof or a blank line.
		line = "";
		while ( ! line.empty() && line[0] != '\n') {
			if (feof(file))
				break;
			if ( ! readLine(line, file, false))
				break;
		}
		return -1; // abort
	}

 private:
	bool multiple;
	FILE * out;
	std::string delim;
};

void
version()
{
	printf( "%s\n%s\n", CondorVersion(), CondorPlatform() );
}

int main( int argc, char *argv[] )
{
	const char *filename=0;
	char *pool=0;
	int command=-1;
	int i;
	bool with_ack = false;
	bool allow_multiple = false;
	bool many_connections = false;

	myDistro->Init( argc, argv );
	config();

	bool use_tcp = param_boolean( "UPDATE_COLLECTOR_WITH_TCP", true );

	for( i=1; i<argc; i++ ) {
		if(!strcmp(argv[i],"-help") || !strcmp(argv[i],"--help")) {
			usage(argv[0], argv[i+1] ? argv[i+1] : "cmd");
			exit(0);
		} else if(!strcmp(argv[i],"-pool")) {
			i++;
			if(!argv[i]) {
				fprintf(stderr,"-pool requires an argument.\n\n");
				usage(argv[0], NULL);
				exit(1);
			}
			pool = argv[i];
		} else if(!strncmp(argv[i],"-tcp",strlen(argv[i]))) {
			use_tcp = true;
		} else if(!strncmp(argv[i],"-udp",strlen(argv[i]))) {
			use_tcp = false;
		} else if(!strncmp(argv[i],"-multiple",strlen(argv[i]))) {
				// We don't set allow_multiple=true by default, because
				// existing users (e.g. glideinWMS) have stray blank lines
				// in the input file.
			allow_multiple = true;
		} else if(!strcmp(argv[i],"-version")) {
			version();
			exit(0);
		} else if(!strcmp(argv[i],"-debug")) {
				// dprintf to console
			dprintf_set_tool_debug("TOOL", 0);
		} else if(argv[i][0]!='-' || !strcmp(argv[i],"-")) {
			if(command==-1) {
				command = getCollectorCommandNum(argv[i]);
				if(command==-1) {
					fprintf(stderr,"Unknown command name %s\n\n",argv[i]);
					usage(argv[0], "all");
					exit(1);
				}
			} else if(!filename) {
				filename = argv[i];
			} else {
				fprintf(stderr,"Extra argument: %s\n\n",argv[i]);
				usage(argv[0], NULL);
				exit(1);
			}
		} else if(!strncmp(argv[i],"-many-connections", strlen(argv[i]))) {
			many_connections = true;
		} else {
			fprintf(stderr,"Unknown argument: %s\n\n",argv[i]);
			usage(argv[0], NULL);
			exit(1);
		}
	}

	FILE *file;
	ClassAdList ads;
	Daemon *collector;
	Sock *sock;

	switch( command ) {
	case UPDATE_STARTD_AD_WITH_ACK:
		with_ack = true;
		break;
	}

	if( with_ack ) {
		use_tcp =  true;
	}

	if(!filename || !strcmp(filename,"-")) {
		file = stdin;
		filename = "(stdin)";
	} else {
		file = safe_fopen_wrapper_follow(filename,"r");
	}
	if(!file) {
		fprintf(stderr,"couldn't open %s: %s\n",filename,strerror(errno));
		return 1;
	}

	// create class that we can use to influence the behavior of Classad::InsertFromFile
	ToolClassAdFileParseHelper parse_helper(allow_multiple, stderr);

	for (;;) {
		ClassAd *ad = new ClassAd();
		int error;
		bool eof;
		int cAttrs = ad->InsertFromFile(file, eof, error, &parse_helper);
		if (error < 0) {
			fprintf(stderr,"couldn't parse ClassAd in %s\n", filename);
			delete ad;
			return 1;
		}
		if (cAttrs > 0) {
			ads.Insert(ad);
		} else {
			delete ad;
			ad = 0; // so we don't double delete it
		}
		if (eof) {
			break;
		}
		if( !allow_multiple && ads.Length() > 0 ) {
			fprintf(stderr,"ERROR: multiple ads in %s\n", filename);
			delete ad;
			return 1;
		}
	}

	if(ads.Length() == 0) {
		fprintf(stderr,"%s is empty\n",filename);
		return 1;
	}

	CollectorList * collectors;
	if ( pool ) {
		collector = new Daemon( DT_COLLECTOR, pool, 0 );
		collectors = new CollectorList();
		collectors->append (collector);
	} else {
		collectors = CollectorList::create();
	}

	bool had_error = false;

	collectors->rewind();
	while (collectors->next(collector)) {

		dprintf(D_FULLDEBUG,"locating collector %s...\n", collector->name());

		if(!collector->locate(Daemon::LOCATE_FOR_LOOKUP)) {
			fprintf(stderr,"couldn't locate collector: %s\n",collector->error());
			had_error = true;
			continue;
		}

		dprintf(D_FULLDEBUG,"collector is %s located at %s\n",
				collector->hostname(),collector->addr());

		sock = NULL;

		ClassAd *ad;
		int success_count = 0;
		int failure_count = 0;
		ads.Rewind();
		while( (ad=ads.Next()) ) {

				// If there's no "MyAddress", generate one..
			if( !ad->Lookup( ATTR_MY_ADDRESS ) ) {
				MyString tmp;
				tmp.formatstr( "<%s:0>", my_ip_string() );
				ad->Assign( ATTR_MY_ADDRESS, tmp.Value() );
			}

			if ( use_tcp ) {
				if( !sock ) {
					sock = collector->startCommand(command,Stream::reli_sock,20);
				}
				else {
						// Use existing connection.
					sock->encode();
					sock->put(command);
				}
			} else {
					// We must open a new UDP socket each time.
				delete sock;
				sock = collector->startCommand(command,Stream::safe_sock,20);
			}

			int result = 0;
			if ( sock ) {
				result += putClassAd( sock, *ad );
				result += sock->end_of_message();
			}
			if ( result != 2 ) {
				fprintf(stderr,"failed to send classad to %s\n",collector->addr());
				had_error = true;
				failure_count++;
				delete sock;
				sock = NULL;
				continue;
			}

			if( with_ack ) {
				sock->decode();
				int ok = 0;
				if( !sock->get(ok) || !sock->end_of_message() ) {
					fprintf(stderr,"failed to get ack from %s\n",collector->addr());
					had_error = true;
					failure_count++;
					delete sock;
					sock = NULL;
					continue;
				}

					// ack protocol does not allow for multiple updates,
					// so close the socket now
				delete sock;
				sock = NULL;
			}

			success_count++;
			if (many_connections) {
				sock = NULL;
			}
		}
		if( sock ) {
			CondorVersionInfo const *ver = sock->get_peer_version();
			if( !ver || ver->built_since_version(7,7,3) ) {
					// graceful hangup so the collector knows we are done
				sock->encode();
				int hangup_cmd = DC_NOP;
				sock->put(hangup_cmd);
				sock->end_of_message();
			}

			delete sock;
			sock = NULL;
		}

		printf("Sent %d of %d ad%s to %s.\n",
			   success_count,
			   success_count + failure_count,
			   success_count+failure_count == 1 ? "" : "s",
			   collector->name());
	}

	if (many_connections) {
		sleep(3600);
	}
	delete collectors;

	return (had_error)?1:0;
}
<|endoftext|>


<commit_before>#include "dynet/dynet.h"

#include "dynet/exec.h"
#include "dynet/nodes.h"
#include "dynet/param-nodes.h"
#include "dynet/aligned-mem-pool.h"
#include "dynet/dynet-helper.h"
#include "dynet/expr.h"

using namespace std;

namespace dynet {

float* kSCALAR_MINUSONE;
float* kSCALAR_ONE;
float* kSCALAR_ZERO;
int n_hgs = 0;

Node::~Node() {}
size_t Node::aux_storage_size() const { return 0; }

// perform the forward/backward passes in one or multiple calls
// TODO: This is a lot of code for something simple. Can it be shortened?
void Node::forward(const std::vector<const Tensor*>& xs,
                   Tensor& fx) const {
  if(this->supports_multibatch() || fx.d.batch_elems() == 1) {
    forward_impl(xs, fx);
  } else {
    size_t i;
    std::vector<Tensor> xs_elems(xs.size());
    std::vector<const Tensor*> xs_ptrs(xs.size());
    std::vector<size_t> xs_sizes(xs.size());
    for(i = 0; i < xs.size(); ++i) {
      xs_elems[i] = xs[i]->batch_elem(0);
      xs_ptrs[i] = &xs_elems[i];
      xs_sizes[i] = xs_elems[i].d.size();
    }
    Tensor fx_elem(fx.batch_elem(0));
    size_t fx_size = fx_elem.d.size();
    forward_impl(xs_ptrs, fx_elem);
    for(unsigned b = 1; b < fx.d.batch_elems(); ++b) {
      for(i = 0; i < xs.size(); ++i) xs_elems[i].v += xs_sizes[i];
      fx_elem.v += fx_size;
      forward_impl(xs_ptrs, fx_elem);
    }
  }
}
void Node::backward(const std::vector<const Tensor*>& xs,
                    const Tensor& fx,
                    const Tensor& dEdf,
                    unsigned xs_i,
                    Tensor& dEdxi) const {
  if(this->supports_multibatch() || fx.d.batch_elems() == 1) {
    backward_impl(xs, fx, dEdf, xs_i, dEdxi);
  } else {
    size_t i;
    std::vector<Tensor> xs_elems(xs.size());
    std::vector<const Tensor*> xs_ptrs(xs.size());
    std::vector<size_t> xs_sizes(xs.size());
    for(i = 0; i < xs.size(); ++i) {
      xs_elems[i] = xs[i]->batch_elem(0);
      xs_ptrs[i] = &xs_elems[i];
      xs_sizes[i] = xs_elems[i].d.size();
    }
    Tensor fx_elem(fx.batch_elem(0));
    size_t fx_size = fx_elem.d.size();
    Tensor dEdf_elem(dEdf.batch_elem(0));
    size_t dEdf_size = dEdf_elem.d.size();
    Tensor dEdxi_elem(dEdxi.batch_elem(0));
    size_t dEdxi_size = dEdxi_elem.d.size();
    backward_impl(xs_ptrs, fx_elem, dEdf_elem, xs_i, dEdxi_elem);
    for(unsigned b = 1; b < fx.d.batch_elems(); ++b) {
      for(i = 0; i < xs.size(); ++i) xs_elems[i].v += xs_sizes[i];
      fx_elem.v += fx_size;
      dEdf_elem.v += dEdf_size;
      dEdxi_elem.v += dEdxi_size;
      backward_impl(xs_ptrs, fx_elem, dEdf_elem, xs_i, dEdxi_elem);
    }
  }
}

ComputationGraph::ComputationGraph() :
  ee(new SimpleExecutionEngine(*this)) {
  ++n_hgs;
  if (n_hgs > 1) {
    cerr << "Memory allocator assumes only a single ComputationGraph at a time.\n";
    throw std::runtime_error("Attempted to create >1 CG");
  }
}

ComputationGraph::~ComputationGraph() {
  this->clear();
  delete ee;
  --n_hgs;
}

void ComputationGraph::clear() {
  parameter_nodes.clear();
  for (auto n : nodes) delete n;
  nodes.clear();
}

CGCheckpoint ComputationGraph::_get_checkpoint() {
    CGCheckpoint p;
    p.device_mem_checkpoint = default_device->mark(this);
    p.node_idx = nodes.size();
    p.par_node_idx = parameter_nodes.size();
    return p;
}

void ComputationGraph::_revert(CGCheckpoint p) {
    default_device->revert(p.device_mem_checkpoint);
    // clear all nodes at position >= p.node_idx
    if ((int)nodes.size() > p.node_idx) {
        nodes.resize(p.node_idx); // TODO verify deletion of nodes.
        ee->invalidate(p.node_idx-1); // clear precomputed forward values
    }
    // clear all parameter nodes at position >= p.par_node_idx
    if ((int)parameter_nodes.size() > p.par_node_idx) {
        parameter_nodes.resize(p.par_node_idx);
    }
}

void ComputationGraph::checkpoint() {
    checkpoints.push_back(_get_checkpoint());
}

void ComputationGraph::revert() {
    if (checkpoints.size() == 0) return;
    _revert(checkpoints.back());
    checkpoints.pop_back();
}

VariableIndex ComputationGraph::add_input(real s) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new ScalarInputNode(s));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const real* ps) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new ScalarInputNode(ps));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<float>& pm) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new InputNode(d, pm));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<float>* pm) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new InputNode(d, pm));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<unsigned int>& ids, const vector<float>& data, float defdata) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new SparseInputNode(d, ids, data, defdata));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_parameters(Parameter p) {
  VariableIndex new_node_index(nodes.size());
  ParameterNode* new_node = new ParameterNode(p);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_parameters(Parameter p) {
  VariableIndex new_node_index(nodes.size());
  ConstParameterNode* new_node = new ConstParameterNode(p);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const unsigned* pindex) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, pindex);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, unsigned index) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, index);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const std::vector<unsigned>& indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const std::vector<unsigned>* indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const unsigned* pindex) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, pindex);
  // get rid of the following in favor of using parameter_nodes to see the needs_derivative
  // expression
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, unsigned index) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, index);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const std::vector<unsigned>& indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const std::vector<unsigned>* indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

// factory function should call this right after creating a new node object
// to set its dimensions properly
void ComputationGraph::set_dim_for_new_node(const VariableIndex& i) {
  Node* node = nodes[i];
  vector<Dim> xds(node->arity());
  unsigned ai = 0;
  for (VariableIndex arg : node->args) {
    xds[ai] = nodes[arg]->dim;
    ++ai;
  }
  node->dim = node->dim_forward(xds);
}

const Tensor& ComputationGraph::incremental_forward(const expr::Expression& last) { return ee->incremental_forward(last.i); }
const Tensor& ComputationGraph::forward(const expr::Expression& last) { return ee->forward(last.i); }
const Tensor& ComputationGraph::incremental_forward(VariableIndex last) { return ee->incremental_forward(last); }
const Tensor& ComputationGraph::forward(VariableIndex last) { return ee->forward(last); }
const Tensor& ComputationGraph::get_value(VariableIndex i) { return ee->get_value(i); }
const Tensor& ComputationGraph::get_value(const expr::Expression& e) { return this->get_value(e.i); }
void ComputationGraph::invalidate() { ee->invalidate(); }
void ComputationGraph::backward(const expr::Expression& last) { ee->backward(last.i); }
void ComputationGraph::backward(VariableIndex i) { ee->backward(i); }

void ComputationGraph::print_graphviz() const {
  cerr << "digraph G {\n  rankdir=LR;\n  nodesep=.05;\n";
  unsigned nc = 0;
  for (auto node : nodes) {
    vector<string> var_names;
    for (auto arg : node->args)
      var_names.push_back(string("v") + to_string((unsigned)arg));
    cerr << "  N" << nc << " [label=\"v" << nc << " = "
         << node->as_string(var_names) << "\"];\n";
    for (auto arg : node->args)
      cerr << "  N" << ((unsigned)arg) << " -> N" << nc << ";\n";
    ++nc;
  }
  cerr << "}\n";
}

}  // namespace dynet

<commit_msg>Fixed broadcasting in new batching impl<commit_after>#include "dynet/dynet.h"

#include "dynet/exec.h"
#include "dynet/nodes.h"
#include "dynet/param-nodes.h"
#include "dynet/aligned-mem-pool.h"
#include "dynet/dynet-helper.h"
#include "dynet/expr.h"

using namespace std;

namespace dynet {

float* kSCALAR_MINUSONE;
float* kSCALAR_ONE;
float* kSCALAR_ZERO;
int n_hgs = 0;

Node::~Node() {}
size_t Node::aux_storage_size() const { return 0; }

// perform the forward/backward passes in one or multiple calls
// TODO: This is a lot of code for something simple. Can it be shortened?
void Node::forward(const std::vector<const Tensor*>& xs,
                   Tensor& fx) const {
  if(this->supports_multibatch() || fx.d.batch_elems() == 1) {
    forward_impl(xs, fx);
  } else {
    size_t i;
    std::vector<Tensor> xs_elems(xs.size());
    std::vector<const Tensor*> xs_ptrs(xs.size());
    std::vector<size_t> xs_sizes(xs.size());
    for(i = 0; i < xs.size(); ++i) {
      xs_elems[i] = xs[i]->batch_elem(0);
      xs_ptrs[i] = &xs_elems[i];
      xs_sizes[i] = xs_elems[i].d.size();
    }
    Tensor fx_elem(fx.batch_elem(0));
    size_t fx_size = fx_elem.d.size();
    forward_impl(xs_ptrs, fx_elem);
    for(unsigned b = 1; b < fx.d.batch_elems(); ++b) {
      for(i = 0; i < xs.size(); ++i)
        if(xs_elems[i].d.bd > 1)
          xs_elems[i].v += xs_sizes[i];
      fx_elem.v += fx_size;
      forward_impl(xs_ptrs, fx_elem);
    }
  }
}
void Node::backward(const std::vector<const Tensor*>& xs,
                    const Tensor& fx,
                    const Tensor& dEdf,
                    unsigned xs_i,
                    Tensor& dEdxi) const {
  if(this->supports_multibatch() || fx.d.batch_elems() == 1) {
    backward_impl(xs, fx, dEdf, xs_i, dEdxi);
  } else {
    size_t i;
    std::vector<Tensor> xs_elems(xs.size());
    std::vector<const Tensor*> xs_ptrs(xs.size());
    std::vector<size_t> xs_sizes(xs.size());
    for(i = 0; i < xs.size(); ++i) {
      xs_elems[i] = xs[i]->batch_elem(0);
      xs_ptrs[i] = &xs_elems[i];
      xs_sizes[i] = xs_elems[i].d.size();
    }
    Tensor fx_elem(fx.batch_elem(0));
    size_t fx_size = fx_elem.d.size();
    Tensor dEdf_elem(dEdf.batch_elem(0));
    size_t dEdf_size = dEdf_elem.d.size();
    Tensor dEdxi_elem(dEdxi.batch_elem(0));
    size_t dEdxi_size = dEdxi_elem.d.size();
    backward_impl(xs_ptrs, fx_elem, dEdf_elem, xs_i, dEdxi_elem);
    for(unsigned b = 1; b < fx.d.batch_elems(); ++b) {
      for(i = 0; i < xs.size(); ++i)
        if(xs_elems[i].d.bd > 1)
          xs_elems[i].v += xs_sizes[i];
      fx_elem.v += fx_size;
      dEdf_elem.v += dEdf_size;
      if(dEdxi_elem.d.bd > 1)
        dEdxi_elem.v += dEdxi_size;
      backward_impl(xs_ptrs, fx_elem, dEdf_elem, xs_i, dEdxi_elem);
    }
  }
}

ComputationGraph::ComputationGraph() :
  ee(new SimpleExecutionEngine(*this)) {
  ++n_hgs;
  if (n_hgs > 1) {
    cerr << "Memory allocator assumes only a single ComputationGraph at a time.\n";
    throw std::runtime_error("Attempted to create >1 CG");
  }
}

ComputationGraph::~ComputationGraph() {
  this->clear();
  delete ee;
  --n_hgs;
}

void ComputationGraph::clear() {
  parameter_nodes.clear();
  for (auto n : nodes) delete n;
  nodes.clear();
}

CGCheckpoint ComputationGraph::_get_checkpoint() {
    CGCheckpoint p;
    p.device_mem_checkpoint = default_device->mark(this);
    p.node_idx = nodes.size();
    p.par_node_idx = parameter_nodes.size();
    return p;
}

void ComputationGraph::_revert(CGCheckpoint p) {
    default_device->revert(p.device_mem_checkpoint);
    // clear all nodes at position >= p.node_idx
    if ((int)nodes.size() > p.node_idx) {
        nodes.resize(p.node_idx); // TODO verify deletion of nodes.
        ee->invalidate(p.node_idx-1); // clear precomputed forward values
    }
    // clear all parameter nodes at position >= p.par_node_idx
    if ((int)parameter_nodes.size() > p.par_node_idx) {
        parameter_nodes.resize(p.par_node_idx);
    }
}

void ComputationGraph::checkpoint() {
    checkpoints.push_back(_get_checkpoint());
}

void ComputationGraph::revert() {
    if (checkpoints.size() == 0) return;
    _revert(checkpoints.back());
    checkpoints.pop_back();
}

VariableIndex ComputationGraph::add_input(real s) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new ScalarInputNode(s));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const real* ps) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new ScalarInputNode(ps));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<float>& pm) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new InputNode(d, pm));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<float>* pm) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new InputNode(d, pm));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_input(const Dim& d, const vector<unsigned int>& ids, const vector<float>& data, float defdata) {
  VariableIndex new_node_index(nodes.size());
  nodes.push_back(new SparseInputNode(d, ids, data, defdata));
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_parameters(Parameter p) {
  VariableIndex new_node_index(nodes.size());
  ParameterNode* new_node = new ParameterNode(p);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_parameters(Parameter p) {
  VariableIndex new_node_index(nodes.size());
  ConstParameterNode* new_node = new ConstParameterNode(p);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const unsigned* pindex) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, pindex);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, unsigned index) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, index);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const std::vector<unsigned>& indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_lookup(LookupParameter p, const std::vector<unsigned>* indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  parameter_nodes.push_back(new_node_index);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const unsigned* pindex) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, pindex);
  // get rid of the following in favor of using parameter_nodes to see the needs_derivative
  // expression
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, unsigned index) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, index);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const std::vector<unsigned>& indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

VariableIndex ComputationGraph::add_const_lookup(LookupParameter p, const std::vector<unsigned>* indices) {
  VariableIndex new_node_index(nodes.size());
  LookupNode* new_node = new LookupNode(p, indices);
  nodes.push_back(new_node);
  set_dim_for_new_node(new_node_index);
  return new_node_index;
}

// factory function should call this right after creating a new node object
// to set its dimensions properly
void ComputationGraph::set_dim_for_new_node(const VariableIndex& i) {
  Node* node = nodes[i];
  vector<Dim> xds(node->arity());
  unsigned ai = 0;
  for (VariableIndex arg : node->args) {
    xds[ai] = nodes[arg]->dim;
    ++ai;
  }
  node->dim = node->dim_forward(xds);
}

const Tensor& ComputationGraph::incremental_forward(const expr::Expression& last) { return ee->incremental_forward(last.i); }
const Tensor& ComputationGraph::forward(const expr::Expression& last) { return ee->forward(last.i); }
const Tensor& ComputationGraph::incremental_forward(VariableIndex last) { return ee->incremental_forward(last); }
const Tensor& ComputationGraph::forward(VariableIndex last) { return ee->forward(last); }
const Tensor& ComputationGraph::get_value(VariableIndex i) { return ee->get_value(i); }
const Tensor& ComputationGraph::get_value(const expr::Expression& e) { return this->get_value(e.i); }
void ComputationGraph::invalidate() { ee->invalidate(); }
void ComputationGraph::backward(const expr::Expression& last) { ee->backward(last.i); }
void ComputationGraph::backward(VariableIndex i) { ee->backward(i); }

void ComputationGraph::print_graphviz() const {
  cerr << "digraph G {\n  rankdir=LR;\n  nodesep=.05;\n";
  unsigned nc = 0;
  for (auto node : nodes) {
    vector<string> var_names;
    for (auto arg : node->args)
      var_names.push_back(string("v") + to_string((unsigned)arg));
    cerr << "  N" << nc << " [label=\"v" << nc << " = "
         << node->as_string(var_names) << "\"];\n";
    for (auto arg : node->args)
      cerr << "  N" << ((unsigned)arg) << " -> N" << nc << ";\n";
    ++nc;
  }
  cerr << "}\n";
}

}  // namespace dynet

<|endoftext|>


<commit_before>#ifndef __PART_DATA_HPP
#define __PART_DATA_HPP

#include <valarray>

#define FLOAT_TYPE float
#define N_TYPES 6

//Class to generate a regular grid of particle positions on demand.
class part_grid
{
    public:
        /* Construct the particle grid parameters.
         * NumPart should be the number of particles per side; the cube root of the total number of particles.
         * Masses are the mass ratios of the different particle species, for making sure no two types share the same position
         * Box is the boxsize.*/
        part_grid(const int NumPart[], const double Masses[], const double Box);
        /* Get the position of a particle at some index on a grid.
         * We want to return:
         * size_t index = k + j* NumPart + i * NumPart**2
         * Pos[0] = i /NumPart * pspace[type]
         * Pos[1] = j /NumPart * pspace[type]
         * Pos[2] = k /NumPart * pspace[type]
         * In other words, k is fast, j is medium, i is slow.
         */
        double Pos(size_t index, int axis, int type);
        //Get number of particles
        int GetNumPart(int type);
        //Get box size
        inline double GetBox(){
            return Box;
        }
    private:
        const std::valarray<int> NumPart;
        const double Box;
        double pspace[N_TYPES];
        double shift[N_TYPES][3];
};

//Class to store the Zeldovich and 2LPT displacements for a particle type.
class lpt_data
{
    public:
        //Again, NumPart is the cube root of the particle number!
        lpt_data(const int NumPart, bool twolpt=true): vel_prefac(0), vel_prefac2(0), twolpt(twolpt),Vel_data(3*NumPart*NumPart*NumPart),Vel_2_data(twolpt*3*NumPart*NumPart*NumPart)
        {}
        //Note Vel_2_data takes zero space if !twolpt
        inline void SetVel(FLOAT_TYPE Vel_in, size_t index, int axis){
                Vel_data[3*index+axis] = Vel_in;
                return;
        }
        inline void Set2Vel(FLOAT_TYPE Vel_in, size_t index, int axis){
                Vel_2_data[3*index+axis] = Vel_in;
                return;
        }
        inline double GetVel(size_t index, int axis)
        {
            double vel = vel_prefac*Vel_data[3*index+axis];
            if(twolpt)
                vel += vel_prefac2*Vel_2_data[3*index+axis];
            return vel;
        }
        inline double GetDisp(size_t index, int axis)
        {
            double disp = Vel_data[3*index+axis];
            if(twolpt)
                disp -= 3./7.*Vel_2_data[3*index+axis];
            return disp;
        }
        inline size_t GetNumPart(){
                return Vel_data.size()/3;
        }
        void SetVelPrefac(double vel_prefac_i, double vel_prefac2_i)
        {
            vel_prefac = vel_prefac_i;
            vel_prefac2 = vel_prefac2_i;
        }
    private:
        double vel_prefac;
        double vel_prefac2;
        const bool twolpt;
        std::valarray <FLOAT_TYPE> Vel_data;
        std::valarray <FLOAT_TYPE> Vel_2_data;
};

#endif

<commit_msg>Explicitly cast to a wider integer type to avoid possible overflows<commit_after>#ifndef __PART_DATA_HPP
#define __PART_DATA_HPP

#include <valarray>

#define FLOAT_TYPE float
#define N_TYPES 6

//Class to generate a regular grid of particle positions on demand.
class part_grid
{
    public:
        /* Construct the particle grid parameters.
         * NumPart should be the number of particles per side; the cube root of the total number of particles.
         * Masses are the mass ratios of the different particle species, for making sure no two types share the same position
         * Box is the boxsize.*/
        part_grid(const int NumPart[], const double Masses[], const double Box);
        /* Get the position of a particle at some index on a grid.
         * We want to return:
         * size_t index = k + j* NumPart + i * NumPart**2
         * Pos[0] = i /NumPart * pspace[type]
         * Pos[1] = j /NumPart * pspace[type]
         * Pos[2] = k /NumPart * pspace[type]
         * In other words, k is fast, j is medium, i is slow.
         */
        double Pos(size_t index, int axis, int type);
        //Get number of particles
        int GetNumPart(int type);
        //Get box size
        inline double GetBox(){
            return Box;
        }
    private:
        const std::valarray<int> NumPart;
        const double Box;
        double pspace[N_TYPES];
        double shift[N_TYPES][3];
};

//Class to store the Zeldovich and 2LPT displacements for a particle type.
class lpt_data
{
    public:
        //Again, NumPart is the cube root of the particle number!
        lpt_data(const int NumPart, bool twolpt=true): vel_prefac(0), vel_prefac2(0), twolpt(twolpt),Vel_data(3*static_cast<size_t>(NumPart)*NumPart*NumPart),Vel_2_data(twolpt*3*static_cast<size_t>(NumPart)*NumPart*NumPart)
        {}
        //Note Vel_2_data takes zero space if !twolpt
        inline void SetVel(FLOAT_TYPE Vel_in, size_t index, int axis){
                Vel_data[3*index+axis] = Vel_in;
                return;
        }
        inline void Set2Vel(FLOAT_TYPE Vel_in, size_t index, int axis){
                Vel_2_data[3*index+axis] = Vel_in;
                return;
        }
        inline double GetVel(size_t index, int axis)
        {
            double vel = vel_prefac*Vel_data[3*index+axis];
            if(twolpt)
                vel += vel_prefac2*Vel_2_data[3*index+axis];
            return vel;
        }
        inline double GetDisp(size_t index, int axis)
        {
            double disp = Vel_data[3*index+axis];
            if(twolpt)
                disp -= 3./7.*Vel_2_data[3*index+axis];
            return disp;
        }
        inline size_t GetNumPart(){
                return Vel_data.size()/3;
        }
        void SetVelPrefac(double vel_prefac_i, double vel_prefac2_i)
        {
            vel_prefac = vel_prefac_i;
            vel_prefac2 = vel_prefac2_i;
        }
    private:
        double vel_prefac;
        double vel_prefac2;
        const bool twolpt;
        std::valarray <FLOAT_TYPE> Vel_data;
        std::valarray <FLOAT_TYPE> Vel_2_data;
};

#endif

<|endoftext|>


<commit_before>#ifndef GRAPHICSDEVICE_HPP_INCLUDED
#define GRAPHICSDEVICE_HPP_INCLUDED

#include "graphicsresource.hpp"
#include "vertexattribute.hpp"

#include <string>
#include <vector>

namespace gst
{
    class Color;
    class Image;
    class Resolution;
    class ShadowedData;
    class Texture;
    class Texture2D;
    class TextureCube;
    class Viewport;

    enum class AttachmentType;
    enum class AttachmentPoint;
    enum class BlendMode;
    enum class BufferTarget;
    enum class CubeFace;
    enum class CullFace;
    enum class DataUsage;
    enum class DrawMode;
    enum class PixelFormat;
    enum class RenderbufferFormat;
    enum class ShaderType;
    enum class TextureFormat;
    enum class TextureTarget;

    // The responsibility of this class is to interact with a graphics card.
    class GraphicsDevice {
    public:
        virtual ~GraphicsDevice() = default;

        // Clear buffers to present values.
        virtual void clear(bool color, bool depth) = 0;

        // Set clear values for color buffers.
        virtual void set_clear_color(Color const & clear_color) = 0;
        // Set blend mode enabled/disabled with appropiate blend function.
        virtual void set_blend_mode(BlendMode blend_mode) = 0;
        // Set faces that can be culled.
        virtual void set_cull_face(CullFace cull_face) = 0;
        // Set depth mask enabled/disabled.
        virtual void set_depth_mask(bool depth_mask) = 0;
        // Set depth test enabled/disabled.
        virtual void set_depth_test(bool depth_test) = 0;
        // Set viewport.
        virtual void set_viewport(Viewport const & viewport) = 0;

        // Return new shader object.
        virtual ResourceName create_shader(ShaderType type) = 0;
        // Destroy shader object.
        virtual void destroy_shader(ResourceName name) = 0;
        // Compile shader from specified source.
        virtual void compile_shader(ResourceName name, std::string const & source) = 0;
        // Return status from last compile operation.
        virtual bool get_compile_status(ResourceName name) = 0;
        // Return error message from last compile operation.
        virtual std::string get_compile_error(ResourceName name) = 0;

        // Return new program object.
        virtual ResourceName create_program() = 0;
        // Destroy program object.
        virtual void destroy_program(ResourceName name) = 0;
        // Attach specified shader object to specified program object.
        virtual void attach_shader(ResourceName program_name, ResourceName shader_name) = 0;
        // Attach specified shader object to specified program object.
        virtual void detach_shader(ResourceName program_name, ResourceName shader_name) = 0;
        // Link program object.
        virtual void link_program(ResourceName name) = 0;
        // Return status from last link operation.
        virtual bool get_link_status(ResourceName name) = 0;
        // Return error message from last compile operation.
        virtual std::string get_link_error(ResourceName name) = 0;
        // Bind vertex attribute index with a named attribute variable.
        virtual void bind_attribute_location(ResourceName program_name, int index, std::string const & name) = 0;
        // Return uniform location from specified name.
        virtual int get_uniform_location(ResourceName program_name, std::string const & name) = 0;
        // Modify value of uniform.
        virtual void uniform(int location, ShadowedData const & data) = 0;
        // Install specified program object as part of current rendering state.
        virtual void use_program(ResourceName name) = 0;

        // Return new buffer object.
        virtual ResourceName create_buffer() = 0;
        // Destroy buffer object.
        virtual void destroy_buffer(ResourceName name) = 0;
        // Bind buffer object.
        virtual void bind_buffer(ResourceName name, BufferTarget target) = 0;
        // Buffer data to current bound buffer object.
        virtual void buffer_data(BufferTarget target, ShadowedData const & data, DataUsage usage) = 0;

        // Return new vertex array object.
        virtual ResourceName create_vertex_array() = 0;
        // Destroy vertex array object.
        virtual void destroy_vertex_array(ResourceName name) = 0;
        // Bind vertex array object.
        virtual void bind_vertex_array(ResourceName name) = 0;
        // Render primitives from stored array data.
        virtual void draw_arrays(DrawMode mode, int first, int count) = 0;
        // Render primitives from stored array data.
        virtual void draw_elements(DrawMode mode, int count) = 0;
        // Enable and define generic vertex attribute.
        virtual void enable_vertex_attribute(VertexAttribute const & attribute) = 0;

        // Return new renderbuffer object.
        virtual ResourceName create_renderbuffer() = 0;
        // Destroy renderbuffer object.
        virtual void destroy_renderbuffer(ResourceName name) = 0;
        // Bind renderbuffer object.
        virtual void bind_renderbuffer(ResourceName name) = 0;
        // Establish data storage of specified format and dimensions for renderbuffer objects image.
        virtual void renderbuffer_storage(Resolution size, RenderbufferFormat format) = 0;

        // Create new texture object.
        virtual ResourceName create_texture() = 0;
        // Destroy texture object.
        virtual void destroy_texture(ResourceName name) = 0;
        // Bind texture object.
        virtual void bind_texture(ResourceName name, TextureTarget target, int unit) = 0;
        // Update texture storage for 2-dimensional texture.
        virtual void update_texture_storage(
            TextureFormat internal_format,
            PixelFormat source_format,
            Resolution size,
            std::vector<unsigned char> const & data) = 0;
        // Update texture storage for texture cube face.
        virtual void update_texture_storage(
            TextureFormat internal_format,
            PixelFormat source_format,
            Resolution size,
            std::vector<unsigned char> const & data,
            CubeFace face) = 0;
        // Update texture parameters.
        virtual void update_texture_parameters(Texture const & texture) = 0;

        // Create new framebuffer object.
        virtual ResourceName create_framebuffer() = 0;
        // Destroy framebuffer object.
        virtual void destroy_framebuffer(ResourceName name) = 0;
        // Bind framebuffer object.
        virtual void bind_framebuffer(ResourceName name) = 0;
        // Attach a texture/renderbuffer object to the currently bound framebuffer object.
        virtual void attach_to_framebuffer(ResourceName attachment, AttachmentType type, AttachmentPoint point) = 0;
        // Return array of status messages for currently bound framebuffer object.
        virtual std::vector<std::string> check_framebuffer_status() const = 0;

        // Return array of error messages (if any).
        virtual std::vector<std::string> get_errors() const = 0;
    };
}

#endif
<commit_msg>change clear comment<commit_after>#ifndef GRAPHICSDEVICE_HPP_INCLUDED
#define GRAPHICSDEVICE_HPP_INCLUDED

#include "graphicsresource.hpp"
#include "vertexattribute.hpp"

#include <string>
#include <vector>

namespace gst
{
    class Color;
    class Image;
    class Resolution;
    class ShadowedData;
    class Texture;
    class Texture2D;
    class TextureCube;
    class Viewport;

    enum class AttachmentType;
    enum class AttachmentPoint;
    enum class BlendMode;
    enum class BufferTarget;
    enum class CubeFace;
    enum class CullFace;
    enum class DataUsage;
    enum class DrawMode;
    enum class PixelFormat;
    enum class RenderbufferFormat;
    enum class ShaderType;
    enum class TextureFormat;
    enum class TextureTarget;

    // The responsibility of this class is to interact with a graphics card.
    class GraphicsDevice {
    public:
        virtual ~GraphicsDevice() = default;

        // Clear buffers.
        virtual void clear(bool color, bool depth) = 0;

        // Set clear values for color buffers.
        virtual void set_clear_color(Color const & clear_color) = 0;
        // Set blend mode enabled/disabled with appropiate blend function.
        virtual void set_blend_mode(BlendMode blend_mode) = 0;
        // Set faces that can be culled.
        virtual void set_cull_face(CullFace cull_face) = 0;
        // Set depth mask enabled/disabled.
        virtual void set_depth_mask(bool depth_mask) = 0;
        // Set depth test enabled/disabled.
        virtual void set_depth_test(bool depth_test) = 0;
        // Set viewport.
        virtual void set_viewport(Viewport const & viewport) = 0;

        // Return new shader object.
        virtual ResourceName create_shader(ShaderType type) = 0;
        // Destroy shader object.
        virtual void destroy_shader(ResourceName name) = 0;
        // Compile shader from specified source.
        virtual void compile_shader(ResourceName name, std::string const & source) = 0;
        // Return status from last compile operation.
        virtual bool get_compile_status(ResourceName name) = 0;
        // Return error message from last compile operation.
        virtual std::string get_compile_error(ResourceName name) = 0;

        // Return new program object.
        virtual ResourceName create_program() = 0;
        // Destroy program object.
        virtual void destroy_program(ResourceName name) = 0;
        // Attach specified shader object to specified program object.
        virtual void attach_shader(ResourceName program_name, ResourceName shader_name) = 0;
        // Attach specified shader object to specified program object.
        virtual void detach_shader(ResourceName program_name, ResourceName shader_name) = 0;
        // Link program object.
        virtual void link_program(ResourceName name) = 0;
        // Return status from last link operation.
        virtual bool get_link_status(ResourceName name) = 0;
        // Return error message from last compile operation.
        virtual std::string get_link_error(ResourceName name) = 0;
        // Bind vertex attribute index with a named attribute variable.
        virtual void bind_attribute_location(ResourceName program_name, int index, std::string const & name) = 0;
        // Return uniform location from specified name.
        virtual int get_uniform_location(ResourceName program_name, std::string const & name) = 0;
        // Modify value of uniform.
        virtual void uniform(int location, ShadowedData const & data) = 0;
        // Install specified program object as part of current rendering state.
        virtual void use_program(ResourceName name) = 0;

        // Return new buffer object.
        virtual ResourceName create_buffer() = 0;
        // Destroy buffer object.
        virtual void destroy_buffer(ResourceName name) = 0;
        // Bind buffer object.
        virtual void bind_buffer(ResourceName name, BufferTarget target) = 0;
        // Buffer data to current bound buffer object.
        virtual void buffer_data(BufferTarget target, ShadowedData const & data, DataUsage usage) = 0;

        // Return new vertex array object.
        virtual ResourceName create_vertex_array() = 0;
        // Destroy vertex array object.
        virtual void destroy_vertex_array(ResourceName name) = 0;
        // Bind vertex array object.
        virtual void bind_vertex_array(ResourceName name) = 0;
        // Render primitives from stored array data.
        virtual void draw_arrays(DrawMode mode, int first, int count) = 0;
        // Render primitives from stored array data.
        virtual void draw_elements(DrawMode mode, int count) = 0;
        // Enable and define generic vertex attribute.
        virtual void enable_vertex_attribute(VertexAttribute const & attribute) = 0;

        // Return new renderbuffer object.
        virtual ResourceName create_renderbuffer() = 0;
        // Destroy renderbuffer object.
        virtual void destroy_renderbuffer(ResourceName name) = 0;
        // Bind renderbuffer object.
        virtual void bind_renderbuffer(ResourceName name) = 0;
        // Establish data storage of specified format and dimensions for renderbuffer objects image.
        virtual void renderbuffer_storage(Resolution size, RenderbufferFormat format) = 0;

        // Create new texture object.
        virtual ResourceName create_texture() = 0;
        // Destroy texture object.
        virtual void destroy_texture(ResourceName name) = 0;
        // Bind texture object.
        virtual void bind_texture(ResourceName name, TextureTarget target, int unit) = 0;
        // Update texture storage for 2-dimensional texture.
        virtual void update_texture_storage(
            TextureFormat internal_format,
            PixelFormat source_format,
            Resolution size,
            std::vector<unsigned char> const & data) = 0;
        // Update texture storage for texture cube face.
        virtual void update_texture_storage(
            TextureFormat internal_format,
            PixelFormat source_format,
            Resolution size,
            std::vector<unsigned char> const & data,
            CubeFace face) = 0;
        // Update texture parameters.
        virtual void update_texture_parameters(Texture const & texture) = 0;

        // Create new framebuffer object.
        virtual ResourceName create_framebuffer() = 0;
        // Destroy framebuffer object.
        virtual void destroy_framebuffer(ResourceName name) = 0;
        // Bind framebuffer object.
        virtual void bind_framebuffer(ResourceName name) = 0;
        // Attach a texture/renderbuffer object to the currently bound framebuffer object.
        virtual void attach_to_framebuffer(ResourceName attachment, AttachmentType type, AttachmentPoint point) = 0;
        // Return array of status messages for currently bound framebuffer object.
        virtual std::vector<std::string> check_framebuffer_status() const = 0;

        // Return array of error messages (if any).
        virtual std::vector<std::string> get_errors() const = 0;
    };
}

#endif
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkXMLPDataReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLPDataReader.h"

#include "vtkDataArraySelection.h"
#include "vtkDataSet.h"
#include "vtkXMLDataElement.h"
#include "vtkXMLDataReader.h"

vtkCxxRevisionMacro(vtkXMLPDataReader, "1.1");

//----------------------------------------------------------------------------
vtkXMLPDataReader::vtkXMLPDataReader()
{
  this->GhostLevel = 0;

  this->NumberOfPieces = 0;

  this->PieceElements = 0;
  this->PieceReaders = 0;
  this->CanReadPieceFlag = 0;

  this->PathName = 0;
}

//----------------------------------------------------------------------------
vtkXMLPDataReader::~vtkXMLPDataReader()
{
  if(this->NumberOfPieces) { this->DestroyPieces(); }
  if(this->PathName) { delete [] this->PathName; }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n";
}

//----------------------------------------------------------------------------
vtkDataSet* vtkXMLPDataReader::GetPieceInputAsDataSet(int piece)
{
  vtkXMLDataReader* reader = this->PieceReaders[piece];
  if(!reader) { return 0; }
  if(reader->GetNumberOfOutputs() < 1) { return 0; }
  return static_cast<vtkDataSet*>(reader->GetOutputs()[0]);
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupOutputInformation()
{
  this->Superclass::SetupOutputInformation();
  int i;

  // Setup the output arrays.
  vtkXMLDataElement* ePointData = this->PPointDataElement;
  vtkXMLDataElement* eCellData = this->PCellDataElement;
  vtkPointData* pointData = this->GetOutputAsDataSet()->GetPointData();
  vtkCellData* cellData = this->GetOutputAsDataSet()->GetCellData();

  // Setup the point and cell data arrays without allocation.
  this->SetDataArraySelections(ePointData, this->PointDataArraySelection);
  if(ePointData)
    {
    for(i=0;i < ePointData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
      if(this->PointDataArrayIsEnabled(eNested))
        {
        vtkDataArray* array = this->CreateDataArray(eNested);
        pointData->AddArray(array);
        array->Delete();
        }
      }
    }
  this->SetDataArraySelections(eCellData, this->CellDataArraySelection);
  if(eCellData)
    {
    for(i=0;i < eCellData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
      if(this->CellDataArrayIsEnabled(eNested))
        {
        vtkDataArray* array = this->CreateDataArray(eNested);
        cellData->AddArray(array);
        array->Delete();
        }
      }
    }

  // Setup attribute indices for the point data and cell data.
  this->ReadAttributeIndices(ePointData, pointData);
  this->ReadAttributeIndices(eCellData, cellData);
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupOutputData()
{
  this->Superclass::SetupOutputData();

  vtkDataSet* output = this->GetOutputAsDataSet();
  vtkXMLDataElement* ePointData = this->PPointDataElement;
  vtkXMLDataElement* eCellData = this->PCellDataElement;
  vtkPointData* pointData = output->GetPointData();
  vtkCellData* cellData = output->GetCellData();

  // Get the size of the output arrays.
  unsigned long pointTuples = this->GetNumberOfPoints();
  unsigned long cellTuples = this->GetNumberOfCells();

  // Allocate data in the arrays.
  int i;
  if(ePointData)
    {
    int a=0;
    for(i=0;i < ePointData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
      if(this->PointDataArrayIsEnabled(eNested))
        {
        pointData->GetArray(a++)->SetNumberOfTuples(pointTuples);
        }
      }
    }
  if(eCellData)
    {
    int a=0;
    for(i=0;i < eCellData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
      if(this->CellDataArrayIsEnabled(eNested))
        {
        cellData->GetArray(a++)->SetNumberOfTuples(cellTuples);
        }
      }
    }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::ReadXMLInformation()
{
  // First setup the filename components.
  this->SplitFileName();

  // Now proceed with reading the information.
  this->Superclass::ReadXMLInformation();
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
{
  if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; }
  // Read information about the data.
  if(!ePrimary->GetScalarAttribute("GhostLevel", this->GhostLevel))
    {
    this->GhostLevel = 0;
    }

  // Read information about the pieces.
  this->PPointDataElement = 0;
  this->PCellDataElement = 0;
  int i;
  int numNested = ePrimary->GetNumberOfNestedElements();
  int numPieces = 0;
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if(strcmp(eNested->GetName(), "Piece") == 0) { ++numPieces; }
    else if(strcmp(eNested->GetName(), "PPointData") == 0)
      {
      this->PPointDataElement = eNested;
      }
    else if(strcmp(eNested->GetName(), "PCellData") == 0)
      {
      this->PCellDataElement = eNested;
      }
    }
  this->SetupPieces(numPieces);
  int piece = 0;
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if(strcmp(eNested->GetName(), "Piece") == 0)
      {
      if(!this->ReadPiece(eNested, piece++)) { return 0; }
      }
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupPieces(int numPieces)
{
  if(this->NumberOfPieces) { this->DestroyPieces(); }
  this->NumberOfPieces = numPieces;
  this->PieceElements = new vtkXMLDataElement*[this->NumberOfPieces];
  this->PieceReaders = new vtkXMLDataReader*[this->NumberOfPieces];
  this->CanReadPieceFlag = new int[this->NumberOfPieces];
  int i;
  for(i=0;i < this->NumberOfPieces;++i)
    {
    this->PieceElements[i] = 0;
    this->PieceReaders[i] = 0;
    this->CanReadPieceFlag[i] = 0;
    }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::DestroyPieces()
{
  int i;
  for(i=0;i < this->NumberOfPieces;++i)
    {
    if(this->PieceReaders[i]) { this->PieceReaders[i]->Delete(); }
    }
  delete [] this->PieceElements;
  delete [] this->CanReadPieceFlag;
  delete [] this->PieceReaders;
  this->PieceElements = 0;
  this->PieceReaders = 0;
  this->NumberOfPieces = 0;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece, int index)
{
  this->Piece = index;
  return this->ReadPiece(ePiece);
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece)
{
  this->PieceElements[this->Piece] = ePiece;

  const char* fileName = ePiece->GetAttribute("Source");
  if(!fileName)
    {
    vtkErrorMacro("Piece " << this->Piece << " has no Source attribute.");
    return 0;
    }

  // The file name is relative to the summary file.  Convert it to
  // something we can use.
  char *pieceFileName = this->CreatePieceFileName(fileName);

  vtkXMLDataReader* reader = this->CreatePieceReader();
  this->PieceReaders[this->Piece] = reader;
  reader->SetFileName(pieceFileName);

  delete [] pieceFileName;

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPieceData(int index)
{
  this->Piece = index;

  // We need data, make sure the piece can be read.
  if(!this->CanReadPiece(this->Piece))
    {
    vtkErrorMacro("File for piece " << this->Piece << " cannot be read.");
    return 0;
    }

  // Actually read the data.
  vtkDataArraySelection* pds =
    this->PieceReaders[this->Piece]->GetPointDataArraySelection();
  vtkDataArraySelection* cds =
    this->PieceReaders[this->Piece]->GetCellDataArraySelection();
  pds->CopySelections(this->PointDataArraySelection);
  cds->CopySelections(this->CellDataArraySelection);
  return this->ReadPieceData();
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPieceData()
{
  vtkDataSet* input = this->GetPieceInputAsDataSet(this->Piece);
  vtkDataSet* output = this->GetOutputAsDataSet();
  //vtkXMLDataElement* ePointData = this->PPointDataElement;
  //vtkXMLDataElement* eCellData = this->PCellDataElement;

  // Copy point data and cell data for this piece.
  int a=0;
  int i;
  for(i=0;i < output->GetPointData()->GetNumberOfArrays();++i)
    {

    this->CopyArrayForPoints(input->GetPointData()->GetArray(i),
                             output->GetPointData()->GetArray(i));
    }
  a=0;
  for(i=0;i < output->GetCellData()->GetNumberOfArrays();++i)
    {
    this->CopyArrayForCells(input->GetCellData()->GetArray(i),
                            output->GetCellData()->GetArray(i));
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::CanReadPiece(int index)
{
  // If necessary, test whether the piece can be read.
  vtkXMLDataReader* reader = this->PieceReaders[index];
  if(reader && !this->CanReadPieceFlag[index])
    {
    if(reader->CanReadFile(reader->GetFileName()))
      {
      // We can read the piece.  Save result to avoid later repeat of
      // test.
      this->CanReadPieceFlag[index] = 1;
      }
    else
      {
      // We cannot read the piece.  Destroy the reader to avoid later
      // repeat of test.
      this->PieceReaders[index] = 0;
      reader->Delete();
      }
    }

  return (this->PieceReaders[index]? 1:0);
}

//----------------------------------------------------------------------------
char* vtkXMLPDataReader::CreatePieceFileName(const char* fileName)
{
  ostrstream fn;
  if(this->PathName) { fn << this->PathName; }
  fn << fileName << ends;
  return fn.str();
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SplitFileName()
{
  // Pull the PathName component out of the FileName.
  size_t length = strlen(this->FileName);
  char* fileName = new char[length+1];
  strcpy(fileName, this->FileName);
  char* begin = fileName;
  char* end = fileName + length;
  char* s;

#if defined(_WIN32)
  // Convert to UNIX-style slashes.
  for(s=begin;s != end;++s) { if(*s == '\\') { *s = '/'; } }
#endif

  // Extract the path name up to the last '/'.
  if(this->PathName) { delete [] this->PathName; this->PathName = 0; }
  char* rbegin = end-1;
  char* rend = begin-1;
  for(s=rbegin;s != rend;--s) { if(*s == '/') { break; } }
  if(s >= begin)
    {
    length = (s-begin)+1;
    this->PathName = new char[length+1];
    strncpy(this->PathName, this->FileName, length);
    this->PathName[length] = '\0';
    begin = s+1;
    }

  // Cleanup temporary name.
  delete [] fileName;
}
<commit_msg>ERR: Removed unused variable.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkXMLPDataReader.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkXMLPDataReader.h"

#include "vtkDataArraySelection.h"
#include "vtkDataSet.h"
#include "vtkXMLDataElement.h"
#include "vtkXMLDataReader.h"

vtkCxxRevisionMacro(vtkXMLPDataReader, "1.2");

//----------------------------------------------------------------------------
vtkXMLPDataReader::vtkXMLPDataReader()
{
  this->GhostLevel = 0;

  this->NumberOfPieces = 0;

  this->PieceElements = 0;
  this->PieceReaders = 0;
  this->CanReadPieceFlag = 0;

  this->PathName = 0;
}

//----------------------------------------------------------------------------
vtkXMLPDataReader::~vtkXMLPDataReader()
{
  if(this->NumberOfPieces) { this->DestroyPieces(); }
  if(this->PathName) { delete [] this->PathName; }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n";
}

//----------------------------------------------------------------------------
vtkDataSet* vtkXMLPDataReader::GetPieceInputAsDataSet(int piece)
{
  vtkXMLDataReader* reader = this->PieceReaders[piece];
  if(!reader) { return 0; }
  if(reader->GetNumberOfOutputs() < 1) { return 0; }
  return static_cast<vtkDataSet*>(reader->GetOutputs()[0]);
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupOutputInformation()
{
  this->Superclass::SetupOutputInformation();
  int i;

  // Setup the output arrays.
  vtkXMLDataElement* ePointData = this->PPointDataElement;
  vtkXMLDataElement* eCellData = this->PCellDataElement;
  vtkPointData* pointData = this->GetOutputAsDataSet()->GetPointData();
  vtkCellData* cellData = this->GetOutputAsDataSet()->GetCellData();

  // Setup the point and cell data arrays without allocation.
  this->SetDataArraySelections(ePointData, this->PointDataArraySelection);
  if(ePointData)
    {
    for(i=0;i < ePointData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
      if(this->PointDataArrayIsEnabled(eNested))
        {
        vtkDataArray* array = this->CreateDataArray(eNested);
        pointData->AddArray(array);
        array->Delete();
        }
      }
    }
  this->SetDataArraySelections(eCellData, this->CellDataArraySelection);
  if(eCellData)
    {
    for(i=0;i < eCellData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
      if(this->CellDataArrayIsEnabled(eNested))
        {
        vtkDataArray* array = this->CreateDataArray(eNested);
        cellData->AddArray(array);
        array->Delete();
        }
      }
    }

  // Setup attribute indices for the point data and cell data.
  this->ReadAttributeIndices(ePointData, pointData);
  this->ReadAttributeIndices(eCellData, cellData);
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupOutputData()
{
  this->Superclass::SetupOutputData();

  vtkDataSet* output = this->GetOutputAsDataSet();
  vtkXMLDataElement* ePointData = this->PPointDataElement;
  vtkXMLDataElement* eCellData = this->PCellDataElement;
  vtkPointData* pointData = output->GetPointData();
  vtkCellData* cellData = output->GetCellData();

  // Get the size of the output arrays.
  unsigned long pointTuples = this->GetNumberOfPoints();
  unsigned long cellTuples = this->GetNumberOfCells();

  // Allocate data in the arrays.
  int i;
  if(ePointData)
    {
    int a=0;
    for(i=0;i < ePointData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
      if(this->PointDataArrayIsEnabled(eNested))
        {
        pointData->GetArray(a++)->SetNumberOfTuples(pointTuples);
        }
      }
    }
  if(eCellData)
    {
    int a=0;
    for(i=0;i < eCellData->GetNumberOfNestedElements();++i)
      {
      vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
      if(this->CellDataArrayIsEnabled(eNested))
        {
        cellData->GetArray(a++)->SetNumberOfTuples(cellTuples);
        }
      }
    }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::ReadXMLInformation()
{
  // First setup the filename components.
  this->SplitFileName();

  // Now proceed with reading the information.
  this->Superclass::ReadXMLInformation();
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
{
  if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; }
  // Read information about the data.
  if(!ePrimary->GetScalarAttribute("GhostLevel", this->GhostLevel))
    {
    this->GhostLevel = 0;
    }

  // Read information about the pieces.
  this->PPointDataElement = 0;
  this->PCellDataElement = 0;
  int i;
  int numNested = ePrimary->GetNumberOfNestedElements();
  int numPieces = 0;
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if(strcmp(eNested->GetName(), "Piece") == 0) { ++numPieces; }
    else if(strcmp(eNested->GetName(), "PPointData") == 0)
      {
      this->PPointDataElement = eNested;
      }
    else if(strcmp(eNested->GetName(), "PCellData") == 0)
      {
      this->PCellDataElement = eNested;
      }
    }
  this->SetupPieces(numPieces);
  int piece = 0;
  for(i=0;i < numNested; ++i)
    {
    vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
    if(strcmp(eNested->GetName(), "Piece") == 0)
      {
      if(!this->ReadPiece(eNested, piece++)) { return 0; }
      }
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SetupPieces(int numPieces)
{
  if(this->NumberOfPieces) { this->DestroyPieces(); }
  this->NumberOfPieces = numPieces;
  this->PieceElements = new vtkXMLDataElement*[this->NumberOfPieces];
  this->PieceReaders = new vtkXMLDataReader*[this->NumberOfPieces];
  this->CanReadPieceFlag = new int[this->NumberOfPieces];
  int i;
  for(i=0;i < this->NumberOfPieces;++i)
    {
    this->PieceElements[i] = 0;
    this->PieceReaders[i] = 0;
    this->CanReadPieceFlag[i] = 0;
    }
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::DestroyPieces()
{
  int i;
  for(i=0;i < this->NumberOfPieces;++i)
    {
    if(this->PieceReaders[i]) { this->PieceReaders[i]->Delete(); }
    }
  delete [] this->PieceElements;
  delete [] this->CanReadPieceFlag;
  delete [] this->PieceReaders;
  this->PieceElements = 0;
  this->PieceReaders = 0;
  this->NumberOfPieces = 0;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece, int index)
{
  this->Piece = index;
  return this->ReadPiece(ePiece);
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece)
{
  this->PieceElements[this->Piece] = ePiece;

  const char* fileName = ePiece->GetAttribute("Source");
  if(!fileName)
    {
    vtkErrorMacro("Piece " << this->Piece << " has no Source attribute.");
    return 0;
    }

  // The file name is relative to the summary file.  Convert it to
  // something we can use.
  char *pieceFileName = this->CreatePieceFileName(fileName);

  vtkXMLDataReader* reader = this->CreatePieceReader();
  this->PieceReaders[this->Piece] = reader;
  reader->SetFileName(pieceFileName);

  delete [] pieceFileName;

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPieceData(int index)
{
  this->Piece = index;

  // We need data, make sure the piece can be read.
  if(!this->CanReadPiece(this->Piece))
    {
    vtkErrorMacro("File for piece " << this->Piece << " cannot be read.");
    return 0;
    }

  // Actually read the data.
  vtkDataArraySelection* pds =
    this->PieceReaders[this->Piece]->GetPointDataArraySelection();
  vtkDataArraySelection* cds =
    this->PieceReaders[this->Piece]->GetCellDataArraySelection();
  pds->CopySelections(this->PointDataArraySelection);
  cds->CopySelections(this->CellDataArraySelection);
  return this->ReadPieceData();
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::ReadPieceData()
{
  vtkDataSet* input = this->GetPieceInputAsDataSet(this->Piece);
  vtkDataSet* output = this->GetOutputAsDataSet();
  //vtkXMLDataElement* ePointData = this->PPointDataElement;
  //vtkXMLDataElement* eCellData = this->PCellDataElement;

  // Copy point data and cell data for this piece.
  int i;
  for(i=0;i < output->GetPointData()->GetNumberOfArrays();++i)
    {

    this->CopyArrayForPoints(input->GetPointData()->GetArray(i),
                             output->GetPointData()->GetArray(i));
    }
  for(i=0;i < output->GetCellData()->GetNumberOfArrays();++i)
    {
    this->CopyArrayForCells(input->GetCellData()->GetArray(i),
                            output->GetCellData()->GetArray(i));
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLPDataReader::CanReadPiece(int index)
{
  // If necessary, test whether the piece can be read.
  vtkXMLDataReader* reader = this->PieceReaders[index];
  if(reader && !this->CanReadPieceFlag[index])
    {
    if(reader->CanReadFile(reader->GetFileName()))
      {
      // We can read the piece.  Save result to avoid later repeat of
      // test.
      this->CanReadPieceFlag[index] = 1;
      }
    else
      {
      // We cannot read the piece.  Destroy the reader to avoid later
      // repeat of test.
      this->PieceReaders[index] = 0;
      reader->Delete();
      }
    }

  return (this->PieceReaders[index]? 1:0);
}

//----------------------------------------------------------------------------
char* vtkXMLPDataReader::CreatePieceFileName(const char* fileName)
{
  ostrstream fn;
  if(this->PathName) { fn << this->PathName; }
  fn << fileName << ends;
  return fn.str();
}

//----------------------------------------------------------------------------
void vtkXMLPDataReader::SplitFileName()
{
  // Pull the PathName component out of the FileName.
  size_t length = strlen(this->FileName);
  char* fileName = new char[length+1];
  strcpy(fileName, this->FileName);
  char* begin = fileName;
  char* end = fileName + length;
  char* s;

#if defined(_WIN32)
  // Convert to UNIX-style slashes.
  for(s=begin;s != end;++s) { if(*s == '\\') { *s = '/'; } }
#endif

  // Extract the path name up to the last '/'.
  if(this->PathName) { delete [] this->PathName; this->PathName = 0; }
  char* rbegin = end-1;
  char* rend = begin-1;
  for(s=rbegin;s != rend;--s) { if(*s == '/') { break; } }
  if(s >= begin)
    {
    length = (s-begin)+1;
    this->PathName = new char[length+1];
    strncpy(this->PathName, this->FileName, length);
    this->PathName[length] = '\0';
    begin = s+1;
    }

  // Cleanup temporary name.
  delete [] fileName;
}
<|endoftext|>


<commit_before>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/dim4.hpp>
#include <af/defines.h>
#include <ArrayInfo.hpp>
#include <Array.hpp>
#include <histogram.hpp>

using af::dim4;

namespace cpu
{

template<typename inType, typename outType>
Array<outType> histogram(const Array<inType> &in, const unsigned &nbins, const double &minval, const double &maxval)
{
    float step = (maxval - minval)/(float)nbins;

    const dim4 inDims  = in.dims();
    dim4 iStrides      = in.strides();
    dim4 outDims       = dim4(nbins,1,inDims[2],inDims[3]);
    Array<outType> out = createValueArray<outType>(outDims, outType(0));
    dim4 oStrides      = out.strides();
    dim_type nElems    = inDims[0]*inDims[1];

    outType *outData    = out.get();
    const inType* inData= in.get();

    for(dim_type b3 = 0; b3 < outDims[2]; b3++) {
        for(dim_type b2 = 0; b2 < outDims[2]; b2++) {
            for(dim_type i=0; i<nElems; i++) {
                int bin = (int)((inData[i] - minval) / step);
                bin = std::max(bin, 0);
                bin = std::min(bin, (int)(nbins - 1));
                outData[bin]++;
            }
            inData  += iStrides[2];
            outData += oStrides[2];
        }
        inData  += iStrides[3];
        outData += oStrides[3];
    }

    return out;
}

#define INSTANTIATE(in_t,out_t)\
template Array<out_t> histogram(const Array<in_t> &in, const unsigned &nbins, const double &minval, const double &maxval);

INSTANTIATE(float , uint)
INSTANTIATE(double, uint)
INSTANTIATE(char  , uint)
INSTANTIATE(int   , uint)
INSTANTIATE(uint  , uint)
INSTANTIATE(uchar , uint)

}
<commit_msg>BUGFIX fixed 3rd dimension index in cpu histogram implementation<commit_after>/*******************************************************
 * Copyright (c) 2014, ArrayFire
 * All rights reserved.
 *
 * This file is distributed under 3-clause BSD license.
 * The complete license agreement can be obtained at:
 * http://arrayfire.com/licenses/BSD-3-Clause
 ********************************************************/

#include <af/dim4.hpp>
#include <af/defines.h>
#include <ArrayInfo.hpp>
#include <Array.hpp>
#include <histogram.hpp>

using af::dim4;

namespace cpu
{

template<typename inType, typename outType>
Array<outType> histogram(const Array<inType> &in, const unsigned &nbins, const double &minval, const double &maxval)
{
    float step = (maxval - minval)/(float)nbins;

    const dim4 inDims  = in.dims();
    dim4 iStrides      = in.strides();
    dim4 outDims       = dim4(nbins,1,inDims[2],inDims[3]);
    Array<outType> out = createValueArray<outType>(outDims, outType(0));
    dim4 oStrides      = out.strides();
    dim_type nElems    = inDims[0]*inDims[1];

    outType *outData    = out.get();
    const inType* inData= in.get();

    for(dim_type b3 = 0; b3 < outDims[3]; b3++) {
        for(dim_type b2 = 0; b2 < outDims[2]; b2++) {
            for(dim_type i=0; i<nElems; i++) {
                int bin = (int)((inData[i] - minval) / step);
                bin = std::max(bin, 0);
                bin = std::min(bin, (int)(nbins - 1));
                outData[bin]++;
            }
            inData  += iStrides[2];
            outData += oStrides[2];
        }
        inData  += iStrides[3];
        outData += oStrides[3];
    }

    return out;
}

#define INSTANTIATE(in_t,out_t)\
template Array<out_t> histogram(const Array<in_t> &in, const unsigned &nbins, const double &minval, const double &maxval);

INSTANTIATE(float , uint)
INSTANTIATE(double, uint)
INSTANTIATE(char  , uint)
INSTANTIATE(int   , uint)
INSTANTIATE(uint  , uint)
INSTANTIATE(uchar , uint)

}
<|endoftext|>