<commit_before>// $Id$
//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de>    *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/// @file   AliHLTHuffman.cxx
/// @author Thorsten Kollegger, Matthias Richter
/// @date   2011-08-14
/// @brief  Huffman code generator/encoder/decoder

#include "AliHLTHuffman.h"

#include <iostream>
#include <set>
#include <bitset>
#include <algorithm>

AliHLTHuffmanNode::AliHLTHuffmanNode()
	: TObject()
	, fValue(-1)
	, fWeight(0.)
{
        // nop
}

AliHLTHuffmanNode::AliHLTHuffmanNode(const AliHLTHuffmanNode& other)
	: TObject()
	, fValue(other.GetValue())
	, fWeight(other.GetWeight())
{
}

AliHLTHuffmanNode& AliHLTHuffmanNode::operator =(const AliHLTHuffmanNode& other) {
        /// assignment operator
	this->fValue = other.fValue;
	this->fWeight = other.fWeight;
	return *this;
}

AliHLTHuffmanNode::~AliHLTHuffmanNode() {
}

void AliHLTHuffmanNode::AssignCode() {
        /// assign code to this node loop to right and left nodes
	if (GetLeftChild()) {
		// shift current bit pattern to left and add one
		std::bitset < 64 > v = (this->GetBinaryCode() << 1);
		v.set(0);
		GetLeftChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
		GetLeftChild()->AssignCode();
	}
	if (GetRightChild()) {
		std::bitset < 64 > v = (this->GetBinaryCode() << 1);
		v.reset(0);
		GetRightChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
		GetRightChild()->AssignCode();
	}
}

void AliHLTHuffmanNode::Print(Option_t* /*option*/) const {
        /// print info
	std::cout << "value=" << GetValue() << ", weight=" << GetWeight() << ", length="
			<< GetBinaryCodeLength() << ", code=" << GetBinaryCode().to_string()
			<< std::endl;
	if (GetLeftChild()) {
		GetLeftChild()->Print();
	}
	if (GetRightChild()) {
		GetRightChild()->Print();
	}
}

ClassImp(AliHLTHuffmanNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode()
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(NULL)
	, fRight(NULL)
{
        // nop
}

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(const AliHLTHuffmanTreeNode& other)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(other.fBinaryCodeLength)
	, fBinaryCode(other.fBinaryCode)
	, fLeft(other.GetLeftChild())
	, fRight(other.GetRightChild())
{

}

AliHLTHuffmanTreeNode& AliHLTHuffmanTreeNode::operator =(const AliHLTHuffmanTreeNode& other)
{
        /// assignment operator
        if (&other==this) return *this;
	this->fBinaryCodeLength = other.GetBinaryCodeLength();
	this->fBinaryCode = other.GetBinaryCode();
	this->fLeft = other.GetLeftChild();
	this->fRight = other.GetRightChild();
	AliHLTHuffmanNode::operator=(other);
	return *this;
}

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(AliHLTHuffmanNode* l, AliHLTHuffmanNode* r)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(l)
	, fRight(r) {
	if (l && r) {
		SetWeight(l->GetWeight() + r->GetWeight());
	} else if (l && !r) {
		SetWeight(l->GetWeight());
	} else if (!l && r) {
		SetWeight(r->GetWeight());
	}
}

AliHLTHuffmanTreeNode::~AliHLTHuffmanTreeNode()
{
        // nop
}

ClassImp(AliHLTHuffmanTreeNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode()
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(NULL)
	, fRight(NULL)
{
        // nop
}

AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode(const AliHLTHuffmanLeaveNode& other)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(other.fBinaryCodeLength)
	, fBinaryCode(other.fBinaryCode)
	, fLeft(other.GetLeftChild())
	, fRight(other.GetRightChild())
{

}

AliHLTHuffmanLeaveNode& AliHLTHuffmanLeaveNode::operator =(const AliHLTHuffmanLeaveNode& other)
{
        /// assignment operator
        if (&other==this) return *this;
	this->fBinaryCodeLength = other.GetBinaryCodeLength();
	this->fBinaryCode = other.GetBinaryCode();
	this->fLeft = other.GetLeftChild();
	this->fRight = other.GetRightChild();
	AliHLTHuffmanNode::operator=(other);
	return *this;
}

AliHLTHuffmanLeaveNode::~AliHLTHuffmanLeaveNode()
{
        // nop
}

ClassImp(AliHLTHuffmanLeaveNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffman::AliHLTHuffman()
	: TNamed()
	, fMaxBits(0)
	, fMaxValue(0)
	, fNodes(0)
	, fHuffTopNode(NULL)
{
        /// nop
}

AliHLTHuffman::AliHLTHuffman(const AliHLTHuffman& other)
	: TNamed()
	, AliHLTLogging()
	, fMaxBits(other.fMaxBits)
	, fMaxValue(other.fMaxValue)
	, fNodes(other.fNodes)
	, fHuffTopNode(NULL) {
        /// nop
}

AliHLTHuffman::AliHLTHuffman(const char* name, UInt_t maxBits)
        : TNamed(name, name)
	, fMaxBits(maxBits)
	, fMaxValue((((AliHLTUInt64_t) 1) << maxBits) - 1)
	, fNodes((((AliHLTUInt64_t) 1) << maxBits))
	, fHuffTopNode(NULL)
 {
        /// standard constructor
	for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
		fNodes[i].SetValue(i);
	}
}

AliHLTHuffman::~AliHLTHuffman() {
        /// destructor, nop
}

const std::bitset<64>& AliHLTHuffman::Encode(const AliHLTUInt64_t v, AliHLTUInt64_t& codeLength) const {
        /// encode a value
	codeLength = 0;
	if (v <= fMaxValue) {
		// valid symbol/value
		if (fHuffTopNode) {
			// huffman code has been generated
			codeLength = fNodes[v].GetBinaryCodeLength();
			return fNodes[v].GetBinaryCode();
		} else {
		  HLTError("encoder '%s' does not seem to be initialized", GetName());
		}
	} else {
	  HLTError("encoder %s: value %llu exceeds range of %d bits", GetName(), v, GetMaxBits());
	}

	static const std::bitset<64> dummy;
	return dummy;
}

Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value) const {
	// TODO: check decoding logic, righ now it is just as written
	AliHLTHuffmanNode* currNode = fHuffTopNode;
	if (!currNode) return kFALSE;
	if (currNode->GetValue() >= 0) {
		// handle case with just one node - also quite unlikely
		value = currNode->GetValue();
		return kTRUE;
	}
	while (currNode) {
		if (bits[0] && currNode->GetLeftChild()) {
			// follow left branch
			currNode = currNode->GetLeftChild();
			bits >>= 1;
			if (currNode->GetValue() >= 0) {
				value = currNode->GetValue();
				return kTRUE;
			}
		}
		if (!bits[0] && currNode->GetRightChild()) {
			currNode = currNode->GetRightChild();
			bits >>= 1;
			if (currNode->GetValue() >= 0) {
				value = currNode->GetValue();
				return kTRUE;
			}
		}
	}
	value = ((AliHLTUInt64_t)1) << 63;
	return kFALSE;
}

Bool_t AliHLTHuffman::AddTrainingValue(const AliHLTUInt64_t value,
		const float_t weight) {
	if (value > fMaxValue) {
		/* TODO: ERROR message */
		return kFALSE;
	}
	fNodes[value].AddWeight(weight);
	return kTRUE;
}

Bool_t AliHLTHuffman::GenerateHuffmanTree() {
	// insert pointer to nodes into ordered structure to build tree
	std::multiset<AliHLTHuffmanNode*, AliHLTHuffmanNode::less> nodeCollection;
	//	std::copy(fNodes.begin(), fNodes.end(),
	//			std::inserter(freq_coll, freq_coll.begin()));
	for (std::vector<AliHLTHuffmanLeaveNode>::iterator i = fNodes.begin(); i
			!= fNodes.end(); ++i) {
		nodeCollection.insert(&(*i));
	}
	while (nodeCollection.size() > 1) {
		// insert new node into structure, combining the two with lowest probability
		nodeCollection.insert(
				new AliHLTHuffmanTreeNode(*nodeCollection.begin(),
						*++nodeCollection.begin()));
		nodeCollection.erase(nodeCollection.begin());
		nodeCollection.erase(nodeCollection.begin());
	}
	//assign value
	fHuffTopNode = *nodeCollection.begin();
	fHuffTopNode->AssignCode();
	return kTRUE;
}

void AliHLTHuffman::Print(Option_t* option) const {
        std::cout << GetName() << endl;
        bool bPrintShort=strcmp(option, "short")==0;
	if (fHuffTopNode && !bPrintShort) {
		std::cout << "Huffman tree:" << endl;
		fHuffTopNode->Print();
	}
	Double_t uncompressedSize = 0;
	Double_t compressedSize = 0;
	Double_t totalWeight = 0;
	if (!bPrintShort)
	  std::cout << std::endl << "Huffman codes:" << std::endl;
	for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
	  if (!bPrintShort) fNodes[i].Print();
		totalWeight += fNodes[i].GetWeight();
		uncompressedSize += fNodes[i].GetWeight() * fMaxBits;
		compressedSize += fNodes[i].GetWeight()
				* fNodes[i].GetBinaryCodeLength();
	}
	if (uncompressedSize > 0) {
		std::cout << "compression ratio: " << compressedSize
				/ uncompressedSize << std::endl;
		std::cout << "<bits> uncompressed: " << uncompressedSize / totalWeight
				<< std::endl;
		std::cout << "<bits> compressed:   " << compressedSize / totalWeight
				<< std::endl;
	}
}

AliHLTHuffman& AliHLTHuffman::operator =(const AliHLTHuffman& other) {
	fMaxValue = other.fMaxValue;
	fNodes = other.fNodes;
	fHuffTopNode = NULL;
	return *this;
}

ClassImp(AliHLTHuffman)

<commit_msg>typo corrected, leading to compile errors on some systems<commit_after>// $Id$
//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Thorsten Kollegger <kollegge@ikf.uni-frankfurt.de>    *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/// @file   AliHLTHuffman.cxx
/// @author Thorsten Kollegger, Matthias Richter
/// @date   2011-08-14
/// @brief  Huffman code generator/encoder/decoder

#include "AliHLTHuffman.h"

#include <iostream>
#include <set>
#include <bitset>
#include <algorithm>

AliHLTHuffmanNode::AliHLTHuffmanNode()
	: TObject()
	, fValue(-1)
	, fWeight(0.)
{
        // nop
}

AliHLTHuffmanNode::AliHLTHuffmanNode(const AliHLTHuffmanNode& other)
	: TObject()
	, fValue(other.GetValue())
	, fWeight(other.GetWeight())
{
}

AliHLTHuffmanNode& AliHLTHuffmanNode::operator =(const AliHLTHuffmanNode& other) {
        /// assignment operator
	this->fValue = other.fValue;
	this->fWeight = other.fWeight;
	return *this;
}

AliHLTHuffmanNode::~AliHLTHuffmanNode() {
}

void AliHLTHuffmanNode::AssignCode() {
        /// assign code to this node loop to right and left nodes
	if (GetLeftChild()) {
		// shift current bit pattern to left and add one
		std::bitset < 64 > v = (this->GetBinaryCode() << 1);
		v.set(0);
		GetLeftChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
		GetLeftChild()->AssignCode();
	}
	if (GetRightChild()) {
		std::bitset < 64 > v = (this->GetBinaryCode() << 1);
		v.reset(0);
		GetRightChild()->SetBinaryCode(this->GetBinaryCodeLength() + 1, v);
		GetRightChild()->AssignCode();
	}
}

void AliHLTHuffmanNode::Print(Option_t* /*option*/) const {
        /// print info
	std::cout << "value=" << GetValue() << ", weight=" << GetWeight() << ", length="
			<< GetBinaryCodeLength() << ", code=" << GetBinaryCode().to_string()
			<< std::endl;
	if (GetLeftChild()) {
		GetLeftChild()->Print();
	}
	if (GetRightChild()) {
		GetRightChild()->Print();
	}
}

ClassImp(AliHLTHuffmanNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode()
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(NULL)
	, fRight(NULL)
{
        // nop
}

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(const AliHLTHuffmanTreeNode& other)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(other.fBinaryCodeLength)
	, fBinaryCode(other.fBinaryCode)
	, fLeft(other.GetLeftChild())
	, fRight(other.GetRightChild())
{

}

AliHLTHuffmanTreeNode& AliHLTHuffmanTreeNode::operator =(const AliHLTHuffmanTreeNode& other)
{
        /// assignment operator
        if (&other==this) return *this;
	this->fBinaryCodeLength = other.GetBinaryCodeLength();
	this->fBinaryCode = other.GetBinaryCode();
	this->fLeft = other.GetLeftChild();
	this->fRight = other.GetRightChild();
	AliHLTHuffmanNode::operator=(other);
	return *this;
}

AliHLTHuffmanTreeNode::AliHLTHuffmanTreeNode(AliHLTHuffmanNode* l, AliHLTHuffmanNode* r)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(l)
	, fRight(r) {
	if (l && r) {
		SetWeight(l->GetWeight() + r->GetWeight());
	} else if (l && !r) {
		SetWeight(l->GetWeight());
	} else if (!l && r) {
		SetWeight(r->GetWeight());
	}
}

AliHLTHuffmanTreeNode::~AliHLTHuffmanTreeNode()
{
        // nop
}

ClassImp(AliHLTHuffmanTreeNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode()
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(0)
	, fBinaryCode(0)
	, fLeft(NULL)
	, fRight(NULL)
{
        // nop
}

AliHLTHuffmanLeaveNode::AliHLTHuffmanLeaveNode(const AliHLTHuffmanLeaveNode& other)
	: AliHLTHuffmanNode()
	, fBinaryCodeLength(other.fBinaryCodeLength)
	, fBinaryCode(other.fBinaryCode)
	, fLeft(other.GetLeftChild())
	, fRight(other.GetRightChild())
{

}

AliHLTHuffmanLeaveNode& AliHLTHuffmanLeaveNode::operator =(const AliHLTHuffmanLeaveNode& other)
{
        /// assignment operator
        if (&other==this) return *this;
	this->fBinaryCodeLength = other.GetBinaryCodeLength();
	this->fBinaryCode = other.GetBinaryCode();
	this->fLeft = other.GetLeftChild();
	this->fRight = other.GetRightChild();
	AliHLTHuffmanNode::operator=(other);
	return *this;
}

AliHLTHuffmanLeaveNode::~AliHLTHuffmanLeaveNode()
{
        // nop
}

ClassImp(AliHLTHuffmanLeaveNode)

///////////////////////////////////////////////////////////////////////////////////////////////

AliHLTHuffman::AliHLTHuffman()
	: TNamed()
	, fMaxBits(0)
	, fMaxValue(0)
	, fNodes(0)
	, fHuffTopNode(NULL)
{
        /// nop
}

AliHLTHuffman::AliHLTHuffman(const AliHLTHuffman& other)
	: TNamed()
	, AliHLTLogging()
	, fMaxBits(other.fMaxBits)
	, fMaxValue(other.fMaxValue)
	, fNodes(other.fNodes)
	, fHuffTopNode(NULL) {
        /// nop
}

AliHLTHuffman::AliHLTHuffman(const char* name, UInt_t maxBits)
        : TNamed(name, name)
	, fMaxBits(maxBits)
	, fMaxValue((((AliHLTUInt64_t) 1) << maxBits) - 1)
	, fNodes((((AliHLTUInt64_t) 1) << maxBits))
	, fHuffTopNode(NULL)
 {
        /// standard constructor
	for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
		fNodes[i].SetValue(i);
	}
}

AliHLTHuffman::~AliHLTHuffman() {
        /// destructor, nop
}

const std::bitset<64>& AliHLTHuffman::Encode(const AliHLTUInt64_t v, AliHLTUInt64_t& codeLength) const {
        /// encode a value
	codeLength = 0;
	if (v <= fMaxValue) {
		// valid symbol/value
		if (fHuffTopNode) {
			// huffman code has been generated
			codeLength = fNodes[v].GetBinaryCodeLength();
			return fNodes[v].GetBinaryCode();
		} else {
		  HLTError("encoder '%s' does not seem to be initialized", GetName());
		}
	} else {
	  HLTError("encoder %s: value %llu exceeds range of %d bits", GetName(), v, GetMaxBits());
	}

	static const std::bitset<64> dummy;
	return dummy;
}

Bool_t AliHLTHuffman::Decode(std::bitset<64> bits, AliHLTUInt64_t& value) const {
	// TODO: check decoding logic, righ now it is just as written
	AliHLTHuffmanNode* currNode = fHuffTopNode;
	if (!currNode) return kFALSE;
	if (currNode->GetValue() >= 0) {
		// handle case with just one node - also quite unlikely
		value = currNode->GetValue();
		return kTRUE;
	}
	while (currNode) {
		if (bits[0] && currNode->GetLeftChild()) {
			// follow left branch
			currNode = currNode->GetLeftChild();
			bits >>= 1;
			if (currNode->GetValue() >= 0) {
				value = currNode->GetValue();
				return kTRUE;
			}
		}
		if (!bits[0] && currNode->GetRightChild()) {
			currNode = currNode->GetRightChild();
			bits >>= 1;
			if (currNode->GetValue() >= 0) {
				value = currNode->GetValue();
				return kTRUE;
			}
		}
	}
	value = ((AliHLTUInt64_t)1) << 63;
	return kFALSE;
}

Bool_t AliHLTHuffman::AddTrainingValue(const AliHLTUInt64_t value,
		const Float_t weight) {
	if (value > fMaxValue) {
		/* TODO: ERROR message */
		return kFALSE;
	}
	fNodes[value].AddWeight(weight);
	return kTRUE;
}

Bool_t AliHLTHuffman::GenerateHuffmanTree() {
	// insert pointer to nodes into ordered structure to build tree
	std::multiset<AliHLTHuffmanNode*, AliHLTHuffmanNode::less> nodeCollection;
	//	std::copy(fNodes.begin(), fNodes.end(),
	//			std::inserter(freq_coll, freq_coll.begin()));
	for (std::vector<AliHLTHuffmanLeaveNode>::iterator i = fNodes.begin(); i
			!= fNodes.end(); ++i) {
		nodeCollection.insert(&(*i));
	}
	while (nodeCollection.size() > 1) {
		// insert new node into structure, combining the two with lowest probability
		nodeCollection.insert(
				new AliHLTHuffmanTreeNode(*nodeCollection.begin(),
						*++nodeCollection.begin()));
		nodeCollection.erase(nodeCollection.begin());
		nodeCollection.erase(nodeCollection.begin());
	}
	//assign value
	fHuffTopNode = *nodeCollection.begin();
	fHuffTopNode->AssignCode();
	return kTRUE;
}

void AliHLTHuffman::Print(Option_t* option) const {
        std::cout << GetName() << endl;
        bool bPrintShort=strcmp(option, "short")==0;
	if (fHuffTopNode && !bPrintShort) {
		std::cout << "Huffman tree:" << endl;
		fHuffTopNode->Print();
	}
	Double_t uncompressedSize = 0;
	Double_t compressedSize = 0;
	Double_t totalWeight = 0;
	if (!bPrintShort)
	  std::cout << std::endl << "Huffman codes:" << std::endl;
	for (AliHLTUInt64_t i = 0; i <= fMaxValue; i++) {
	  if (!bPrintShort) fNodes[i].Print();
		totalWeight += fNodes[i].GetWeight();
		uncompressedSize += fNodes[i].GetWeight() * fMaxBits;
		compressedSize += fNodes[i].GetWeight()
				* fNodes[i].GetBinaryCodeLength();
	}
	if (uncompressedSize > 0) {
		std::cout << "compression ratio: " << compressedSize
				/ uncompressedSize << std::endl;
		std::cout << "<bits> uncompressed: " << uncompressedSize / totalWeight
				<< std::endl;
		std::cout << "<bits> compressed:   " << compressedSize / totalWeight
				<< std::endl;
	}
}

AliHLTHuffman& AliHLTHuffman::operator =(const AliHLTHuffman& other) {
	fMaxValue = other.fMaxValue;
	fNodes = other.fNodes;
	fHuffTopNode = NULL;
	return *this;
}

ClassImp(AliHLTHuffman)

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_automation.hxx"

////////////////////////////////////////////////////////////////////////////
////
////                  Windows ONLY
////
////////////////////////////////////////////////////////////////////////////

#include "registry_win.hxx"
#include <osl/thread.h>
#include <sal/macros.h>

String ReadRegistry( String aKey, String aValueName )
{
    String aRet;
    HKEY hBaseKey;
    if ( aKey.GetToken( 0, '\\' ).EqualsIgnoreCaseAscii( "HKEY_CURRENT_USER" ) )
        hBaseKey = HKEY_CURRENT_USER;
    else if ( aKey.GetToken( 0, '\\' ).EqualsIgnoreCaseAscii( "HKEY_LOCAL_MACHINE" ) )
        hBaseKey = HKEY_LOCAL_MACHINE;
    else
    {
        return aRet;
    }

    aKey.Erase( 0, aKey.Search( '\\' )+1 );

    HKEY hRegKey;

    if ( RegOpenKeyW( hBaseKey,
                reinterpret_cast<LPCWSTR>(aKey.GetBuffer()),
                &hRegKey ) == ERROR_SUCCESS )
    {
        LONG lRet;
        sal_Unicode PathW[_MAX_PATH ];
        DWORD lSize = SAL_N_ELEMENTS(PathW);
        DWORD Type = REG_SZ;

        lRet = RegQueryValueExW(hRegKey, reinterpret_cast<LPCWSTR>(aValueName.GetBuffer()), NULL, &Type, (LPBYTE)PathW, &lSize);

        if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ))
        {
            aRet = String( PathW );
        }

        RegCloseKey(hRegKey);
    }
    return aRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Fix windows build of automation<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_automation.hxx"

////////////////////////////////////////////////////////////////////////////
////
////                  Windows ONLY
////
////////////////////////////////////////////////////////////////////////////

#include <windows.h>
#include "registry_win.hxx"
#include <osl/thread.h>
#include <sal/macros.h>

String ReadRegistry( String aKey, String aValueName )
{
    String aRet;
    HKEY hBaseKey;
    if ( aKey.GetToken( 0, '\\' ).EqualsIgnoreCaseAscii( "HKEY_CURRENT_USER" ) )
        hBaseKey = HKEY_CURRENT_USER;
    else if ( aKey.GetToken( 0, '\\' ).EqualsIgnoreCaseAscii( "HKEY_LOCAL_MACHINE" ) )
        hBaseKey = HKEY_LOCAL_MACHINE;
    else
    {
        return aRet;
    }

    aKey.Erase( 0, aKey.Search( '\\' )+1 );

    HKEY hRegKey;

    if ( RegOpenKeyW( hBaseKey,
                reinterpret_cast<LPCWSTR>(aKey.GetBuffer()),
                &hRegKey ) == ERROR_SUCCESS )
    {
        LONG lRet;
        sal_Unicode PathW[_MAX_PATH ];
        DWORD lSize = SAL_N_ELEMENTS(PathW);
        DWORD Type = REG_SZ;

        lRet = RegQueryValueExW(hRegKey, reinterpret_cast<LPCWSTR>(aValueName.GetBuffer()), NULL, &Type, (LPBYTE)PathW, &lSize);

        if ((lRet == ERROR_SUCCESS) && (Type == REG_SZ))
        {
            aRet = String( PathW );
        }

        RegCloseKey(hRegKey);
    }
    return aRet;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*===- driver_2D.cpp - Driver -=================================================
*
*                                  DEMON
*
* This file is distributed under the BSD Open Source License. See LICENSE.TXT
* for details.
*
*===-----------------------------------------------------------------------===*/

#include "Runge_Kutta.h"

#include "ConfinementForce.h"
#include "RectConfinementForce.h"
#include "ShieldedCoulombForce.h"
#include "DragForce.h"
#include "DrivingForce.h"
#include "ThermalForce.h"
#include "ThermalForceLocalized.h"
#include "RotationalForce.h"
#include "TimeVaryingDragForce.h"
#include "TimeVaryingThermalForce.h"

#include <ctime>
#include <iostream>
using namespace std;

void help()
{
// 80 cols is ********************************************************************************
     cout << "\nOptions:\n" << endl
          << " -c noDefault.fits      continue run from file" << endl
          << " -C 1E-13               set confinementConst" << endl
          << " -D -1.0 10.0           use TimeVaryingDragForce; set scale, offset" << endl
          << " -e 5.0                 set simulation end time" << endl
          << " -f noDefaut.fits       use final positions and velocities from file" << endl
          << " -g 10.0                set gamma (magnitute of drag constant)" << endl
          << " -G                     initialize particles on square grid" << endl
          << " -h                     display Help (instead of running)" << endl
          << " -L 0.001 1E-14 1E-14   use ThermalForceLocalized; set rad, in/out therm vals" << endl
          << " -M 0.2 100             create Mach Code; set bullet velocity, mass factor" << endl
          << " -n 10                  set number of particles" << endl
          << " -o 0.01                set the data Output time step" << endl
          << " -O data.fits           set the name of the output file" << endl
          << " -r 0.01                set cloud radius (half side-length with -G)" << endl
          << " -R 1E-13 1E-12         use RectConfinementForce; set confineConstX,Y" << endl
          << " -s 2E4                 set coulomb shelding constant" << endl
          << " -S 1E-15 0.005 0.007   use RotationalForce; set strength, rmin, rmax" << endl
          << " -t 0.0001              set the simulation time step" << endl
          << " -T 1E-14               use ThermalForce; set thermal reduction factor" << endl
          << " -v 1E-14 0.0           use TimeVaryingThermalForce; set scale and offset" << endl
          << " -w 1E-13 0.007 0.00001 use DrivingForce; set amplitude, shift, driveConst" << endl << endl
          << " Notes: " << endl
          << " Parameters specified above represent the default values and accepted type," << endl
          << " with the exception of -c and -f, for which there are no default values." << endl
          << " -c appends to file; ignores all force flags (use -f to run with different" << endl
          << "    forces)." << endl
          << " -D uses strengthening drag if scale > 0, weakening drag if scale < 0." << endl
          << " -G overrides -c and -f." << endl
          << " -n expects even number, else will add 1 (required for SIMD)." << endl
          << " -S creates a shear layer between rmin = cloudsize/2 and" << endl
          << "    rmax = rmin + cloudsize/5." << endl
          << " -T runs with heat; otherwise, runs cold." << endl
          << " -v uses increases temp if scale > 0, decreasing temp if scale < 0." << endl
          << " -w creates acoustic waves along the x-axis (best with -R)." << endl << endl;
}

// check if force is used
void checkForce(const char option, const long usedForces, const ForceFlag flag)
{
	if(usedForces & flag)
	{
		cout << "\nError: -" << option << " already set.\n";
		help();
		exit(1);
	}
}

// check if force is in compatible with other force
void checkForce(char option1, char option2, long usedForces, ForceFlag flag1, ForceFlag flag2)
{
	checkForce(option1, usedForces, flag1);
	if(usedForces & flag2)
	{
		cout << "\nError: -" << option1 << " cannot be used with -" << option2 <<"\n";
		help();
		exit(1);
	}
}

// check no defaul command line flag
void checkOption(const int argc, char * const argv[], int i, const char option)
{
	if(i+1 >= argc || argv[i+1][0] == '-')
	{
		cout << "\nError: -" << option << " option incomplete.\n";
		help();
		exit(1);
	}
}

// check single default command line flag
int checkOption(const int argc, char * const argv[], int i, const char option,
                const string name, double * const value)
{
	if(i+1 >= argc || argv[i+1][0] == '-')
	{
		cout << "\nWarning: -" << option << " option incomplete.";
		cout << "\nUsing default " << name << " (" << *value << ").\n\n";
	}
	else
		*value = atof(argv[++i]);
	return i;
}

// check double default command line flag
int checkOption(const int argc, char * const argv[], int i, const char option,
                const string name1, double * const value1,
                const string name2, double * const value2)
{
	if(i+1 >= argc || argv[i+1][0] == '-')
	{
		cout << "\nWarning: -" << option << " option incomplete.";
		cout << "\nUsing default "<< name1 << " (" << *value1 << ") and " << name2 << " (" << *value2 << ").\n\n";
	}
	else
	{
		*value1 = atof(argv[++i]);
		i = checkOption(argc, argv, i, option, name2, value2);
	}
	return i;
}

// check triple default command line flag
int checkOption(const int argc, char * const argv[], int i, const char option,
                const string name1, double * const value1,
                const string name2, double * const value2,
                const string name3, double * const value3)
{
	if(i+1 >= argc || argv[i+1][0] == '-')
	{
		cout << "\nWarning: -" << option << " option incomplete.";
		cout << "\nUsing default "<< name1 << " (" << *value1 << "), " << name2 << " (" << *value2 << ") and " << name3 << " (" << *value3 << ").\n\n";
	}
	else
	{
		*value1 = atof(argv[++i]);
		i = checkOption(argc, argv, i, option, name2, value2, name3, value3);
	}
	return i;
}

// Test is character is a A..Z or a..Z
inline const bool isCharacter(const char c)
{
	return (c > 'a' && c < 'z') || (c > 'A' && c < 'Z');
}

// check double default command line flag calling negative numbers for the first item
int checkOptionWithNeg(const int argc, char * const argv[], int i, const char option,
                       const string name1, double * const value1,
                       const string name2, double * const value2)
{
	if(i+1 >= argc || (argv[i+1][0] == '-' && isCharacter(argv[i+1][1])))
	{
		cout << "\nWarning: -" << option << " option incomplete.";
		cout << "\nUsing default "<< name1 << " (" << *value1 << ") and " << name2 << " (" << *value2 << ").\n\n";
	}
	else
	{
		*value1 = atof(argv[++i]);
		i = checkOption(argc, argv, i, option, name2, value2);
	}
	return i;
}

// Cound number of flagged forces being used.
const unsigned int getNumForces(const long usedForces)
{
	unsigned int i = 0;
	if (usedForces & ConfinementForceFlag)
		++i;
	if (usedForces & DragForceFlag)
		++i;
	if (usedForces & ShieldedCoulombForceFlag)
		++i;
	if (usedForces & RectConfinementForceFlag)
		++i;
	if (usedForces & ThermalForceFlag)
		++i;
	if (usedForces & ThermalForceLocalizedFlag)
		++i;
	if (usedForces & DrivingForceFlag)
		++i;
	if (usedForces & RotationalForceFlag)
		++i;
	if (usedForces & TimeVaryingDragForceFlag)
		++i;
	if (usedForces & TimeVaryingThermalForceFlag)
		++i;
	return i;
}

// Check for error from fitsfile.
void checkFitsError(const int error, const int lineNumber)
{
	if(!error)
		return;

	char message[80];
	fits_read_errmsg(message);
	cout << "\nError: Fits file error " << error;
	cout << " at line number " << lineNumber << " (driver_2D.cpp)\n";
	cout << message << endl;
	exit(1);
}

// Delete specified fitsfile if it exists.
void deleteFitsFile(char * const filename, int * const error)
{
	//check for pre-existing data file:
	int exists = 0;
	fits_file_exists(filename, &exists, error);

	if(exists)
	{
		cout << "\nRemoving pre-existing " << filename << " file.\n\n";
		remove(filename);	//required by fits, else can't create
	}
	checkFitsError(*error, __LINE__);
}

int main (int argc, char * const argv[])
{
	long timer = time(NULL);		//start timer

	// Bit packed forces.
	long usedForces = 0;

	//object declarations:
	Cloud *cloud;
	Force **forceArray;		//new pointer to Force object (will set to array)

	//declare variables and set default values:
	unsigned int numParticles = 10;
	unsigned int numForces = 3;
	double startTime = 0.0;
	double simTimeStep = 0.0001;
	double dataTimeStep = 0.01;
	double endTime = 5;
	double cloudSize = 0.01;		//radius
	double confinementConst = 1E-13;	//confinementForce
	double confinementConstX = 1E-13;	//RectConfinementForce
	double confinementConstY = 1E-12;	//RectConfinementForce
	double shieldingConstant = 2E4;		//corresponds to 10*(ion debye length)
	double gamma = 10.0;
	double thermRed = 1E-14;		//default thermal reduction factor
	double thermRed1 = thermRed;		//default inner reduction factor (-L)	//TODO: inner or outer?
	double thermScale = 1E-14;		//default for TimeVaryingThermalForce
	double thermOffset = 0.0;		//default for TimeVaryingThermalForce
	double heatRadius = .001;		//apply thermal force only within this radius
	double driveConst = .00001;		//used in DrivingForce.cpp for waves
	double waveAmplitude = 1E-13;		//driving wave amplitude (default comparable to other forces throughout cloud)
	double waveShift = 0.007;		//driving wave shift
	double machSpeed = 0.2;			//firing speed for Mach Cone experiment
	double massFactor = 100;		//mass multiplier for fired Mach Cone particle
	double rmin = cloudSize/2.0;		//inner radius of shear layer
	double rmax = rmin + cloudSize/5.0;	//outer ratius of shear layer
	double rotConst = 1E-15;		//rotational force in shear layer
	double dragScale = -1.0;		//used in TimeVaryingDragForce
	int continueFileIndex = 0;		//Index of argv array that holds the file name of the fitsfile to continue.
	int finalsFileIndex = 0;		//Index of argv array that holds the file name of the fitsfile to use finals of.
	int outputFileIndex = 0;		//Index of argv array that holds the file name of the fitsfile to output.
	bool grid = false;			//true -> initialize particles on grid
	bool Mach = false;			//true -> perform Mach Cone experiment

	//process command line flags:
	for(int i = 0; i < argc; i++)
	{
		switch(argv[i][1])
		{
			case 'c': // "c"ontinue from file:
				checkOption(argc, argv, i, 'c');
				continueFileIndex = ++i;
				break;
			case 'C': // set "C"onfinementConst:
				checkOption(argc, argv, i, 'C');
				confinementConst = atof(argv[++i]);	//store confinementConst
				break;
			case 'D': // use TimeVarying"D"ragForce:
				checkForce('D', usedForces, TimeVaryingDragForceFlag);
				usedForces |= TimeVaryingDragForceFlag;
				// dragScale needs to allow negative numbers.
				i = checkOptionWithNeg(argc, argv, i, 'D', "scale factor", &dragScale, "offset", &gamma);
				break;
			case 'e': // set "e"nd time:
				checkOption(argc, argv, i, 'e');
				//WARNING: Assumes integer input!
				endTime = atoi(argv[++i]);	//store end time
				break;
			case 'f': // use "f"inal positions and velocities from previous run:
				checkOption(argc, argv, i, 'f');
				finalsFileIndex = ++i;
				break;
			case 'g': // set "g"amma:
				checkOption(argc, argv, i, 'g');
				//WARNING: Assumes double input!
				gamma = atof(argv[++i]);	//store gamma
				break;
			case 'G': // initialize on "G"rid:
				grid = true;
				break;
			case 'h': // display "h"elp:
				help();
				exit(1);
				break;
			case 'L': // perform laser heating experiment:
				checkForce('L', 'T', usedForces, ThermalForceLocalizedFlag, ThermalForceFlag);
				checkForce('L', 'v', usedForces, ThermalForceLocalizedFlag, TimeVaryingThermalForceFlag);
				usedForces |= ThermalForceLocalizedFlag;
				i = checkOption(argc, argv, i, 'S', "radius", &heatRadius, "heat factor1", &thermRed, "heat factor2", &thermRed1);
				break;
			case 'M': // perform "M"ach Cone experiment:
				Mach = true;
				i = checkOption(argc, argv, i, 'M', "velocity", &machSpeed, "mass", &massFactor);
				break;
			case 'n': // set "n"umber of particles:
				checkOption(argc, argv, i, 'n');
				//WARNING: Assumes integer input!
				numParticles = atoi(argv[++i]);	//store number of particles
				if((numParticles % 2) != 0)	//odd
				{
					cout << "\nEven number of particles required for SIMD.";
					cout << "\nIncrementing number of particles to " << ++numParticles << endl;
				}
				break;
			case 'o': // set dataTimeStep, which conrols "o"utput rate
				checkOption(argc, argv, i, 'o');
				dataTimeStep = atof(argv[++i]);	//store timestep
				break;
			case 'O': // name "O"utput file
				checkOption(argc, argv, i, 'O');
				outputFileIndex = ++i;
				break;
			case 'r': // set cloud "r"adius:
				checkOption(argc, argv, i, 'r');
				cloudSize = atof(argv[++i]);	//store cloud size
				break;
			case 'R': // use "R"ectangular confinement:
				checkForce('R', usedForces, RectConfinementForceFlag);
				usedForces |= RectConfinementForceFlag;
				i = checkOption(argc, argv, i, 'R', "confine constantX", &confinementConstX, "confine constantX", &confinementConstY);
				break;
			case 's': // set "s"hielding constant:
				checkOption(argc, argv, i, 's');
				shieldingConstant = atof(argv[++i]);	//store shielding constant
				break;
			case 'S': // rotational "S"hear:
				checkForce('S', usedForces, RotationalForceFlag);
				usedForces |= RotationalForceFlag;
				i = checkOption(argc, argv, i, 'S', "force constant", &rotConst, "rmin", &rmin, "rmax", &rmax);
				break;
			case 't': // set "t"imestep:
				i = checkOption(argc, argv, i, 't', "time step", &simTimeStep);
				if(simTimeStep == 0.0)		//prevent divide-by-zero error
				{
					cout << "\nError: simTimeStep set to 0.0 with -t.";
					cout << "\nTerminating to prevent divide-by-zero.\n\n";
					help();
					exit(1);
				}
				break;
			case 'T': // set "T"emperature reduction factor:
				checkForce('T', 'L', usedForces, ThermalForceFlag, ThermalForceLocalizedFlag);
				checkForce('T', 'v', usedForces, ThermalForceFlag, TimeVaryingThermalForceFlag);
				usedForces |= ThermalForceFlag;
				i = checkOption(argc, argv, i, 'T', "heat factor", &thermRed);
				break;
			case 'v': // set time "v"arying thermal force
				checkForce('v', 'T', usedForces, TimeVaryingThermalForceFlag, ThermalForceFlag);
				checkForce('v', 'L', usedForces, TimeVaryingThermalForceFlag, ThermalForceLocalizedFlag);
				usedForces |= TimeVaryingThermalForceFlag;
				i = checkOptionWithNeg(argc, argv, i, 'v', "heat value scale", &thermScale, "heat value offset", &thermOffset);
				break;
			case 'w': // drive "w"aves:
				checkForce('w', usedForces, DrivingForceFlag);
				usedForces |= DrivingForceFlag;
				i = checkOption(argc, argv, i, 'w', "amplitude", &waveAmplitude, "wave shift", &waveShift, "driving constant", &driveConst);
				break;
			default: // default (expressionless)
				break;
		}
	}

	if (!(usedForces & TimeVaryingDragForceFlag))
		usedForces |= DragForceFlag;
	if (!(usedForces & RectConfinementForceFlag))
		usedForces |= ConfinementForceFlag;
	usedForces |= ShieldedCoulombForceFlag;

/*-----------------------------------------------------------------------------
 * Initialize cloud:
-----------------------------------------------------------------------------*/
	//declare fits file and error:
	fitsfile *file;
	int error = 0;

	if(grid)
		cloud = Cloud::initializeGrid(numParticles, cloudSize);
	else if(finalsFileIndex)
	{
		//check if file exists:
		int exists = 0;
		fits_file_exists(argv[finalsFileIndex], &exists, &error);
		if(exists != 1)
		{
			cout << "\nError: " << argv[finalsFileIndex] << " does not exist.\n\n";
			help();
			exit(1);
		}
		checkFitsError(error, __LINE__);

		cout << "\nInitializing with " << argv[finalsFileIndex] << ".\n\n";

		//open file:
		fits_open_file(&file, argv[finalsFileIndex], READONLY, &error);	//file pointer, file name (char), read only, error
		checkFitsError(error, __LINE__);

		//initialize with last time step from file:
		cloud = Cloud::initializeFromFile(file, &error, NULL);
		checkFitsError(error, __LINE__);

		//close file:
 		fits_close_file(file, &error);
		checkFitsError(error, __LINE__);
	}
	else if (continueFileIndex)
	{
		//check if file exists:
		int exists = 0;
		fits_file_exists(argv[continueFileIndex], &exists, &error);
		if(exists != 1)
		{
			cout << "\nError: " << argv[continueFileIndex] << " does not exist.\n\n";
			help();
			exit(1);
		}
		checkFitsError(error, __LINE__);

		cout << "\nInitializing with " << argv[continueFileIndex] << ".\n\n";

		//open file:
		fits_open_file(&file, argv[continueFileIndex], READWRITE, &error);	//file pointer, file name (char), read/write, error
		checkFitsError(error, __LINE__);

		//use the same forces:
		fits_read_key_lng(file, const_cast<char *> ("FORCES"), &usedForces, NULL, &error);
		checkFitsError(error, __LINE__);

		//initialize with last time step from file:
		cloud = Cloud::initializeFromFile(file, &error, &startTime);
		checkFitsError(error, __LINE__);
	}
	else
		cloud = Cloud::initializeNew(numParticles, cloudSize);

	// Create a new file if we aren't continueing one.
	if (!continueFileIndex)
	{
		if(outputFileIndex)	//use specified file name
		{
			deleteFitsFile(argv[outputFileIndex], &error);
			fits_create_file(&file, argv[outputFileIndex], &error);
			checkFitsError(error, __LINE__);

			//create "proper" primary HDU
			//	prevents fits from shitting itself when creating binary tables
			fits_create_img(file, 16, 0, NULL, &error);
			checkFitsError(error, __LINE__);
		}
		else			//use default file name
		{
			deleteFitsFile(const_cast<char *> ("data.fits"), &error);
			fits_create_file(&file, const_cast<char *> ("data.fits"), &error);
			checkFitsError(error, __LINE__);

			//create "proper" primary HDU
			//	prevents fits from shitting itself when creating binary tables
			fits_create_img(file, 16, 0, NULL, &error);
			checkFitsError(error, __LINE__);
		}
	}

/*-----------------------------------------------------------------------------
 * This concludes initialization of cloud.
 * Initialize array of Force objects:
-----------------------------------------------------------------------------*/
    cout << "Initializing forces.\n\n";

	numForces = getNumForces(usedForces);
	forceArray = new Force*[numForces];
	unsigned int index = 0;
	if (usedForces & ConfinementForceFlag)
		forceArray[index++] = new ConfinementForce(cloud, confinementConst);
	if (usedForces & DragForceFlag)
		forceArray[index++] = new DragForce(cloud, gamma);
	if (usedForces & ShieldedCoulombForceFlag)
		forceArray[index++] = new ShieldedCoulombForce(cloud, shieldingConstant);
	if (usedForces & RectConfinementForceFlag)
		forceArray[index++] = new RectConfinementForce(cloud, confinementConstX, confinementConstY);
	if (usedForces & ThermalForceFlag)
		forceArray[index++] = new ThermalForce(cloud, thermRed);
	if (usedForces & ThermalForceLocalizedFlag)
		forceArray[index++] = new ThermalForceLocalized(cloud, thermRed, thermRed1, heatRadius);
	if (usedForces & DrivingForceFlag)
		forceArray[index++] = new DrivingForce(cloud, driveConst, waveAmplitude, waveShift);
	if (usedForces & RotationalForceFlag)
		forceArray[index++] = new RotationalForce(cloud, rmin, rmax, rotConst);
	if (usedForces & TimeVaryingDragForceFlag)
		forceArray[index++] = new TimeVaryingDragForce(cloud, dragScale, gamma);
	if (usedForces & TimeVaryingThermalForceFlag)
		forceArray[index++] = new TimeVaryingThermalForce(cloud, thermScale, thermOffset);

	// Initalize forces from fits file if this is continuing a file otherwise write force parameters to the fitsfile.
	if(continueFileIndex)
	{
		for (unsigned int i = 0; i < numForces; i++)
			forceArray[i]->readForce(file, &error);
		checkFitsError(error, __LINE__);
	}
	else
	{
		for (unsigned int i = 0; i < numForces; i++)
            forceArray[i]->writeForce(file, &error);
		checkFitsError(error, __LINE__);
	}

/*-----------------------------------------------------------------------------
 * Commence Runge-Kutta algorithm:
-----------------------------------------------------------------------------*/

	//write initial data:
	if (!continueFileIndex)
	{
		cloud->writeCloudSetup(file, &error);
		checkFitsError(error, __LINE__);
	}
	else
	{
		fits_movnam_hdu(file, BINARY_TBL, const_cast<char *> ("TIME_STEP"), 0, &error);
		checkFitsError(error, __LINE__);
	}

	if(Mach)
	{
		//reserve particle 1 for mach experiment
		cloud->x[0] = -2.0*cloudSize;
		cloud->y[0] = 0.0;
		cloud->Vx[0] = machSpeed;
		cloud->Vy[0] = 0.0;
		cloud->mass[0] = massFactor*cloud->mass[0];
	}

	Runge_Kutta rk4(cloud, forceArray, simTimeStep, numForces, startTime);

	cout << "Commencing Runge-Kutta algorithm.\n\n";

	//execute simulation for desired length of time:
	while(startTime < endTime)
	{
		//call Runge-Kutta algorithm:
		rk4.moveParticles(startTime += dataTimeStep);
		//write positions and velocities:
		cloud->writeTimeStep(file, &error, rk4.currentTime);
		cout << rk4.currentTime << endl;
	}

	cout << "Runge-Kutta algorithm complete.\n\n";

/*-----------------------------------------------------------------------------
 * This concludes the Runge-Kutta algorithm.
-----------------------------------------------------------------------------*/

	//close fits file:
	fits_close_file(file, &error);

	//calculate and display elapsed time:
	long seconds = time(NULL) - timer;
	long minutes = seconds/60;
	long hours = minutes/60;
	minutes -= 60*hours;
	seconds -= minutes*60;
	seconds -= hours*3600;
	cout << "Time elapsed: " << hours << " hours, " << minutes << " minutes, " << seconds << " seconds.\n\n";

	// Clean up objects.
	for (unsigned int i = 0; i < numForces; i++)
		delete forceArray[i];
	delete[] forceArray;
	delete cloud;

	return 0;
}
<commit_msg>Delete driver_2D.cpp since it was renamed to driver.cpp<commit_after><|endoftext|>


<commit_before>#include "core.h"
#include "performance_model.h"
#include "fastforward_performance_model.h"
#include "branch_predictor.h"
#include "simulator.h"
#include "simple_performance_model.h"
#include "iocoom_performance_model.h"
#include "magic_performance_model.h"
#include "oneipc_performance_model.h"
#include "interval_performance_model.h"
#include "core_manager.h"
#include "config.hpp"
#include "stats.h"
#include "dvfs_manager.h"

PerformanceModel* PerformanceModel::create(Core* core)
{
   String type;

   try {
      type = Sim()->getCfg()->getStringArray("perf_model/core/type", core->getId());
   } catch (...) {
      LOG_PRINT_ERROR("No perf model type provided.");
   }

   if (type == "iocoom")
      return new IOCOOMPerformanceModel(core);
   else if (type == "simple")
      return new SimplePerformanceModel(core);
   else if (type == "magic")
      return new MagicPerformanceModel(core);
   else if (type == "oneipc")
      return new OneIPCPerformanceModel(core);
   else if (type == "interval")
   {
      // The interval model needs the branch misprediction penalty
      int mispredict_penalty = Sim()->getCfg()->getIntArray("perf_model/branch_predictor/mispredict_penalty", core->getId());
      return new IntervalPerformanceModel(core, mispredict_penalty);
   }
   else
   {
      LOG_PRINT_ERROR("Invalid perf model type: %s", type.c_str());
      return NULL;
   }
}

// Public Interface
PerformanceModel::PerformanceModel(Core *core)
   : m_core(core)
   , m_enabled(false)
   , m_fastforward(false)
   , m_fastforward_model(new FastforwardPerformanceModel(core, this))
   , m_hold(false)
   , m_instruction_count(0)
   , m_elapsed_time(Sim()->getDvfsManager()->getCoreDomain(core->getId()))
   , m_idle_elapsed_time(Sim()->getDvfsManager()->getCoreDomain(core->getId()))
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
   , m_basic_block_queue(64) // Reduce from default size to keep memory issue time more or less synchronized
   #else
   , m_basic_block_queue(128) // Need a bit more space for when the dyninsninfo items aren't coming in yet, or for a boatload of TLBMissInstructions
   #endif
   , m_dynamic_info_queue(640) // Required for REPZ CMPSB instructions with max counts of 256 (256 * 2 memory accesses + space for other dynamic instructions)
   , m_current_ins_index(0)
{
   m_bp = BranchPredictor::create(core->getId());

   registerStatsMetric("performance_model", core->getId(), "instruction_count", &m_instruction_count);

   registerStatsMetric("performance_model", core->getId(), "elapsed_time", &m_elapsed_time);
   registerStatsMetric("performance_model", core->getId(), "idle_elapsed_time", &m_idle_elapsed_time);

   registerStatsMetric("performance_model", core->getId(), "cpiStartTime", &m_cpiStartTime);

   registerStatsMetric("performance_model", core->getId(), "cpiSyncFutex", &m_cpiSyncFutex);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadMutex", &m_cpiSyncPthreadMutex);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadCond", &m_cpiSyncPthreadCond);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadBarrier", &m_cpiSyncPthreadBarrier);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncJoin", &m_cpiSyncJoin);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPause", &m_cpiSyncPause);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncSleep", &m_cpiSyncSleep);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncUnscheduled", &m_cpiSyncUnscheduled);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncDvfsTransition", &m_cpiSyncDvfsTransition);

   registerStatsMetric("performance_model", core->getId(), "cpiRecv", &m_cpiRecv);
}

PerformanceModel::~PerformanceModel()
{
   delete m_bp;
   delete m_fastforward_model;
}

void PerformanceModel::enable()
{
   m_enabled = true;
}

void PerformanceModel::disable()
{
   m_enabled = false;
}

void PerformanceModel::countInstructions(IntPtr address, UInt32 count)
{
   if (m_fastforward)
   {
      m_fastforward_model->countInstructions(address, count);
   }
}

void PerformanceModel::queueDynamicInstruction(Instruction *i)
{
   if (i->getType() == INST_SPAWN)
   {
      SpawnInstruction const* spawn_insn = dynamic_cast<SpawnInstruction const*>(i);
      LOG_ASSERT_ERROR(spawn_insn != NULL, "Expected a SpawnInstruction, but did not get one.");
      setElapsedTime(spawn_insn->getTime());
      return;
   }

   if (!m_enabled)
   {
      // queueBasicBlock and pushDynamicInstructionInfo are not being called in fast-forward by using instrumentation modes
      // For queueDynamicInstruction, which are used all over the place, ignore them manually
      delete i;
      return;
   }

   if (m_fastforward)
   {
      if (i->isIdle())
         handleIdleInstruction(i);
      else
         m_fastforward_model->queueDynamicInstruction(i);
   }
   else
   {
      BasicBlock *bb = new BasicBlock(true);
      bb->push_back(i);
      #ifdef ENABLE_PERF_MODEL_OWN_THREAD
         m_basic_block_queue.push_wait(bb);
      #else
         m_basic_block_queue.push(bb);
      #endif
   }
}

void PerformanceModel::queueBasicBlock(BasicBlock *basic_block)
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_basic_block_queue.push_wait(basic_block);
   #else
      m_basic_block_queue.push(basic_block);
   #endif
}

void PerformanceModel::handleIdleInstruction(Instruction *instruction)
{
   if (instruction->getType() == INST_SYNC)
   {
      // Keep track of the type of Sync instruction and it's latency to calculate CPI numbers
      SyncInstruction const* sync_insn = dynamic_cast<SyncInstruction const*>(instruction);
      LOG_ASSERT_ERROR(sync_insn != NULL, "Expected a SyncInstruction, but did not get one.");

      // Thread may wake up on a different core than where it went to sleep, and/or a different thread
      // may have run on this core while the thread was asleep
      // So, compute actual delay between our last local time and the time we're supposed to wake up
      SubsecondTime time_begin = getElapsedTime();
      SubsecondTime time_end = sync_insn->getTime();
      SubsecondTime insn_cost;

      if (time_end > time_begin)
         insn_cost = time_end - time_begin;
      else
         // Core may have executed other instructions already
         insn_cost = SubsecondTime::Zero();

      switch(sync_insn->getSyncType()) {
      case(SyncInstruction::FUTEX):
         m_cpiSyncFutex += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_MUTEX):
         m_cpiSyncPthreadMutex += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_COND):
         m_cpiSyncPthreadCond += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_BARRIER):
         m_cpiSyncPthreadBarrier += insn_cost;
         break;
      case(SyncInstruction::JOIN):
         m_cpiSyncJoin += insn_cost;
         break;
      case(SyncInstruction::PAUSE):
         m_cpiSyncPause += insn_cost;
         break;
      case(SyncInstruction::SLEEP):
         m_cpiSyncSleep += insn_cost;
         break;
      case(SyncInstruction::UNSCHEDULED):
         m_cpiSyncUnscheduled += insn_cost;
         break;
      default:
         LOG_ASSERT_ERROR(false, "Unexpected SyncInstruction::type_t enum type. (%d)", sync_insn->getSyncType());
      }
      incrementIdleElapsedTime(insn_cost);
   }
   else if (instruction->getType() == INST_DELAY)
   {
      SubsecondTime insn_cost = instruction->getCost(getCore());
      DelayInstruction const* delay_insn = dynamic_cast<DelayInstruction const*>(instruction);
      LOG_ASSERT_ERROR(delay_insn != NULL, "Expected a DelayInstruction, but did not get one.");
      switch(delay_insn->getDelayType()) {
      case(DelayInstruction::DVFS_TRANSITION):
         m_cpiSyncDvfsTransition += insn_cost;
         break;
      default:
         LOG_ASSERT_ERROR(false, "Unexpected DelayInstruction::type_t enum type. (%d)", delay_insn->getDelayType());
      }
      incrementIdleElapsedTime(insn_cost);
   }
   else if (instruction->getType() == INST_RECV)
   {
      SubsecondTime insn_cost = instruction->getCost(getCore());
      __attribute__((unused)) RecvInstruction const* recv_insn = dynamic_cast<RecvInstruction const*>(instruction);
      LOG_ASSERT_ERROR(recv_insn != NULL, "Expected a RecvInstruction, but did not get one.");
      m_cpiRecv += insn_cost;
      incrementIdleElapsedTime(insn_cost);
   }
   else
   {
      LOG_PRINT_ERROR("Unexpectedly received something other than a Sync or Recv Instruction");
   }
}

void PerformanceModel::iterate()
{
   // Because we will sometimes not have info available (we will throw
   // a DynamicInstructionInfoNotAvailable), we need to be able to
   // continue from the middle of a basic block. m_current_ins_index
   // tracks which instruction we are currently on within the basic
   // block.

   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
   while (m_basic_block_queue.size() > 0)
   #else
   while (m_basic_block_queue.size() > 1)
   #endif
   {
      // While the functional thread is waiting because of clock skew minimization, wait here as well
      #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      while(m_hold)
         sched_yield();
      #endif

      BasicBlock *current_bb = m_basic_block_queue.front();

      for( ; m_current_ins_index < current_bb->size(); m_current_ins_index++)
      {
         Instruction *ins = current_bb->at(m_current_ins_index);
         if (ins->isIdle()) {
            handleIdleInstruction(ins);
         } else {
            bool res = handleInstruction(ins);
            if (!res)
               // DynamicInstructionInfo not available
               return;
         }
      }

      if (current_bb->isDynamic())
         delete current_bb;

      m_basic_block_queue.pop();
      m_current_ins_index = 0; // move to beginning of next bb
   }
}

void PerformanceModel::pushDynamicInstructionInfo(DynamicInstructionInfo &i)
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.push_wait(i);
   #else
      m_dynamic_info_queue.push(i);
   #endif
}

void PerformanceModel::popDynamicInstructionInfo()
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.pop_wait();
   #else
      m_dynamic_info_queue.pop();
   #endif
}

DynamicInstructionInfo* PerformanceModel::getDynamicInstructionInfo()
{
   // Information is needed to model the instruction, but isn't
   // available. This is handled in iterate() by returning early and
   // continuing from that instruction later.

   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.empty_wait();
   #else
      if (m_dynamic_info_queue.empty())
         return NULL;
   #endif

   return &m_dynamic_info_queue.front();
}

DynamicInstructionInfo* PerformanceModel::getDynamicInstructionInfo(const Instruction &instruction, bool exec_loads)
{
   DynamicInstructionInfo* info = getDynamicInstructionInfo();

   if (!info)
      return NULL;

   LOG_ASSERT_ERROR(info->eip == instruction.getAddress(), "Expected dynamic info for eip %lx \"%s\", got info for eip %lx", instruction.getAddress(), instruction.getDisassembly().c_str(), info->eip);

   if ((info->type == DynamicInstructionInfo::MEMORY_READ || info->type == DynamicInstructionInfo::MEMORY_WRITE)
      && info->memory_info.hit_where == HitWhere::UNKNOWN)
   {
      if (info->memory_info.executed)
      {
         if (exec_loads)
         {
            MemoryResult res = m_core->accessMemory(
               /*instruction.isAtomic()
                  ? (info->type == DynamicInstructionInfo::MEMORY_READ ? Core::LOCK : Core::UNLOCK)
                  :*/ Core::NONE, // Just as in pin/lite/memory_modeling.cc, make the second part of an atomic update implicit
               info->type == DynamicInstructionInfo::MEMORY_READ ? (instruction.isAtomic() ? Core::READ_EX : Core::READ) : Core::WRITE,
               info->memory_info.addr,
               NULL,
               info->memory_info.size,
               Core::MEM_MODELED_RETURN,
               instruction.getAddress()
            );
            info->memory_info.latency = res.latency;
            info->memory_info.hit_where = res.hit_where;
         }
         else
         {
            info->memory_info.latency = SubsecondTime::Zero();
            info->memory_info.hit_where = HitWhere::UNKNOWN;
         }
      }
      else
      {
         info->memory_info.latency = 1 * m_core->getDvfsDomain()->getPeriod(); // 1 cycle latency
         info->memory_info.hit_where = HitWhere::PREDICATE_FALSE;
      }
   }

   return info;
}

void PerformanceModel::incrementIdleElapsedTime(SubsecondTime time)
{
   // Advance the idle time
   m_idle_elapsed_time.addLatency(time);
   // Advance the total (non-idle + idle) time
   incrementElapsedTime(time);
   // Let the performance model know time has jumped
   notifyElapsedTimeUpdate();
   if (m_fastforward)
      m_fastforward_model->notifyElapsedTimeUpdate();
}

// Only called at the start of the simulation (SPAWN_INST)
void PerformanceModel::setElapsedTime(SubsecondTime time)
{
   // TODO: what happens when a core is reused? (See streamcluster, Redmine #37)
   // Is the initial time for the second thread set with another SPAWN_INST? Or maybe a RECV_INST?
   // When using the scheduler and moving an existing thread to this core, SPAWN_INST is now used.
   //LOG_ASSERT_ERROR(getElapsedTime() == SubsecondTime::Zero(), "setElapsedTime() can only be called when the current time is 0 (via SPAWN_INSN).");
   LOG_ASSERT_ERROR(time >= getElapsedTime(), "setElapsedTime() cannot go backwards in time");

   m_cpiStartTime += time - getElapsedTime();
   // All time up to now was idle
   m_idle_elapsed_time.setElapsedTime(time);
   // Set the elapsed time
   m_elapsed_time.setElapsedTime(time);
   // Let the performance model know time has jumped
   notifyElapsedTimeUpdate();
   if (m_fastforward)
      m_fastforward_model->notifyElapsedTimeUpdate();
}
<commit_msg>[PATCH 40/85] [performance_model] Always handle idle instructions immediately rather than pushing them in the basic block queue, this should simplify the performance models and how they have to keep track of idle threads<commit_after>#include "core.h"
#include "performance_model.h"
#include "fastforward_performance_model.h"
#include "branch_predictor.h"
#include "simulator.h"
#include "simple_performance_model.h"
#include "iocoom_performance_model.h"
#include "magic_performance_model.h"
#include "oneipc_performance_model.h"
#include "interval_performance_model.h"
#include "core_manager.h"
#include "config.hpp"
#include "stats.h"
#include "dvfs_manager.h"

PerformanceModel* PerformanceModel::create(Core* core)
{
   String type;

   try {
      type = Sim()->getCfg()->getStringArray("perf_model/core/type", core->getId());
   } catch (...) {
      LOG_PRINT_ERROR("No perf model type provided.");
   }

   if (type == "iocoom")
      return new IOCOOMPerformanceModel(core);
   else if (type == "simple")
      return new SimplePerformanceModel(core);
   else if (type == "magic")
      return new MagicPerformanceModel(core);
   else if (type == "oneipc")
      return new OneIPCPerformanceModel(core);
   else if (type == "interval")
   {
      // The interval model needs the branch misprediction penalty
      int mispredict_penalty = Sim()->getCfg()->getIntArray("perf_model/branch_predictor/mispredict_penalty", core->getId());
      return new IntervalPerformanceModel(core, mispredict_penalty);
   }
   else
   {
      LOG_PRINT_ERROR("Invalid perf model type: %s", type.c_str());
      return NULL;
   }
}

// Public Interface
PerformanceModel::PerformanceModel(Core *core)
   : m_core(core)
   , m_enabled(false)
   , m_fastforward(false)
   , m_fastforward_model(new FastforwardPerformanceModel(core, this))
   , m_hold(false)
   , m_instruction_count(0)
   , m_elapsed_time(Sim()->getDvfsManager()->getCoreDomain(core->getId()))
   , m_idle_elapsed_time(Sim()->getDvfsManager()->getCoreDomain(core->getId()))
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
   , m_basic_block_queue(64) // Reduce from default size to keep memory issue time more or less synchronized
   #else
   , m_basic_block_queue(128) // Need a bit more space for when the dyninsninfo items aren't coming in yet, or for a boatload of TLBMissInstructions
   #endif
   , m_dynamic_info_queue(640) // Required for REPZ CMPSB instructions with max counts of 256 (256 * 2 memory accesses + space for other dynamic instructions)
   , m_current_ins_index(0)
{
   m_bp = BranchPredictor::create(core->getId());

   registerStatsMetric("performance_model", core->getId(), "instruction_count", &m_instruction_count);

   registerStatsMetric("performance_model", core->getId(), "elapsed_time", &m_elapsed_time);
   registerStatsMetric("performance_model", core->getId(), "idle_elapsed_time", &m_idle_elapsed_time);

   registerStatsMetric("performance_model", core->getId(), "cpiStartTime", &m_cpiStartTime);

   registerStatsMetric("performance_model", core->getId(), "cpiSyncFutex", &m_cpiSyncFutex);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadMutex", &m_cpiSyncPthreadMutex);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadCond", &m_cpiSyncPthreadCond);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPthreadBarrier", &m_cpiSyncPthreadBarrier);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncJoin", &m_cpiSyncJoin);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncPause", &m_cpiSyncPause);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncSleep", &m_cpiSyncSleep);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncUnscheduled", &m_cpiSyncUnscheduled);
   registerStatsMetric("performance_model", core->getId(), "cpiSyncDvfsTransition", &m_cpiSyncDvfsTransition);

   registerStatsMetric("performance_model", core->getId(), "cpiRecv", &m_cpiRecv);
}

PerformanceModel::~PerformanceModel()
{
   delete m_bp;
   delete m_fastforward_model;
}

void PerformanceModel::enable()
{
   m_enabled = true;
}

void PerformanceModel::disable()
{
   m_enabled = false;
}

void PerformanceModel::countInstructions(IntPtr address, UInt32 count)
{
   if (m_fastforward)
   {
      m_fastforward_model->countInstructions(address, count);
   }
}

void PerformanceModel::queueDynamicInstruction(Instruction *i)
{
   if (i->getType() == INST_SPAWN)
   {
      SpawnInstruction const* spawn_insn = dynamic_cast<SpawnInstruction const*>(i);
      LOG_ASSERT_ERROR(spawn_insn != NULL, "Expected a SpawnInstruction, but did not get one.");
      setElapsedTime(spawn_insn->getTime());
      return;
   }

   if (!m_enabled)
   {
      // queueBasicBlock and pushDynamicInstructionInfo are not being called in fast-forward by using instrumentation modes
      // For queueDynamicInstruction, which are used all over the place, ignore them manually
      delete i;
      return;
   }

   if (i->isIdle())
   {
      handleIdleInstruction(i);
   }
   else
   {
      if (m_fastforward)
      {
         m_fastforward_model->queueDynamicInstruction(i);
      }
      else
      {
         BasicBlock *bb = new BasicBlock(true);
         bb->push_back(i);
         #ifdef ENABLE_PERF_MODEL_OWN_THREAD
            m_basic_block_queue.push_wait(bb);
         #else
            m_basic_block_queue.push(bb);
         #endif
      }
   }
}

void PerformanceModel::queueBasicBlock(BasicBlock *basic_block)
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_basic_block_queue.push_wait(basic_block);
   #else
      m_basic_block_queue.push(basic_block);
   #endif
}

void PerformanceModel::handleIdleInstruction(Instruction *instruction)
{
   if (instruction->getType() == INST_SYNC)
   {
      // Keep track of the type of Sync instruction and it's latency to calculate CPI numbers
      SyncInstruction const* sync_insn = dynamic_cast<SyncInstruction const*>(instruction);
      LOG_ASSERT_ERROR(sync_insn != NULL, "Expected a SyncInstruction, but did not get one.");

      // Thread may wake up on a different core than where it went to sleep, and/or a different thread
      // may have run on this core while the thread was asleep
      // So, compute actual delay between our last local time and the time we're supposed to wake up
      SubsecondTime time_begin = getElapsedTime();
      SubsecondTime time_end = sync_insn->getTime();
      SubsecondTime insn_cost;

      if (time_end > time_begin)
         insn_cost = time_end - time_begin;
      else
         // Core may have executed other instructions already
         insn_cost = SubsecondTime::Zero();

      switch(sync_insn->getSyncType()) {
      case(SyncInstruction::FUTEX):
         m_cpiSyncFutex += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_MUTEX):
         m_cpiSyncPthreadMutex += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_COND):
         m_cpiSyncPthreadCond += insn_cost;
         break;
      case(SyncInstruction::PTHREAD_BARRIER):
         m_cpiSyncPthreadBarrier += insn_cost;
         break;
      case(SyncInstruction::JOIN):
         m_cpiSyncJoin += insn_cost;
         break;
      case(SyncInstruction::PAUSE):
         m_cpiSyncPause += insn_cost;
         break;
      case(SyncInstruction::SLEEP):
         m_cpiSyncSleep += insn_cost;
         break;
      case(SyncInstruction::UNSCHEDULED):
         m_cpiSyncUnscheduled += insn_cost;
         break;
      default:
         LOG_ASSERT_ERROR(false, "Unexpected SyncInstruction::type_t enum type. (%d)", sync_insn->getSyncType());
      }
      incrementIdleElapsedTime(insn_cost);
   }
   else if (instruction->getType() == INST_DELAY)
   {
      SubsecondTime insn_cost = instruction->getCost(getCore());
      DelayInstruction const* delay_insn = dynamic_cast<DelayInstruction const*>(instruction);
      LOG_ASSERT_ERROR(delay_insn != NULL, "Expected a DelayInstruction, but did not get one.");
      switch(delay_insn->getDelayType()) {
      case(DelayInstruction::DVFS_TRANSITION):
         m_cpiSyncDvfsTransition += insn_cost;
         break;
      default:
         LOG_ASSERT_ERROR(false, "Unexpected DelayInstruction::type_t enum type. (%d)", delay_insn->getDelayType());
      }
      incrementIdleElapsedTime(insn_cost);
   }
   else if (instruction->getType() == INST_RECV)
   {
      SubsecondTime insn_cost = instruction->getCost(getCore());
      __attribute__((unused)) RecvInstruction const* recv_insn = dynamic_cast<RecvInstruction const*>(instruction);
      LOG_ASSERT_ERROR(recv_insn != NULL, "Expected a RecvInstruction, but did not get one.");
      m_cpiRecv += insn_cost;
      incrementIdleElapsedTime(insn_cost);
   }
   else
   {
      LOG_PRINT_ERROR("Unexpectedly received something other than a Sync or Recv Instruction");
   }
}

void PerformanceModel::iterate()
{
   // Because we will sometimes not have info available (we will throw
   // a DynamicInstructionInfoNotAvailable), we need to be able to
   // continue from the middle of a basic block. m_current_ins_index
   // tracks which instruction we are currently on within the basic
   // block.

   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
   while (m_basic_block_queue.size() > 0)
   #else
   while (m_basic_block_queue.size() > 1)
   #endif
   {
      // While the functional thread is waiting because of clock skew minimization, wait here as well
      #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      while(m_hold)
         sched_yield();
      #endif

      BasicBlock *current_bb = m_basic_block_queue.front();

      for( ; m_current_ins_index < current_bb->size(); m_current_ins_index++)
      {
         Instruction *ins = current_bb->at(m_current_ins_index);
         LOG_ASSERT_ERROR(!ins->isIdle(), "Idle instructions should not make it here!");

         bool res = handleInstruction(ins);
         if (!res)
            // DynamicInstructionInfo not available
            return;
      }

      if (current_bb->isDynamic())
         delete current_bb;

      m_basic_block_queue.pop();
      m_current_ins_index = 0; // move to beginning of next bb
   }
}

void PerformanceModel::pushDynamicInstructionInfo(DynamicInstructionInfo &i)
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.push_wait(i);
   #else
      m_dynamic_info_queue.push(i);
   #endif
}

void PerformanceModel::popDynamicInstructionInfo()
{
   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.pop_wait();
   #else
      m_dynamic_info_queue.pop();
   #endif
}

DynamicInstructionInfo* PerformanceModel::getDynamicInstructionInfo()
{
   // Information is needed to model the instruction, but isn't
   // available. This is handled in iterate() by returning early and
   // continuing from that instruction later.

   #ifdef ENABLE_PERF_MODEL_OWN_THREAD
      m_dynamic_info_queue.empty_wait();
   #else
      if (m_dynamic_info_queue.empty())
         return NULL;
   #endif

   return &m_dynamic_info_queue.front();
}

DynamicInstructionInfo* PerformanceModel::getDynamicInstructionInfo(const Instruction &instruction, bool exec_loads)
{
   DynamicInstructionInfo* info = getDynamicInstructionInfo();

   if (!info)
      return NULL;

   LOG_ASSERT_ERROR(info->eip == instruction.getAddress(), "Expected dynamic info for eip %lx \"%s\", got info for eip %lx", instruction.getAddress(), instruction.getDisassembly().c_str(), info->eip);

   if ((info->type == DynamicInstructionInfo::MEMORY_READ || info->type == DynamicInstructionInfo::MEMORY_WRITE)
      && info->memory_info.hit_where == HitWhere::UNKNOWN)
   {
      if (info->memory_info.executed)
      {
         if (exec_loads)
         {
            MemoryResult res = m_core->accessMemory(
               /*instruction.isAtomic()
                  ? (info->type == DynamicInstructionInfo::MEMORY_READ ? Core::LOCK : Core::UNLOCK)
                  :*/ Core::NONE, // Just as in pin/lite/memory_modeling.cc, make the second part of an atomic update implicit
               info->type == DynamicInstructionInfo::MEMORY_READ ? (instruction.isAtomic() ? Core::READ_EX : Core::READ) : Core::WRITE,
               info->memory_info.addr,
               NULL,
               info->memory_info.size,
               Core::MEM_MODELED_RETURN,
               instruction.getAddress()
            );
            info->memory_info.latency = res.latency;
            info->memory_info.hit_where = res.hit_where;
         }
         else
         {
            info->memory_info.latency = SubsecondTime::Zero();
            info->memory_info.hit_where = HitWhere::UNKNOWN;
         }
      }
      else
      {
         info->memory_info.latency = 1 * m_core->getDvfsDomain()->getPeriod(); // 1 cycle latency
         info->memory_info.hit_where = HitWhere::PREDICATE_FALSE;
      }
   }

   return info;
}

void PerformanceModel::incrementIdleElapsedTime(SubsecondTime time)
{
   // Advance the idle time
   m_idle_elapsed_time.addLatency(time);
   // Advance the total (non-idle + idle) time
   incrementElapsedTime(time);
   // Let the performance model know time has jumped
   notifyElapsedTimeUpdate();
   if (m_fastforward)
      m_fastforward_model->notifyElapsedTimeUpdate();
}

// Only called at the start of the simulation (SPAWN_INST)
void PerformanceModel::setElapsedTime(SubsecondTime time)
{
   // TODO: what happens when a core is reused? (See streamcluster, Redmine #37)
   // Is the initial time for the second thread set with another SPAWN_INST? Or maybe a RECV_INST?
   // When using the scheduler and moving an existing thread to this core, SPAWN_INST is now used.
   //LOG_ASSERT_ERROR(getElapsedTime() == SubsecondTime::Zero(), "setElapsedTime() can only be called when the current time is 0 (via SPAWN_INSN).");
   LOG_ASSERT_ERROR(time >= getElapsedTime(), "setElapsedTime() cannot go backwards in time");

   m_cpiStartTime += time - getElapsedTime();
   // All time up to now was idle
   m_idle_elapsed_time.setElapsedTime(time);
   // Set the elapsed time
   m_elapsed_time.setElapsedTime(time);
   // Let the performance model know time has jumped
   notifyElapsedTimeUpdate();
   if (m_fastforward)
      m_fastforward_model->notifyElapsedTimeUpdate();
}
<|endoftext|>


<commit_before>/*******************************************************************/
/*                               XDMF                              */
/*                   eXtensible Data Model and Format              */
/*                                                                 */
/*  Id : Id  */
/*  Date : $Date$ */
/*  Version : $Revision$ */
/*                                                                 */
/*  Author:                                                        */
/*     Jerry A. Clarke                                             */
/*     clarke@arl.army.mil                                         */
/*     US Army Research Laboratory                                 */
/*     Aberdeen Proving Ground, MD                                 */
/*                                                                 */
/*     Copyright @ 2002 US Army Research Laboratory                */
/*     All Rights Reserved                                         */
/*     See Copyright.txt or http://www.arl.hpc.mil/ice 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 <vtkXdmfDataArray.h>

#include <vtkObjectFactory.h>
#include <vtkCommand.h>

#include <vtkUnsignedCharArray.h>
#include <vtkCharArray.h>
#include <vtkIntArray.h>
#include <vtkLongArray.h>
#include <vtkFloatArray.h>
#include <vtkDoubleArray.h>
#include <vtkUnsignedIntArray.h>
#include "vtkShortArray.h"
#include "vtkUnsignedShortArray.h"

#include <XdmfArray.h>

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkXdmfDataArray);

//----------------------------------------------------------------------------
vtkXdmfDataArray::vtkXdmfDataArray()
{
  this->Array = NULL;
  this->vtkArray = NULL;
}

//----------------------------------------------------------------------------
vtkDataArray *vtkXdmfDataArray::FromXdmfArray( char *ArrayName, int CopyShape,
  int rank, int Components, int MakeCopy ){
  XdmfArray *array = this->Array;
    XdmfInt64 components = 1;
    XdmfInt64 tuples = 0;
  if ( ArrayName != NULL ) {
    array = TagNameToArray( ArrayName );
  }
  if( array == NULL ){
    XdmfErrorMessage("Array is NULL");
    return(NULL);
  }
  if ( this->vtkArray )
    {
    this->vtkArray->Delete();
    this->vtkArray = 0;
    }
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkCharArray::New();
    }
    break;
  case XDMF_UINT8_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedCharArray::New();
    }
    break;
  case XDMF_INT16_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkShortArray::New();
    }
    break;
  case XDMF_UINT16_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedShortArray::New();
    }
    break;
  case XDMF_UINT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedIntArray::New();
    }
    break;
  case XDMF_INT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkIntArray::New();
    }
    break;
  case XDMF_INT64_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkLongArray::New();
    }
    break;
  case XDMF_FLOAT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkFloatArray::New();
    }
    break;
  case XDMF_FLOAT64_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkDoubleArray::New();
    }
    break;
  default:
    vtkErrorMacro("Cannot create VTK data array: " << array->GetNumberType());
    return 0;
  }
  if ( CopyShape )
    {
    if  ( array->GetRank() > rank + 1 )
      {
      this->vtkArray->Delete();
      this->vtkArray = 0;
      vtkErrorMacro("Rank of Xdmf array is more than 1 + rank of dataset");
      return 0;
      }
    if ( array->GetRank() > rank )
      {
      components = array->GetDimension( rank );
      }
    tuples = array->GetNumberOfElements() / components;
    /// this breaks
    components = Components;
    tuples = array->GetNumberOfElements() / components;
    // cout << "Tuples: " << tuples << " components: " << components << endl;
    // cout << "Rank: " << rank << endl;
    this->vtkArray->SetNumberOfComponents( components );
    if(MakeCopy) this->vtkArray->SetNumberOfTuples( tuples );
    }
  else
    {
    this->vtkArray->SetNumberOfComponents( 1 );
    if(MakeCopy) this->vtkArray->SetNumberOfTuples( array->GetNumberOfElements() );
    }
  //cout << "Number type: " << array->GetNumberType() << endl;
  if(MakeCopy){
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    array->GetValues( 0,
      ( XDMF_8_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT8_TYPE :
    array->GetValues( 0,
      ( XDMF_8_U_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT16_TYPE :
    array->GetValues( 0,
      ( XDMF_16_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT16_TYPE :
    array->GetValues( 0,
      ( XDMF_16_U_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT32_TYPE :
    array->GetValues( 0,
      (XDMF_32_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT32_TYPE :
    array->GetValues( 0,
      (XDMF_32_U_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT64_TYPE :
    array->GetValues( 0,
      (XDMF_64_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT32_TYPE :
    array->GetValues( 0,
      ( float *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT64_TYPE :
    array->GetValues( 0,
      ( double *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  default :
    if ( array->GetNumberOfElements() > 0 )
      {
      //cout << "Manual idx" << endl;
      //cout << "Tuples: " << vtkArray->GetNumberOfTuples() << endl;
      //cout << "Components: " << vtkArray->GetNumberOfComponents() << endl;
      //cout << "Elements: " << array->GetNumberOfElements() << endl;
      vtkIdType jj, kk;
      vtkIdType idx = 0;
      for ( jj = 0; jj < vtkArray->GetNumberOfTuples(); jj ++ )
        {
        for ( kk = 0; kk < vtkArray->GetNumberOfComponents(); kk ++ )
          {
          double val = array->GetValueAsFloat64(idx);
          //cout << "Value: " << val << endl;
          vtkArray->SetComponent(jj, kk, val);
          idx ++;
          }
        }
      }
    break;
  }
  }else{
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    vtkCharArray *chara = vtkCharArray::SafeDownCast(this->vtkArray);
    if(!chara){
        XdmfErrorMessage("Cannot downcast data array");
        return(0);
    }
    chara->SetArray((char *)array->GetDataPointer(), components * tuples, 1);
    break;
  case XDMF_UINT8_TYPE :
    vtkUnsignedCharArray *uchara = vtkUnsignedCharArray::SafeDownCast(this->vtkArray);
    if(!uchara){
        XdmfErrorMessage("Cannot downcast ucharata array");
        return(0);
    }
    uchara->SetArray((unsigned char *)array->GetDataPointer(), components * tuples, 1);
    break;
  case XDMF_INT16_TYPE :
    vtkShortArray *shorta = vtkShortArray::SafeDownCast(this->vtkArray);
    if(!shorta){
        XdmfErrorMessage("Cannot downcast data array");
        return(0);
    }
    shorta->SetArray((short *)array->GetDataPointer(), tuples, 1);
    break;
  case XDMF_UINT16_TYPE :
    vtkUnsignedShortArray *ushorta = vtkUnsignedShortArray::SafeDownCast(this->vtkArray);
    if(!ushorta){
        XdmfErrorMessage("Cannot downcast ushortata array");
        return(0);
    }
    ushorta->SetArray((unsigned short *)array->GetDataPointer(), components * tuples, 1);
    break;
  case XDMF_INT32_TYPE :
    vtkIntArray *inta = vtkIntArray::SafeDownCast(this->vtkArray);
    if(!inta){
        XdmfErrorMessage("Cannot downcast intata array");
        return(0);
    }
    inta->SetArray((int *)array->GetDataPointer(), components * tuples, 1);
    break;
  case XDMF_UINT32_TYPE :
    vtkUnsignedIntArray *uinta = vtkUnsignedIntArray::SafeDownCast(this->vtkArray);
    if(!uinta){
        XdmfErrorMessage("Cannot downcast uintata array");
        return(0);
    }
    uinta->SetArray((unsigned int *)array->GetDataPointer(), components * tuples, 1);
    break;
  case XDMF_FLOAT32_TYPE :
    vtkFloatArray *floata = vtkFloatArray::SafeDownCast(this->vtkArray);
    if(!floata){
        XdmfErrorMessage("Cannot downcast floatata array");
        return(0);
    }
    floata->SetArray((float *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_FLOAT64_TYPE :
    vtkDoubleArray *doublea = vtkDoubleArray::SafeDownCast(this->vtkArray);
    if(!doublea){
        XdmfErrorMessage("Cannot downcast doubleata array");
        return(0);
    }
    doublea->SetArray((double *)array->GetDataPointer(), components * tuples, 0);
    break;
  default :
    XdmfErrorMessage("Can't handle number type");
    return(0);
    break;
  }
  array->Reset();
  }
  return( this->vtkArray );
}

//----------------------------------------------------------------------------
char *vtkXdmfDataArray::ToXdmfArray( vtkDataArray *DataArray, int CopyShape ){
  XdmfArray *array;
  if ( DataArray  == NULL )  {
    DataArray = this->vtkArray;
  }
  if ( DataArray  == NULL )  {
    vtkDebugMacro(<< "Array is NULL");
    return(NULL);
  }
  if ( this->Array == NULL ){
    this->Array = new XdmfArray();
    switch( DataArray->GetDataType() ){
    case VTK_CHAR :
    case VTK_UNSIGNED_CHAR :
      this->Array->SetNumberType( XDMF_INT8_TYPE );
      break;
    case VTK_SHORT :
    case VTK_UNSIGNED_SHORT :
    case VTK_INT :
    case VTK_UNSIGNED_INT :
    case VTK_LONG :
    case VTK_UNSIGNED_LONG :
      this->Array->SetNumberType( XDMF_INT32_TYPE );
      break;
    case VTK_FLOAT :
      this->Array->SetNumberType( XDMF_FLOAT32_TYPE );
      break;
    case VTK_DOUBLE :
      this->Array->SetNumberType( XDMF_FLOAT64_TYPE );
      break;
    default :
      XdmfErrorMessage("Can't handle Data Type");
      return( NULL );
    }
  }
  array = this->Array;
  if( CopyShape ) {
    XdmfInt64 Shape[3];

    Shape[0] = DataArray->GetNumberOfTuples();
    Shape[1] = DataArray->GetNumberOfComponents();
    if( Shape[1] == 1 ) {
      array->SetShape( 1, Shape );
    } else {
      array->SetShape( 2, Shape );
    }

  }
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    array->SetValues( 0,
      ( unsigned char  *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT32_TYPE :
  case XDMF_INT64_TYPE :
    array->SetValues( 0,
      ( int *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT32_TYPE :
    array->SetValues( 0,
      ( float *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  default :
    array->SetValues( 0,
      ( double *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  }
  return( array->GetTagName() );
}
<commit_msg>Don't Save Arrays<commit_after>/*******************************************************************/
/*                               XDMF                              */
/*                   eXtensible Data Model and Format              */
/*                                                                 */
/*  Id : Id  */
/*  Date : $Date$ */
/*  Version : $Revision$ */
/*                                                                 */
/*  Author:                                                        */
/*     Jerry A. Clarke                                             */
/*     clarke@arl.army.mil                                         */
/*     US Army Research Laboratory                                 */
/*     Aberdeen Proving Ground, MD                                 */
/*                                                                 */
/*     Copyright @ 2002 US Army Research Laboratory                */
/*     All Rights Reserved                                         */
/*     See Copyright.txt or http://www.arl.hpc.mil/ice 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 <vtkXdmfDataArray.h>

#include <vtkObjectFactory.h>
#include <vtkCommand.h>

#include <vtkUnsignedCharArray.h>
#include <vtkCharArray.h>
#include <vtkIntArray.h>
#include <vtkLongArray.h>
#include <vtkFloatArray.h>
#include <vtkDoubleArray.h>
#include <vtkUnsignedIntArray.h>
#include "vtkShortArray.h"
#include "vtkUnsignedShortArray.h"

#include <XdmfArray.h>

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkXdmfDataArray);

//----------------------------------------------------------------------------
vtkXdmfDataArray::vtkXdmfDataArray()
{
  this->Array = NULL;
  this->vtkArray = NULL;
}

//----------------------------------------------------------------------------
vtkDataArray *vtkXdmfDataArray::FromXdmfArray( char *ArrayName, int CopyShape,
  int rank, int Components, int MakeCopy ){
  XdmfArray *array = this->Array;
    XdmfInt64 components = 1;
    XdmfInt64 tuples = 0;
  if ( ArrayName != NULL ) {
    array = TagNameToArray( ArrayName );
  }
  if( array == NULL ){
    XdmfErrorMessage("Array is NULL");
    return(NULL);
  }
  if ( this->vtkArray )
    {
    this->vtkArray->Delete();
    this->vtkArray = 0;
    }
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkCharArray::New();
    }
    break;
  case XDMF_UINT8_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedCharArray::New();
    }
    break;
  case XDMF_INT16_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkShortArray::New();
    }
    break;
  case XDMF_UINT16_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedShortArray::New();
    }
    break;
  case XDMF_UINT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkUnsignedIntArray::New();
    }
    break;
  case XDMF_INT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkIntArray::New();
    }
    break;
  case XDMF_INT64_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkLongArray::New();
    }
    break;
  case XDMF_FLOAT32_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkFloatArray::New();
    }
    break;
  case XDMF_FLOAT64_TYPE :
    if( this->vtkArray == NULL ) {
      this->vtkArray = vtkDoubleArray::New();
    }
    break;
  default:
    vtkErrorMacro("Cannot create VTK data array: " << array->GetNumberType());
    return 0;
  }
  if ( CopyShape )
    {
    if  ( array->GetRank() > rank + 1 )
      {
      this->vtkArray->Delete();
      this->vtkArray = 0;
      vtkErrorMacro("Rank of Xdmf array is more than 1 + rank of dataset");
      return 0;
      }
    if ( array->GetRank() > rank )
      {
      components = array->GetDimension( rank );
      }
    tuples = array->GetNumberOfElements() / components;
    /// this breaks
    components = Components;
    tuples = array->GetNumberOfElements() / components;
    // cout << "Tuples: " << tuples << " components: " << components << endl;
    // cout << "Rank: " << rank << endl;
    this->vtkArray->SetNumberOfComponents( components );
    if(MakeCopy) this->vtkArray->SetNumberOfTuples( tuples );
    }
  else
    {
    this->vtkArray->SetNumberOfComponents( 1 );
    if(MakeCopy) this->vtkArray->SetNumberOfTuples( array->GetNumberOfElements() );
    }
  //cout << "Number type: " << array->GetNumberType() << endl;
  if(MakeCopy){
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    array->GetValues( 0,
      ( XDMF_8_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT8_TYPE :
    array->GetValues( 0,
      ( XDMF_8_U_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT16_TYPE :
    array->GetValues( 0,
      ( XDMF_16_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT16_TYPE :
    array->GetValues( 0,
      ( XDMF_16_U_INT*)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT32_TYPE :
    array->GetValues( 0,
      (XDMF_32_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_UINT32_TYPE :
    array->GetValues( 0,
      (XDMF_32_U_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT64_TYPE :
    array->GetValues( 0,
      (XDMF_64_INT *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT32_TYPE :
    array->GetValues( 0,
      ( float *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT64_TYPE :
    array->GetValues( 0,
      ( double *)this->vtkArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  default :
    if ( array->GetNumberOfElements() > 0 )
      {
      //cout << "Manual idx" << endl;
      //cout << "Tuples: " << vtkArray->GetNumberOfTuples() << endl;
      //cout << "Components: " << vtkArray->GetNumberOfComponents() << endl;
      //cout << "Elements: " << array->GetNumberOfElements() << endl;
      vtkIdType jj, kk;
      vtkIdType idx = 0;
      for ( jj = 0; jj < vtkArray->GetNumberOfTuples(); jj ++ )
        {
        for ( kk = 0; kk < vtkArray->GetNumberOfComponents(); kk ++ )
          {
          double val = array->GetValueAsFloat64(idx);
          //cout << "Value: " << val << endl;
          vtkArray->SetComponent(jj, kk, val);
          idx ++;
          }
        }
      }
    break;
  }
  }else{
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    vtkCharArray *chara = vtkCharArray::SafeDownCast(this->vtkArray);
    if(!chara){
        XdmfErrorMessage("Cannot downcast data array");
        return(0);
    }
    chara->SetArray((char *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_UINT8_TYPE :
    vtkUnsignedCharArray *uchara = vtkUnsignedCharArray::SafeDownCast(this->vtkArray);
    if(!uchara){
        XdmfErrorMessage("Cannot downcast ucharata array");
        return(0);
    }
    uchara->SetArray((unsigned char *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_INT16_TYPE :
    vtkShortArray *shorta = vtkShortArray::SafeDownCast(this->vtkArray);
    if(!shorta){
        XdmfErrorMessage("Cannot downcast data array");
        return(0);
    }
    shorta->SetArray((short *)array->GetDataPointer(), tuples, 0);
    break;
  case XDMF_UINT16_TYPE :
    vtkUnsignedShortArray *ushorta = vtkUnsignedShortArray::SafeDownCast(this->vtkArray);
    if(!ushorta){
        XdmfErrorMessage("Cannot downcast ushortata array");
        return(0);
    }
    ushorta->SetArray((unsigned short *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_INT32_TYPE :
    vtkIntArray *inta = vtkIntArray::SafeDownCast(this->vtkArray);
    if(!inta){
        XdmfErrorMessage("Cannot downcast intata array");
        return(0);
    }
    inta->SetArray((int *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_UINT32_TYPE :
    vtkUnsignedIntArray *uinta = vtkUnsignedIntArray::SafeDownCast(this->vtkArray);
    if(!uinta){
        XdmfErrorMessage("Cannot downcast uintata array");
        return(0);
    }
    uinta->SetArray((unsigned int *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_FLOAT32_TYPE :
    vtkFloatArray *floata = vtkFloatArray::SafeDownCast(this->vtkArray);
    if(!floata){
        XdmfErrorMessage("Cannot downcast floatata array");
        return(0);
    }
    floata->SetArray((float *)array->GetDataPointer(), components * tuples, 0);
    break;
  case XDMF_FLOAT64_TYPE :
    vtkDoubleArray *doublea = vtkDoubleArray::SafeDownCast(this->vtkArray);
    if(!doublea){
        XdmfErrorMessage("Cannot downcast doubleata array");
        return(0);
    }
    doublea->SetArray((double *)array->GetDataPointer(), components * tuples, 0);
    break;
  default :
    XdmfErrorMessage("Can't handle number type");
    return(0);
    break;
  }
  array->Reset();
  }
  return( this->vtkArray );
}

//----------------------------------------------------------------------------
char *vtkXdmfDataArray::ToXdmfArray( vtkDataArray *DataArray, int CopyShape ){
  XdmfArray *array;
  if ( DataArray  == NULL )  {
    DataArray = this->vtkArray;
  }
  if ( DataArray  == NULL )  {
    vtkDebugMacro(<< "Array is NULL");
    return(NULL);
  }
  if ( this->Array == NULL ){
    this->Array = new XdmfArray();
    switch( DataArray->GetDataType() ){
    case VTK_CHAR :
    case VTK_UNSIGNED_CHAR :
      this->Array->SetNumberType( XDMF_INT8_TYPE );
      break;
    case VTK_SHORT :
    case VTK_UNSIGNED_SHORT :
    case VTK_INT :
    case VTK_UNSIGNED_INT :
    case VTK_LONG :
    case VTK_UNSIGNED_LONG :
      this->Array->SetNumberType( XDMF_INT32_TYPE );
      break;
    case VTK_FLOAT :
      this->Array->SetNumberType( XDMF_FLOAT32_TYPE );
      break;
    case VTK_DOUBLE :
      this->Array->SetNumberType( XDMF_FLOAT64_TYPE );
      break;
    default :
      XdmfErrorMessage("Can't handle Data Type");
      return( NULL );
    }
  }
  array = this->Array;
  if( CopyShape ) {
    XdmfInt64 Shape[3];

    Shape[0] = DataArray->GetNumberOfTuples();
    Shape[1] = DataArray->GetNumberOfComponents();
    if( Shape[1] == 1 ) {
      array->SetShape( 1, Shape );
    } else {
      array->SetShape( 2, Shape );
    }

  }
  switch( array->GetNumberType() ){
  case XDMF_INT8_TYPE :
    array->SetValues( 0,
      ( unsigned char  *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_INT32_TYPE :
  case XDMF_INT64_TYPE :
    array->SetValues( 0,
      ( int *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  case XDMF_FLOAT32_TYPE :
    array->SetValues( 0,
      ( float *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  default :
    array->SetValues( 0,
      ( double *)DataArray->GetVoidPointer( 0 ),
      array->GetNumberOfElements() );
    break;
  }
  return( array->GetTagName() );
}
<|endoftext|>