<commit_before>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>

using namespace boost;
using namespace std;

class rshell{
    protected:
	//Variables
        string commands;
	string nextConnector;
        vector<string> commandlist;
	bool prevCommandPass;
	bool forceExit;
    public:
	//Constructor
        rshell(){
	    commands = "";
	    nextConnector = ";";
	    prevCommandPass = true;
	    forceExit = false;
        }
	//Separates string into tokens and puts them into commandlist, if the token ends with a ;, it stays with the string
	void parseAllCommands(){
            char_separator<char> delims(" ");
	    tokenizer<char_separator<char> > tokenlist(commands, delims);
            for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
	        string com(*i);
		commandlist.push_back(com);
            }
        }
	//Executes one command and sets prevCommandPass to true or false.
	void executeCommand(vector<string> com){
	    char* argv[1024];
	    int pid_child;
	    int status_child;

            for(unsigned int i = 0; i < com.size(); i++){
	        argv[i] = (char*)com.at(i).c_str();
            }
	    argv[com.size()] = NULL;
	    pid_child = fork();
	    if (pid_child == 0){
	        if(execvp(argv[0], argv) == -1){
		    perror("execvp failed: ");
		    prevCommandPass = false;
		    return;
		}
	    }
            else{
	        if (waitpid(pid_child, &status_child, 0) == -1){
		    perror("pid incorrect: ");
		}
	    }
	    prevCommandPass = true;
	}
	//Splits commandlist into commands with their arguments then calls executeCommand to run them.
	void executeAllCommands(){
            vector<string> commandsublist;
	    unsigned int i = 0;
	    unsigned int j = 0;
	    while (i < commandlist.size()){
		j = 0;
		if (checkCommandRun()){
	            while (!checkBreaker(commandlist.at(i))){
			//Exit check
	       	        if (commandlist.at(i) == "exit"){
	                    forceExit = true;
		            return;
		        }
			//Comment check
	                if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
		            executeCommand(commandsublist);
		            return;
		        }
			//Adds command to the list
	                commandsublist.push_back(commandlist.at(i));
			if (commandsublist.at(j).at(commandsublist.at(j).length() - 1) == ';'){
			    commandsublist.at(j).erase(commandsublist.at(j).length() - 1);
			    nextConnector = ';';
			    break;
			}
		        i++;
			j++;
			if (i == commandlist.size()){
			    executeCommand(commandsublist);
			    return;
			}
                    }
                    if (checkBreaker(commandlist.at(i))){
    		        nextConnector = commandlist.at(i);
		    }
		    i++;
		}
		executeCommand(commandsublist);
		commandsublist.clear();
	    }
	}
	//Checks if there is a comment sign in the first letter returns true
	bool checkComment(string str){
	    if (str.at(0) == '#'){
		return true;
	    }
	    return false;
	}
	//Checks if the string is a breaker
	bool checkBreaker(string str){
	    if (str == "||" || str == "&&" || str == ";"){
	        return true;
            }
	    return false;
	}
	//Checks if the next command should be ran.
	bool checkCommandRun(){
	    if (nextConnector == "||"){
		if(prevCommandPass){
	            return false;
		}
		return true;
	    }
	    if (nextConnector == "&&"){
		if(prevCommandPass){
		    return true;
		}
		return false;
	    }
	    if (nextConnector == ";"){
		return true;
	    }
	    return true;
	}
	//Starts the program.
	void run(){
	    while (!forceExit){
		cout << "$";
	        getline(cin, commands);
		if (commands != "" && commands != "exit"){
		    parseAllCommands();
                    executeAllCommands();
		}
		if (commands == "exit"){
		    cout << "Forced Exit." << endl;
		    forceExit = true;
		    return;
		}
		commandlist.clear();
	    }
	}
};
<commit_msg>improved readability<commit_after>#include <string>
#include <vector>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <stdlib.h>
#include <cstdio>
#include <sys/wait.h>

using namespace boost;
using namespace std;

class rshell{
    protected:
		//Data Members
        string commands;
		string nextConnector;
        vector<string> commandlist;
		bool prevCommandPass;
		bool forceExit;

    public:
		//Constructor
        rshell(){
	    	commands = "";
	    	nextConnector = ";";
	    	prevCommandPass = true;
	    	forceExit = false;
		}

		// Parses the string (strings ending in ';' will keep the ';')
		void parseAllCommands(){
			char_separator<char> delims(" ");
	    	tokenizer<char_separator<char> > tokenlist(commands, delims);
        	for (tokenizer<char_separator<char> >::iterator i = tokenlist.begin(); i != tokenlist.end(); i++){
	    		string com(*i);
				commandlist.push_back(com);
        	}
    	}

		// Executes one command and sets prevCommandPass to true or false.
		void executeCommand(vector<string> com){
	    	char* argv[1024];
	    	int pid_child;
	    	int status_child;

        	for(unsigned int i = 0; i < com.size(); i++){
	        	argv[i] = (char*)com.at(i).c_str();
        	}
	    	argv[com.size()] = NULL;
	    	pid_child = fork();
	    	if (pid_child == 0){
	        	if(execvp(argv[0], argv) == -1){
		    		perror("execvp failed: ");
		    		prevCommandPass = false;
		    		return;
				}
	    	}
        	else{
	       		if (waitpid(pid_child, &status_child, 0) == -1){
		    		perror("pid incorrect: ");
				}
	    	}
	    	prevCommandPass = true;
		}

		//Splits commandlist into commands with their arguments then calls executeCommand to run them.
		void executeAllCommands(){
        	vector<string> commandsublist;
	    	unsigned int i = 0;
	    	unsigned int j = 0;
	    	while (i < commandlist.size()){
				j = 0;
				if (checkCommandRun()){
	        		while (!checkBreaker(commandlist.at(i))){
						//Exit check
	       	        	if (commandlist.at(i) == "exit"){
	                    	forceExit = true;
		            	return;
		        		}
						// Comment check
	            		if (commandlist.at(i) == "#" || checkComment(commandlist.at(i))){
		            		executeCommand(commandsublist);
		            		return;
		        		}
						//Adds command to the list
	            		commandsublist.push_back(commandlist.at(i));
						if (commandsublist.at(j).at(commandsublist.at(j).length() - 1) == ';'){
				    		commandsublist.at(j).erase(commandsublist.at(j).length() - 1);
							nextConnector = ';';
			    			break;
						}
		        		i++;
						j++;
						if (i == commandlist.size()){
			    			executeCommand(commandsublist);
			    			return;
						}
                	}
	                if (checkBreaker(commandlist.at(i))){
   		 		    	nextConnector = commandlist.at(i);
			    	}
					i++;
				}
			executeCommand(commandsublist);
			commandsublist.clear();
			}
		}

		//	Checks if there is a '#' at the front of the string
		bool checkComment(string str){
		    if (str.at(0) == '#'){
				return true;
		    }
		    return false;
		}

		//	Checks if the string is a breaker
		bool checkBreaker(string str){
		    if (str == "||" || str == "&&" || str == ";"){
		        return true;
			}
			return false;
		}

		// Checks if the next command should be run
		bool checkCommandRun(){
		    if (nextConnector == "||"){
				if(prevCommandPass){
		            return false;
				}
				return true;
		    }
		    if (nextConnector == "&&"){
				if(prevCommandPass){
			    	return true;
				}
				return false;
		    }
		    if (nextConnector == ";"){
				return true;
		    }
		    return true;
		}

		//Starts the program.
		void run(){
		    while (!forceExit){
				cout << "$";
		    	getline(cin, commands);
		    	parseAllCommands();
  	 	     	executeAllCommands();

				if (commands == "exit"){
			    	cout << "Forced Exit." << endl;
			    	forceExit = true;
			    return;
			}
			commandlist.clear();
		    }
		}
};
<|endoftext|>


<commit_before>#include "WebSystemController.h"
#include "Overlay.h"
#include "Crawl.h"

#pragma mark – Life Cycle

void WebSystemController::init() {
    // Connect the websystem
    connection.setHost("projectvictory.hostfile", 80);
    // Set up listeners
    connection.addHashTagCountListener(this, &WebSystemController::onHashTagCount);
    connection.addShoutoutListener(this, &WebSystemController::onShoutout);
    connection.addCommandListener(this, &WebSystemController::onCommand);

    // Set up the voting GUI
    initVotingGUI();
    initWebSystemGUI();
}

void WebSystemController::update() {
    float currentTime = ofGetElapsedTimef();
    static float lastHashTagUpdate = 0.f;
    if ( lastHashTagUpdate + (float(UPDATE_VOTES_EVERY_MS) / 1000) < currentTime && overlay && webSystemIsEnabled ) {
        connection.requestHashTagCount( overlay->voteDisplay.topic1 );
        connection.requestHashTagCount( overlay->voteDisplay.topic2 );
        lastHashTagUpdate = currentTime;
    }

    // only decay effects 10/sec
    static float lastEffectsDecaySecs = 0.0f;
    if ( shouldDecaysEffects && currentTime - lastEffectsDecaySecs > DECAY_EFFECT_EVERY_SEC) {
        decayVideoFXToDefault();
        lastEffectsDecaySecs = currentTime;
    }
}

#pragma mark - VoteSystem

void WebSystemController::initWebSystemGUI() {
    websystemGUI = new ofxUISuperCanvas( "WEB SYSTEM", 20, 20, 200, 200 );
    websystemGUI->setColorBack( ofColor(ofColor::green, 125) );
    websystemGUI->addLabelToggle( "ENABLED", &webSystemIsEnabled );
    websystemGUI->addLabelToggle( "SHOUTOUTS", &shoutoutsAreEnabled );
    websystemGUI->addLabelToggle( "COMMANDS", &commandsAreEnabled );
    websystemGUI->addLabelToggle( "DECAYS", &shouldDecaysEffects );
    websystemGUI->autoSizeToFitWidgets();
}

#pragma mark – Web System Connection

void WebSystemController::onHashTagCount(Json::Value body) {

    if (!webSystemIsEnabled) { return; }

    // Do something with the incoming count
    string hashTag = body["tag"].asString();
    // This will return the straight out number.
    // You can dig into  "result" to get an array with number of votes cast per minute for 120 minutes
    float numberOfShoutouts = WebSystem::Utils::countHashTagsInResult( body["result"] );

    overlay->voteDisplay.setVote(hashTag, numberOfShoutouts);

}

void WebSystemController::onShoutout(Json::Value body) {

    // Get the info on the shoutout (you might want to store these in a vector if they are used later)
    string screenname = body["tweet"]["userScreenName"].asString();
    string tweetText = body["tweet"]["text"].asString();

    if (!webSystemIsEnabled || !shoutoutsAreEnabled) { return; }

    cout << "@" << screenname << ": " << tweetText << endl;

    overlay->crawl.addCrawlItem( screenname, tweetText );

}

void WebSystemController::onCommand(Json::Value body) {

    if (!webSystemIsEnabled || !commandsAreEnabled) { return; }

    // p.s. if you want to know what is the body, you can send it to cout:
    // cout << body;

    // Get the screen name of the user who tweeted
    string screenname = body["tweet"]["userScreenName"].asString();

    // DO NOT USE THE TWEET TEXT. It is unmoderated!
    string doNotUse = body["tweet"]["text"].asString();

    // Get the text command which trigger the action
    string command = body["payload"]["command"].asString();

    cout << "@" << screenname << " triggered " << command << endl;

    // Store a trigger to save the image

    // This is dirty. Want tweet id as string.
    stringstream s;
    s << body["tweet"]["id"];
    string tweetid = s.str();
    tweetid.erase(tweetid.size() - 1);
    screenShotTriggers[ ofGetElapsedTimef() ] = tweetid;

    // Apply the payload to the videofx. They need to be a decayer somewhere, so this may not be how it works.
    if (videoFX) {
        WebSystem::Utils::applyPayload( videoFX, body["payload"] );
        cout << "should have applied payload" << endl;
    }

}

#pragma mark – Decay

void WebSystemController::decayVideoFXToDefault() {

    // store the last time on first run (this won't work if using multiple effects)
    static float lastUpdate = ofGetElapsedTimef();

    // I think, the 0.3 means that each effect will decay by 30% every second
    WebSystem::Utils::decayEffects( videoFX, lastUpdate, 0.3f );

    lastUpdate = ofGetElapsedTimef();

}

#pragma mark - VoteSystem

void WebSystemController::initVotingGUI() {
    voteGUI = new ofxUISuperCanvas( "VOTEING SYSTEM", 20, 340, 200, 200 );
    voteGUI->setColorBack(ofColor(ofColor::thistle, 125));
    voteGUI->addLabel("TOPIC 1");
    vote1TextInput = voteGUI->addTextInput("TOPIC 1", "");
    voteGUI->addLabel("TOPIC 2");
    vote2TextInput = voteGUI->addTextInput("TOPIC 2", "");
    voteGUI->addButton("UPDATE TOPICS", false);
    voteGUI->autoSizeToFitWidgets();
    ofAddListener( voteGUI->newGUIEvent, this, &WebSystemController::voteingGUIEvent );
    voteGUI->loadSettings("settings.voting.gui.xml");

}

void WebSystemController::voteingGUIEvent(ofxUIEventArgs &e) {

    if ( e.widget->getName() == "UPDATE TOPICS") {
        ofxUIButton *button = (ofxUIButton *)e.widget;
        if (button->getValue()) {
            overlay->voteDisplay.topic1 = vote1TextInput->getTextString();
            overlay->voteDisplay.topic2 = vote2TextInput->getTextString();
            overlay->voteDisplay.resetVotes();
        } else {
            voteGUI->saveSettings("settings.voting.gui.xml");
        }
    }

}

// Image saving
string WebSystemController::getNextScreenShotFilename() {
    float currentTime = ofGetElapsedTimef();
    string filename = "";

    // find the first trigger needing to be saved
    ScreenShotTriggersIt it = screenShotTriggers.begin();

    bool found = false;
    while ( !found && it != screenShotTriggers.end()) {

        if ( it->first < currentTime + 1.0f) {
            found = true;
            filename = it->second;
            screenShotTriggers.erase(it);
        }

    }

    return filename;

}

<commit_msg>GUI Positioning<commit_after>#include "WebSystemController.h"
#include "Overlay.h"
#include "Crawl.h"

#pragma mark – Life Cycle

void WebSystemController::init() {
    // Connect the websystem
    connection.setHost("projectvictory.hostfile", 80);
    // Set up listeners
    connection.addHashTagCountListener(this, &WebSystemController::onHashTagCount);
    connection.addShoutoutListener(this, &WebSystemController::onShoutout);
    connection.addCommandListener(this, &WebSystemController::onCommand);

    // Set up the voting GUI
    initVotingGUI();
    initWebSystemGUI();
}

void WebSystemController::update() {
    float currentTime = ofGetElapsedTimef();
    static float lastHashTagUpdate = 0.f;
    if ( lastHashTagUpdate + (float(UPDATE_VOTES_EVERY_MS) / 1000) < currentTime && overlay && webSystemIsEnabled ) {
        connection.requestHashTagCount( overlay->voteDisplay.topic1 );
        connection.requestHashTagCount( overlay->voteDisplay.topic2 );
        lastHashTagUpdate = currentTime;
    }

    // only decay effects 10/sec
    static float lastEffectsDecaySecs = 0.0f;
    if ( shouldDecaysEffects && currentTime - lastEffectsDecaySecs > DECAY_EFFECT_EVERY_SEC) {
        decayVideoFXToDefault();
        lastEffectsDecaySecs = currentTime;
    }
}

#pragma mark - VoteSystem

void WebSystemController::initWebSystemGUI() {
    websystemGUI = new ofxUISuperCanvas( "WEB SYSTEM", 20, 20, 200, 200 );
    websystemGUI->setColorBack( ofColor(ofColor::green, 125) );
    websystemGUI->addLabelToggle( "ENABLED", &webSystemIsEnabled );
    websystemGUI->addLabelToggle( "SHOUTOUTS", &shoutoutsAreEnabled );
    websystemGUI->addLabelToggle( "COMMANDS", &commandsAreEnabled );
    websystemGUI->addLabelToggle( "DECAYS", &shouldDecaysEffects );
    websystemGUI->autoSizeToFitWidgets();
}

#pragma mark – Web System Connection

void WebSystemController::onHashTagCount(Json::Value body) {

    if (!webSystemIsEnabled) { return; }

    // Do something with the incoming count
    string hashTag = body["tag"].asString();
    // This will return the straight out number.
    // You can dig into  "result" to get an array with number of votes cast per minute for 120 minutes
    float numberOfShoutouts = WebSystem::Utils::countHashTagsInResult( body["result"] );

    overlay->voteDisplay.setVote(hashTag, numberOfShoutouts);

}

void WebSystemController::onShoutout(Json::Value body) {

    // Get the info on the shoutout (you might want to store these in a vector if they are used later)
    string screenname = body["tweet"]["userScreenName"].asString();
    string tweetText = body["tweet"]["text"].asString();

    if (!webSystemIsEnabled || !shoutoutsAreEnabled) { return; }

    cout << "@" << screenname << ": " << tweetText << endl;

    overlay->crawl.addCrawlItem( screenname, tweetText );

}

void WebSystemController::onCommand(Json::Value body) {

    if (!webSystemIsEnabled || !commandsAreEnabled) { return; }

    // p.s. if you want to know what is the body, you can send it to cout:
    // cout << body;

    // Get the screen name of the user who tweeted
    string screenname = body["tweet"]["userScreenName"].asString();

    // DO NOT USE THE TWEET TEXT. It is unmoderated!
    string doNotUse = body["tweet"]["text"].asString();

    // Get the text command which trigger the action
    string command = body["payload"]["command"].asString();

    cout << "@" << screenname << " triggered " << command << endl;

    // Store a trigger to save the image

    // This is dirty. Want tweet id as string.
    stringstream s;
    s << body["tweet"]["id"];
    string tweetid = s.str();
    tweetid.erase(tweetid.size() - 1);
    screenShotTriggers[ ofGetElapsedTimef() ] = tweetid;

    // Apply the payload to the videofx. They need to be a decayer somewhere, so this may not be how it works.
    if (videoFX) {
        WebSystem::Utils::applyPayload( videoFX, body["payload"] );
        cout << "should have applied payload" << endl;
    }

}

#pragma mark – Decay

void WebSystemController::decayVideoFXToDefault() {

    // store the last time on first run (this won't work if using multiple effects)
    static float lastUpdate = ofGetElapsedTimef();

    // I think, the 0.3 means that each effect will decay by 30% every second
    WebSystem::Utils::decayEffects( videoFX, lastUpdate, 0.3f );

    lastUpdate = ofGetElapsedTimef();

}

#pragma mark - VoteSystem

void WebSystemController::initVotingGUI() {
    voteGUI = new ofxUISuperCanvas( "VOTEING SYSTEM", 20, 180, 200, 200 );
    voteGUI->setColorBack(ofColor(ofColor::thistle, 125));
    voteGUI->addLabel("TOPIC 1");
    vote1TextInput = voteGUI->addTextInput("TOPIC 1", "");
    voteGUI->addLabel("TOPIC 2");
    vote2TextInput = voteGUI->addTextInput("TOPIC 2", "");
    voteGUI->addButton("UPDATE TOPICS", false);
    voteGUI->autoSizeToFitWidgets();
    ofAddListener( voteGUI->newGUIEvent, this, &WebSystemController::voteingGUIEvent );
    voteGUI->loadSettings("settings.voting.gui.xml");

}

void WebSystemController::voteingGUIEvent(ofxUIEventArgs &e) {

    if ( e.widget->getName() == "UPDATE TOPICS") {
        ofxUIButton *button = (ofxUIButton *)e.widget;
        if (button->getValue()) {
            overlay->voteDisplay.topic1 = vote1TextInput->getTextString();
            overlay->voteDisplay.topic2 = vote2TextInput->getTextString();
            overlay->voteDisplay.resetVotes();
        } else {
            voteGUI->saveSettings("settings.voting.gui.xml");
        }
    }

}

// Image saving
string WebSystemController::getNextScreenShotFilename() {
    float currentTime = ofGetElapsedTimef();
    string filename = "";

    // find the first trigger needing to be saved
    ScreenShotTriggersIt it = screenShotTriggers.begin();

    bool found = false;
    while ( !found && it != screenShotTriggers.end()) {

        if ( it->first < currentTime + 1.0f) {
            found = true;
            filename = it->second;
            screenShotTriggers.erase(it);
        }

    }

    return filename;

}

<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id: ValuePrinter.cpp 46307 2012-10-04 06:53:23Z axel $
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/ValuePrinter.h"
#include "cling/Utils/AST.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Frontend/CompilerInstance.h"

using namespace cling;
using namespace clang;
using namespace llvm;

StoredValueRef::StoredValue::StoredValue(Interpreter& interp,
                                         QualType clangTy,
                                         const llvm::Type* llvm_Ty)
  : Value(GenericValue(), clangTy, llvm_Ty), m_Interp(interp), m_Mem(0){
  if (clangTy->isIntegralOrEnumerationType() ||
      clangTy->isRealFloatingType() ||
      clangTy->hasPointerRepresentation()) {
    return;
  };
  if (const MemberPointerType* MPT = clangTy->getAs<MemberPointerType>()) {
    if (MPT->isMemberDataPointer()) {
      return;
    }
  }
  m_Mem = m_Buf;
  const uint64_t size = (uint64_t) getAllocSizeInBytes();
  if (size > sizeof(m_Buf)) {
    m_Mem = new char[size];
  }
  setGV(llvm::PTOGV(m_Mem));
}

StoredValueRef::StoredValue::~StoredValue() {
  // Destruct the object, then delete the memory if needed.
  Destruct();
  if (m_Mem != m_Buf)
    delete [] m_Mem;
}

void* StoredValueRef::StoredValue::GetDtorWrapperPtr(CXXRecordDecl* CXXRD) {
   std::string funcname;
  {
    llvm::raw_string_ostream namestr(funcname);
    namestr << "__cling_StoredValue_Destruct_" << CXXRD;
  }
  void* dtorWrapperPtr = m_Interp.getAddressOfGlobal(funcname.c_str());
  if (dtorWrapperPtr)
    return dtorWrapperPtr;

  std::string code("extern \"C\" void ");
  std::string typeName
    = utils::TypeName::GetFullyQualifiedName(getClangType(),
                                             CXXRD->getASTContext());
  code += funcname + "(void* obj){((" + typeName + "*)obj)->~"
    + typeName +"();}";
  m_Interp.declare(code);
  return m_Interp.getAddressOfGlobal(funcname.c_str());
}

void StoredValueRef::StoredValue::Destruct() {
  // If applicable, call addr->~Type() to destruct the object.
  // template <typename T> void destr(T* obj = 0) { (T)obj->~T(); }
  // |-FunctionDecl destr 'void (struct XB *)'
  // |-TemplateArgument type 'struct XB'
  // |-ParmVarDecl obj 'struct XB *'
  // `-CompoundStmt
  //   `-CXXMemberCallExpr 'void'
  //     `-MemberExpr '<bound member function type>' ->~XB
  //       `-ImplicitCastExpr 'struct XB *' <LValueToRValue>
  //         `-DeclRefExpr  'struct XB *' lvalue ParmVar 'obj' 'struct XB *'

  if (getClangType.isConst())
    return;
  const RecordType* RT = dyn_cast<RecordType>(getClangType());
  if (!RT)
    return;
  CXXRecordDecl* CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl());
  if (!CXXRD || CXXRD->hasTrivialDestructor())
    return;

  CXXRD = CXXRD->getCanonicalDecl();
  void* funcPtr = GetDtorWrapperPtr(CXXRD);
  if (!funcPtr)
    return;

  typedef void (*DtorWrapperFunc_t)(void* obj);
  DtorWrapperFunc_t wrapperFuncPtr = (DtorWrapperFunc_t) funcPtr;
  (*wrapperFuncPtr)(getAs<void*>());
}

long long StoredValueRef::StoredValue::getAllocSizeInBytes() const {
  const ASTContext& ctx = m_Interp.getCI()->getASTContext();
  return (long long) ctx.getTypeSizeInChars(getClangType()).getQuantity();
}

void StoredValueRef::dump() const {
  ASTContext& ctx = m_Value->m_Interp.getCI()->getASTContext();
  valuePrinterInternal::StreamStoredValueRef(llvm::errs(), this, ctx);
}

StoredValueRef StoredValueRef::allocate(Interpreter& interp, QualType t,
                                        const llvm::Type* llvmTy) {
  return new StoredValue(interp, t, llvmTy);
}

StoredValueRef StoredValueRef::bitwiseCopy(Interpreter& interp,
                                           const Value& value) {
  StoredValue* SValue
    = new StoredValue(interp, value.getClangType(), value.getLLVMType());
  if (SValue->m_Mem) {
    const char* src = (const char*)value.getGV().PointerVal;
    // It's not a pointer. LLVM stores a char[5] (i.e. 5 x i8) as an i40,
    // so use that instead. We don't keep it as an int; instead, we "allocate"
    // it as a "proper" char[5] in the m_Mem. "Allocate" because it uses the
    // m_Buf, so no actual allocation happens.
    uint64_t IntVal = value.getGV().IntVal.getSExtValue();
    if (!src) src = (const char*)&IntVal;
    memcpy(SValue->m_Mem, src,
           SValue->getAllocSizeInBytes());
  } else {
    SValue->setGV(value.getGV());
  }
  return SValue;
}
<commit_msg>The destructor is called N::A<B>::~A<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id: ValuePrinter.cpp 46307 2012-10-04 06:53:23Z axel $
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/StoredValueRef.h"
#include "cling/Interpreter/Interpreter.h"
#include "cling/Interpreter/ValuePrinter.h"
#include "cling/Utils/AST.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/Frontend/CompilerInstance.h"

using namespace cling;
using namespace clang;
using namespace llvm;

StoredValueRef::StoredValue::StoredValue(Interpreter& interp,
                                         QualType clangTy,
                                         const llvm::Type* llvm_Ty)
  : Value(GenericValue(), clangTy, llvm_Ty), m_Interp(interp), m_Mem(0){
  if (clangTy->isIntegralOrEnumerationType() ||
      clangTy->isRealFloatingType() ||
      clangTy->hasPointerRepresentation()) {
    return;
  };
  if (const MemberPointerType* MPT = clangTy->getAs<MemberPointerType>()) {
    if (MPT->isMemberDataPointer()) {
      return;
    }
  }
  m_Mem = m_Buf;
  const uint64_t size = (uint64_t) getAllocSizeInBytes();
  if (size > sizeof(m_Buf)) {
    m_Mem = new char[size];
  }
  setGV(llvm::PTOGV(m_Mem));
}

StoredValueRef::StoredValue::~StoredValue() {
  // Destruct the object, then delete the memory if needed.
  Destruct();
  if (m_Mem != m_Buf)
    delete [] m_Mem;
}

void* StoredValueRef::StoredValue::GetDtorWrapperPtr(CXXRecordDecl* CXXRD) {
   std::string funcname;
  {
    llvm::raw_string_ostream namestr(funcname);
    namestr << "__cling_StoredValue_Destruct_" << CXXRD;
  }
  void* dtorWrapperPtr = m_Interp.getAddressOfGlobal(funcname.c_str());
  if (dtorWrapperPtr)
    return dtorWrapperPtr;

  std::string code("extern \"C\" void ");
  std::string typeName
    = utils::TypeName::GetFullyQualifiedName(getClangType(),
                                             CXXRD->getASTContext());
  code += funcname + "(void* obj){((" + typeName + "*)obj)->~"
    + getClangType().toString() +"();}";
  m_Interp.declare(code);
  return m_Interp.getAddressOfGlobal(funcname.c_str());
}

void StoredValueRef::StoredValue::Destruct() {
  // If applicable, call addr->~Type() to destruct the object.
  // template <typename T> void destr(T* obj = 0) { (T)obj->~T(); }
  // |-FunctionDecl destr 'void (struct XB *)'
  // |-TemplateArgument type 'struct XB'
  // |-ParmVarDecl obj 'struct XB *'
  // `-CompoundStmt
  //   `-CXXMemberCallExpr 'void'
  //     `-MemberExpr '<bound member function type>' ->~XB
  //       `-ImplicitCastExpr 'struct XB *' <LValueToRValue>
  //         `-DeclRefExpr  'struct XB *' lvalue ParmVar 'obj' 'struct XB *'

  if (getClangType.isConst())
    return;
  const RecordType* RT = dyn_cast<RecordType>(getClangType());
  if (!RT)
    return;
  CXXRecordDecl* CXXRD = dyn_cast<CXXRecordDecl>(RT->getDecl());
  if (!CXXRD || CXXRD->hasTrivialDestructor())
    return;

  CXXRD = CXXRD->getCanonicalDecl();
  void* funcPtr = GetDtorWrapperPtr(CXXRD);
  if (!funcPtr)
    return;

  typedef void (*DtorWrapperFunc_t)(void* obj);
  DtorWrapperFunc_t wrapperFuncPtr = (DtorWrapperFunc_t) funcPtr;
  (*wrapperFuncPtr)(getAs<void*>());
}

long long StoredValueRef::StoredValue::getAllocSizeInBytes() const {
  const ASTContext& ctx = m_Interp.getCI()->getASTContext();
  return (long long) ctx.getTypeSizeInChars(getClangType()).getQuantity();
}

void StoredValueRef::dump() const {
  ASTContext& ctx = m_Value->m_Interp.getCI()->getASTContext();
  valuePrinterInternal::StreamStoredValueRef(llvm::errs(), this, ctx);
}

StoredValueRef StoredValueRef::allocate(Interpreter& interp, QualType t,
                                        const llvm::Type* llvmTy) {
  return new StoredValue(interp, t, llvmTy);
}

StoredValueRef StoredValueRef::bitwiseCopy(Interpreter& interp,
                                           const Value& value) {
  StoredValue* SValue
    = new StoredValue(interp, value.getClangType(), value.getLLVMType());
  if (SValue->m_Mem) {
    const char* src = (const char*)value.getGV().PointerVal;
    // It's not a pointer. LLVM stores a char[5] (i.e. 5 x i8) as an i40,
    // so use that instead. We don't keep it as an int; instead, we "allocate"
    // it as a "proper" char[5] in the m_Mem. "Allocate" because it uses the
    // m_Buf, so no actual allocation happens.
    uint64_t IntVal = value.getGV().IntVal.getSExtValue();
    if (!src) src = (const char*)&IntVal;
    memcpy(SValue->m_Mem, src,
           SValue->getAllocSizeInBytes());
  } else {
    SValue->setGV(value.getGV());
  }
  return SValue;
}
<|endoftext|>


<commit_before>#include <memory>
#include <algorithm>
#include <iterator>
#include <unordered_set>
#include <unordered_map>

#include "s_rules.hh"
#include "s_closure.hh"
#include "cons_util.hh"
#include "env.hh"
#include "zs_error.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_util.hh"
#include "printer.hh"
#include "hasher.hh"

// #include <iostream>

using namespace std;

namespace Procedure{

namespace {

Lisp_ptr pick_first(Lisp_ptr p){
  if(p.tag() == Ptr_tag::cons){
    auto c = p.get<Cons*>();
    if(!c) throw zs_error("syntax-rules: the pattern is empty list\n");

    return c->car();
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();
    assert(v);
    if(v->empty()) throw zs_error("syntax-rules: the pattern is empty vector\n");

    return (*v)[0];
  }else{
    throw zs_error("syntax-rules: informal pattern passed! (%s)\n", stringify(p.tag()));
  }
}

void check_pattern(const SyntaxRules& sr, Lisp_ptr p,
                   unordered_set<Lisp_ptr> tab){
  if(identifierp(p)){
    if(find(begin(sr.literals()), end(sr.literals()), p) != end(sr.literals())){
      // literal identifier
      return;
    }

    // pattern variable
    if(tab.find(p) != tab.end()){
      throw zs_error("syntax-rules error: duplicated pattern variable! (%s)\n",
                     identifier_symbol(p)->name().c_str());
    }
    tab.insert(p);
    return;
  }else if(p.tag() == Ptr_tag::cons){
    if(nullp(p)) return;

    auto i = begin(p);

    for(; i; ++i){
      check_pattern(sr, *i, tab);
    }

    check_pattern(sr, i.base(), tab);
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();

    for(auto i : *v){
      check_pattern(sr, i, tab);
    }
  }else{
    return;
  }
}

void check_pattern(const SyntaxRules& sr, Lisp_ptr p){
  pick_first(p);
  check_pattern(sr, p, {});
}

} // namespace

constexpr ProcInfo SyntaxRules::sr_procinfo;

SyntaxRules::SyntaxRules(Env* e, Lisp_ptr lits, Lisp_ptr rls)
  : env_(e), literals_(lits), rules_(rls){
  for(auto i : lits){
    if(!identifierp(i))
      throw builtin_identifier_check_failed("syntax-rules", i);
  }

  for(auto i : rls){
    bind_cons_list_strict
      (i,
       [&](Lisp_ptr pat, Lisp_ptr tmpl){
        (void)tmpl;
        check_pattern(*this, pat);
      });
  }
}

SyntaxRules::~SyntaxRules() = default;

static
bool try_match_1(std::unordered_map<Lisp_ptr, Lisp_ptr>& match_obj,
                 const SyntaxRules& sr, Lisp_ptr ignore_ident, Lisp_ptr pattern,
                 Env* form_env, Lisp_ptr form){

  // cout << __func__ << "\tpattern = " << pattern << "\n\t\tform = " << form << endl;
  // for(auto ii : match_obj){
  //   cout << '\t' << ii.first << " = " << ii.second << '\n';
  // }

  if(form.tag() == Ptr_tag::syntactic_closure){
    // destruct syntactic closure
    auto sc = form.get<SyntacticClosure*>();

    return try_match_1(match_obj, sr, ignore_ident, pattern, sc->env(), sc->expr());
  }

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(pattern)){
    if(find(begin(sr.literals()), end(sr.literals()), pattern) != end(sr.literals())){
      // literal identifier
      // if(!identifierp(form))
      //   cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      if(!identifierp(form)) return false;

      // if(!identifier_eq(sr.env(), pattern, form_env, form))
      //   cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return identifier_eq(sr.env(), pattern, form_env, form);
    }else{
      // non-literal identifier
      if(pattern != ignore_ident){
        match_obj.insert({pattern, new SyntacticClosure(form_env, nullptr, form)});
      }
      return true;
    }
  }else if(pattern.tag() == Ptr_tag::cons){
    if(form.tag() != Ptr_tag::cons){
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }

    if(nullp(pattern) && nullp(form)){
      return true;
    }

    auto p_i = begin(pattern);
    auto f_i = begin(form);

    for(; p_i; ++p_i, (f_i ? ++f_i : f_i)){
      // checks ellipsis
      auto p_n = next(p_i);
      if((p_n) && identifierp(*p_n) && identifier_symbol(*p_n) == ellipsis_sym){
        if(identifierp(*p_i)){
          // like: (A B C ...)
          if(*p_i == ignore_ident){
            throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
          }

          auto p_e = p_i;
          while(p_e) ++p_e;

          if(!nullp(p_e.base())){
            throw zs_error("syntax-rules error: '...' is appeared in a inproper list pattern!\n");
          }

          auto f_e = f_i;
          while(f_e) ++f_e;

          if(!nullp(f_e.base())){
            throw zs_error("syntax-rules error: '...' is used for a inproper list form!\n");
          }

          match_obj.insert({*p_i, f_i.base()});
          return true;
        }else{
          // like: ((A B C) ...)
          throw zs_error("syntax-rules error: ellipsis pattern is under implementing...\n");
        }
      }

      if(!f_i) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(match_obj, sr, ignore_ident, *p_i, form_env, *f_i)){
        // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
        return false;
      }
    }

    // checks length
    if((p_i.base().tag() == Ptr_tag::cons) && (f_i.base().tag() == Ptr_tag::cons)){
      // cout << "\treached @ " << __LINE__ << endl;
      // cout << "\t\t pat = " << p_i.base() << ", form = " << f_i.base() << endl;
      return (nullp(p_i.base()) && nullp(f_i.base()));
    }else{
      // dotted list case
      // cout << __func__ << "\treached @ " << __LINE__ << endl;
      return try_match_1(match_obj, sr, ignore_ident, p_i.base(), form_env, f_i.base());
    }
  }else if(pattern.tag() == Ptr_tag::vector){
    if(form.tag() != Ptr_tag::vector){
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }

    auto p_v = pattern.get<Vector*>();
    auto f_v = form.get<Vector*>();

    auto p_i = begin(*p_v), p_e = end(*p_v);
    auto f_i = begin(*f_v), f_e = end(*f_v);

    for(; p_i != p_e; ++p_i, ++f_i){
      // checks ellipsis
      auto p_n = next(p_i);

      if((p_n != p_e) && identifierp(*p_n) && identifier_symbol(*p_n) == ellipsis_sym){
        if(identifierp(*p_i)){
          // like: (A B C ...)
          if(*p_i == ignore_ident){
            throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
          }

          match_obj.insert({*p_i, new Vector(f_i, f_e)});
          return true;
        }else{
          // like: ((A B C) ...)
          throw zs_error("syntax-rules error: ellipsis pattern is under implementing...\n");
        }
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(match_obj, sr, ignore_ident, *p_i, form_env, *f_i)){
        // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return true;
    }else{
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }
  }else{
    // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
    return equal_internal(pattern, form);
  }
}

static
Lisp_ptr expand(const std::unordered_map<Lisp_ptr, Lisp_ptr>& match_obj,
                Lisp_ptr tmpl){
  // cout << __func__ << " arg = " << tmpl << endl;

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(tmpl)){
    auto m_ret = match_obj.find(tmpl);
    if(m_ret != match_obj.end()){
      return m_ret->second;
    }else{
      return tmpl;
    }
  }else if(tmpl.tag() == Ptr_tag::cons){
    if(nullp(tmpl)) return tmpl;

    GrowList gl;
    auto t_i = begin(tmpl);

    for(; t_i; ++t_i){
      auto t_n = next(t_i);

      // check ellipsis
      if(identifierp(*t_i)
         && (t_n) && identifierp(*t_n)
         && identifier_symbol(*t_n) == ellipsis_sym){
        auto m_ret = match_obj.find(*t_i);

        if(m_ret == match_obj.end()){
          throw zs_error("syntax-rules error: invalid template: followed by '...', but not bound by pattern\n");
        }

        if(m_ret->second.tag() == Ptr_tag::cons){
          // this can be replaced directly?
          for(auto i : m_ret->second){
            gl.push(i);
          }
        }else if(m_ret->second.tag() == Ptr_tag::vector){
          auto m_ret_vec = m_ret->second.get<Vector*>();
          for(auto i : *m_ret_vec){
            gl.push(i);
          }
        }else{
          throw zs_error("syntax-rules error: invalid template: not sequence type\n");
        }

        ++t_i;
      }else{
        gl.push(expand(match_obj, *t_i));
      }
    }

    return gl.extract_with_tail(expand(match_obj, t_i.base()));
  }else if(tmpl.tag() == Ptr_tag::vector){
    auto t_vec = tmpl.get<Vector*>();

    Vector vec;

    for(auto t_i = begin(*t_vec), t_e = end(*t_vec); t_i != t_e; ++t_i){
      auto t_n = next(t_i);

      // check ellipsis
      if(identifierp(*t_i)
         && (t_n != t_e) && identifierp(*t_n)
         && identifier_symbol(*t_n) == ellipsis_sym){
        auto m_ret = match_obj.find(*t_i);

        if(m_ret == match_obj.end()){
          throw zs_error("syntax-rules error: invalid template: followed by '...', but not bound by pattern\n");
        }

        if(m_ret->second.tag() == Ptr_tag::cons){
          vec.insert(vec.end(), begin(m_ret->second), end(m_ret->second));
        }else if(m_ret->second.tag() == Ptr_tag::vector){
          auto m_ret_vec = m_ret->second.get<Vector*>();
          vec.insert(vec.end(), begin(*m_ret_vec), end(*m_ret_vec));
        }else{
          throw zs_error("syntax-rules error: invalid template: not sequence type\n");
        }

        ++t_i;
      }else{
        vec.push_back(expand(match_obj, *t_i));
      }
    }

    return new Vector(move(vec));
  }else{
    return tmpl;
  }
}

Lisp_ptr SyntaxRules::apply(Lisp_ptr form, Env* form_env) const{
  std::unordered_map<Lisp_ptr, Lisp_ptr> match_obj;

  // cout << "## " << __func__ << ": form = " << form << endl;

  for(auto i : this->rules()){
    auto pat = i.get<Cons*>()->car();
    auto tmpl = i.get<Cons*>()->cdr().get<Cons*>()->car();

    // cout << "## trying: pattern = " << pat << endl;

    auto ignore_ident = pick_first(pat);
    if(try_match_1(match_obj, *this, ignore_ident, pat, form_env, form)){
      // cout << "## matched!: pattern = " << pat << '\n';
      // for(auto ii : match_obj){
      //   cout << '\t' << ii.first << " = " << ii.second << '\n' << endl;;
      // }

      return expand(match_obj, tmpl);
    }else{
      // cleaning map
      for(auto e : match_obj){
        if(auto sc = e.second.get<SyntacticClosure*>()){
          delete sc;
        }
      }
      match_obj.clear();
    }
  }

  // cout << "## no match: form = " << form << endl;
  throw zs_error("syntax-rules error: no matching pattern found!\n");
}

} // Procedure
<commit_msg>fixed syntax-rules ellipsis treating (not completed)<commit_after>#include <memory>
#include <algorithm>
#include <iterator>
#include <unordered_set>
#include <unordered_map>

#include "s_rules.hh"
#include "s_closure.hh"
#include "cons_util.hh"
#include "env.hh"
#include "zs_error.hh"
#include "builtin_equal.hh"
#include "builtin_extra.hh"
#include "builtin_util.hh"
#include "printer.hh"
#include "hasher.hh"

// #include <iostream>

using namespace std;

namespace Procedure{

namespace {

Lisp_ptr pick_first(Lisp_ptr p){
  if(p.tag() == Ptr_tag::cons){
    auto c = p.get<Cons*>();
    if(!c) throw zs_error("syntax-rules: the pattern is empty list\n");

    return c->car();
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();
    assert(v);
    if(v->empty()) throw zs_error("syntax-rules: the pattern is empty vector\n");

    return (*v)[0];
  }else{
    throw zs_error("syntax-rules: informal pattern passed! (%s)\n", stringify(p.tag()));
  }
}

void check_pattern(const SyntaxRules& sr, Lisp_ptr p,
                   unordered_set<Lisp_ptr> tab){
  if(identifierp(p)){
    if(find(begin(sr.literals()), end(sr.literals()), p) != end(sr.literals())){
      // literal identifier
      return;
    }

    // pattern variable
    if(tab.find(p) != tab.end()){
      throw zs_error("syntax-rules error: duplicated pattern variable! (%s)\n",
                     identifier_symbol(p)->name().c_str());
    }
    tab.insert(p);
    return;
  }else if(p.tag() == Ptr_tag::cons){
    if(nullp(p)) return;

    auto i = begin(p);

    for(; i; ++i){
      check_pattern(sr, *i, tab);
    }

    check_pattern(sr, i.base(), tab);
  }else if(p.tag() == Ptr_tag::vector){
    auto v = p.get<Vector*>();

    for(auto i : *v){
      check_pattern(sr, i, tab);
    }
  }else{
    return;
  }
}

void check_pattern(const SyntaxRules& sr, Lisp_ptr p){
  pick_first(p);
  check_pattern(sr, p, {});
}

} // namespace

constexpr ProcInfo SyntaxRules::sr_procinfo;

SyntaxRules::SyntaxRules(Env* e, Lisp_ptr lits, Lisp_ptr rls)
  : env_(e), literals_(lits), rules_(rls){
  for(auto i : lits){
    if(!identifierp(i))
      throw builtin_identifier_check_failed("syntax-rules", i);
  }

  for(auto i : rls){
    bind_cons_list_strict
      (i,
       [&](Lisp_ptr pat, Lisp_ptr tmpl){
        (void)tmpl;
        check_pattern(*this, pat);
      });
  }
}

SyntaxRules::~SyntaxRules() = default;

static
void ensure_binding(std::unordered_map<Lisp_ptr, Lisp_ptr>& match_obj,
                    const SyntaxRules& sr, Lisp_ptr ignore_ident, Lisp_ptr pattern){
  if(identifierp(pattern)){
    if(find(begin(sr.literals()), end(sr.literals()), pattern) != end(sr.literals())){
      return;
    }else{
      // non-literal identifier
      if(pattern != ignore_ident){
        match_obj.insert({pattern, new Vector()});
      }
      return;
    }
  }else if(pattern.tag() == Ptr_tag::cons){
    if(nullp(pattern)){
      return;
    }

    auto p_i = begin(pattern);

    for(; p_i; ++p_i){
      ensure_binding(match_obj, sr, ignore_ident, *p_i);
    }

    // checks length
    if((p_i.base().tag() == Ptr_tag::cons)){
      return;
    }else{
      // dotted list case
      ensure_binding(match_obj, sr, ignore_ident, p_i.base());
      return;
    }
  }else if(pattern.tag() == Ptr_tag::vector){
    auto p_v = pattern.get<Vector*>();
    auto p_i = begin(*p_v), p_e = end(*p_v);

    for(; p_i != p_e; ++p_i){
      ensure_binding(match_obj, sr, ignore_ident, *p_i);
    }
  }else{
    return;
  }

}

static
bool try_match_1(std::unordered_map<Lisp_ptr, Lisp_ptr>& match_obj,
                 const SyntaxRules& sr, Lisp_ptr ignore_ident, Lisp_ptr pattern,
                 Env* form_env, Lisp_ptr form,
                 bool insert_by_push){

  // cout << __func__ << "\tpattern = " << pattern << "\n\t\tform = " << form << endl;
  // for(auto ii : match_obj){
  //   cout << '\t' << ii.first << " = " << ii.second << '\n';
  // }

  if(form.tag() == Ptr_tag::syntactic_closure){
    // destruct syntactic closure
    auto sc = form.get<SyntacticClosure*>();

    return try_match_1(match_obj, sr, ignore_ident, pattern, sc->env(), sc->expr(), insert_by_push);
  }

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(pattern)){
    if(find(begin(sr.literals()), end(sr.literals()), pattern) != end(sr.literals())){
      // literal identifier
      // if(!identifierp(form))
      //   cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      if(!identifierp(form)) return false;

      // if(!identifier_eq(sr.env(), pattern, form_env, form))
      //   cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return identifier_eq(sr.env(), pattern, form_env, form);
    }else{
      // non-literal identifier
      if(pattern != ignore_ident){
        auto val = new SyntacticClosure(form_env, nullptr, form);
        if(insert_by_push){
          auto place = match_obj.find(pattern);
          assert(place->second.tag() == Ptr_tag::vector);
          place->second.get<Vector*>()->push_back(val);
        }else{
          match_obj.insert({pattern, val});
        }
      }
      return true;
    }
  }else if(pattern.tag() == Ptr_tag::cons){
    if(form.tag() != Ptr_tag::cons){
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }

    if(nullp(pattern) && nullp(form)){
      return true;
    }

    auto p_i = begin(pattern);
    auto f_i = begin(form);

    for(; p_i; ++p_i, (f_i ? ++f_i : f_i)){
      // checks ellipsis
      auto p_n = next(p_i);
      if((p_n) && identifierp(*p_n) && identifier_symbol(*p_n) == ellipsis_sym){
        if(*p_i == ignore_ident){
          throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
        }

        auto p_e = p_i;
        while(p_e) ++p_e;

        if(!nullp(p_e.base())){
          throw zs_error("syntax-rules error: '...' is appeared in a inproper list pattern!\n");
        }

        // accumulating...
        ensure_binding(match_obj, sr, ignore_ident, *p_i);
        for(; f_i; ++f_i){
          if(!try_match_1(match_obj, sr, ignore_ident, *p_i, form_env, *f_i, true)){
            // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
            return false;
          }
        }

        if(!nullp(f_i.base())){
          throw zs_error("syntax-rules error: '...' is used for a inproper list form!\n");
        }

        return true;
      }

      if(!f_i) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(match_obj, sr, ignore_ident, *p_i, form_env, *f_i, insert_by_push)){
        // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
        return false;
      }
    }

    // checks length
    if((p_i.base().tag() == Ptr_tag::cons) && (f_i.base().tag() == Ptr_tag::cons)){
      // cout << "\treached @ " << __LINE__ << endl;
      // cout << "\t\t pat = " << p_i.base() << ", form = " << f_i.base() << endl;
      return (nullp(p_i.base()) && nullp(f_i.base()));
    }else{
      // dotted list case
      // cout << __func__ << "\treached @ " << __LINE__ << endl;
      return try_match_1(match_obj, sr, ignore_ident, p_i.base(), form_env, f_i.base(), insert_by_push);
    }
  }else if(pattern.tag() == Ptr_tag::vector){
    if(form.tag() != Ptr_tag::vector){
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }

    auto p_v = pattern.get<Vector*>();
    auto f_v = form.get<Vector*>();

    auto p_i = begin(*p_v), p_e = end(*p_v);
    auto f_i = begin(*f_v), f_e = end(*f_v);

    for(; p_i != p_e; ++p_i, ++f_i){
      // checks ellipsis
      auto p_n = next(p_i);

      if((p_n != p_e) && identifierp(*p_n) && identifier_symbol(*p_n) == ellipsis_sym){
        if(identifierp(*p_i)){
          // like: (A B C ...)
          if(*p_i == ignore_ident){
            throw zs_error("syntax-rules error: '...' is appeared following the first identifier.\n");
          }

          match_obj.insert({*p_i, new Vector(f_i, f_e)});
          return true;
        }else{
          // like: ((A B C) ...)
          throw zs_error("syntax-rules error: ellipsis pattern is under implementing...\n");
        }
      }

      if(f_i == f_e) break; // this check is delayed to here, for checking the ellipsis.

      if(!try_match_1(match_obj, sr, ignore_ident, *p_i, form_env, *f_i, insert_by_push)){
        // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
        return false;
      }
    }

    // checks length
    if((p_i == p_e) && (f_i == f_e)){
      return true;
    }else{
      // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
      return false;
    }
  }else{
    // cout << __func__ << "\tcheck failed @ " << __LINE__ << endl;
    return equal_internal(pattern, form);
  }
}

static
Lisp_ptr expand(const std::unordered_map<Lisp_ptr, Lisp_ptr>& match_obj,
                Lisp_ptr tmpl){
  // cout << __func__ << " arg = " << tmpl << endl;
  // for(auto ii : match_obj){
  //   cout << '\t' << ii.first << " = " << ii.second << '\n';
  // }

  const auto ellipsis_sym = intern(vm.symtable(), "...");

  if(identifierp(tmpl)){
    auto m_ret = match_obj.find(tmpl);
    if(m_ret != match_obj.end()){
      return m_ret->second;
    }else{
      return tmpl;
    }
  }else if(tmpl.tag() == Ptr_tag::cons){
    if(nullp(tmpl)) return tmpl;

    GrowList gl;
    auto t_i = begin(tmpl);

    for(; t_i; ++t_i){
      auto t_n = next(t_i);

      // check ellipsis
      if(identifierp(*t_i)
         && (t_n) && identifierp(*t_n)
         && identifier_symbol(*t_n) == ellipsis_sym){
        auto m_ret = match_obj.find(*t_i);

        if(m_ret == match_obj.end()){
          // cout << __func__ << " key = " << *t_i << endl;
          throw zs_error("syntax-rules error: invalid template: followed by '...', but not bound by pattern\n");
        }

        if(m_ret->second.tag() == Ptr_tag::cons){
          // this can be replaced directly?
          for(auto i : m_ret->second){
            gl.push(i);
          }
        }else if(m_ret->second.tag() == Ptr_tag::vector){
          auto m_ret_vec = m_ret->second.get<Vector*>();
          for(auto i : *m_ret_vec){
            gl.push(i);
          }
        }else{
          throw zs_error("syntax-rules error: invalid template: not sequence type\n");
        }

        ++t_i;
      }else{
        gl.push(expand(match_obj, *t_i));
      }
    }

    return gl.extract_with_tail(expand(match_obj, t_i.base()));
  }else if(tmpl.tag() == Ptr_tag::vector){
    auto t_vec = tmpl.get<Vector*>();

    Vector vec;

    for(auto t_i = begin(*t_vec), t_e = end(*t_vec); t_i != t_e; ++t_i){
      auto t_n = next(t_i);

      // check ellipsis
      if(identifierp(*t_i)
         && (t_n != t_e) && identifierp(*t_n)
         && identifier_symbol(*t_n) == ellipsis_sym){
        auto m_ret = match_obj.find(*t_i);

        if(m_ret == match_obj.end()){
          throw zs_error("syntax-rules error: invalid template: followed by '...', but not bound by pattern\n");
        }

        if(m_ret->second.tag() == Ptr_tag::cons){
          vec.insert(vec.end(), begin(m_ret->second), end(m_ret->second));
        }else if(m_ret->second.tag() == Ptr_tag::vector){
          auto m_ret_vec = m_ret->second.get<Vector*>();
          vec.insert(vec.end(), begin(*m_ret_vec), end(*m_ret_vec));
        }else{
          throw zs_error("syntax-rules error: invalid template: not sequence type\n");
        }

        ++t_i;
      }else{
        vec.push_back(expand(match_obj, *t_i));
      }
    }

    return new Vector(move(vec));
  }else{
    return tmpl;
  }
}

Lisp_ptr SyntaxRules::apply(Lisp_ptr form, Env* form_env) const{
  std::unordered_map<Lisp_ptr, Lisp_ptr> match_obj;

  // cout << "## " << __func__ << ": form = " << form << endl;

  for(auto i : this->rules()){
    auto pat = i.get<Cons*>()->car();
    auto tmpl = i.get<Cons*>()->cdr().get<Cons*>()->car();

    // cout << "## trying: pattern = " << pat << endl;

    auto ignore_ident = pick_first(pat);
    if(try_match_1(match_obj, *this, ignore_ident, pat, form_env, form, false)){
      // cout << "## matched!:\tpattern = " << pat << '\n';
      // cout << "## \t\tform = " << form << '\n';
      // for(auto ii : match_obj){
      //   cout << '\t' << ii.first << " = " << ii.second << '\n';
      // }

      auto ex = expand(match_obj, tmpl);
      // cout << "## expand = " << ex << '\n';
      // cout << endl;
      return ex;
    }else{
      // cleaning map
      for(auto e : match_obj){
        if(auto sc = e.second.get<SyntacticClosure*>()){
          delete sc;
        }
      }
      match_obj.clear();
    }
  }

  // cout << "## no match: form = " << form << endl;
  throw zs_error("syntax-rules error: no matching pattern found!\n");
}

} // Procedure
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2257
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1333184 by johtaylo@johtaylo-jtincrementor-increment on 2016/10/28 03:00:05<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2258
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2571
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1503341 by johtaylo@johtaylo-jtincrementor2-increment on 2018/01/13 03:00:06<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2572
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2897
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1781819 by chui@ocl-promo-incrementor on 2019/05/13 03:00:04<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2898
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2368
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1376751 by johtaylo@johtaylo-jtincrementor-increment on 2017/02/23 03:00:05<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2369
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2544
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1487469 by johtaylo@johtaylo-jtincrementor2-increment on 2017/11/28 03:00:04<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2545
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2778
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1709971 by chui@ocl-promo-incrementor on 2018/11/21 03:00:10<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 2779
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2029
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<commit_msg>P4 to Git Change 1235185 by johtaylo@johtaylo-JTBUILDER03-increment on 2016/02/08 03:00:10<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
# define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
# define AMD_PLATFORM_BUILD_NUMBER 2030
#endif // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
# define AMD_PLATFORM_REVISION_NUMBER 0
#endif // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
# define AMD_PLATFORM_RELEASE_INFO
#endif // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING XSTR(AMD_PLATFORM_BUILD_NUMBER) \
    "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
# define AMD_PLATFORM_INFO "AMD-APP" AMD_PLATFORM_RELEASE_INFO \
    DEBUG_ONLY("." IF(IS_OPTIMIZED,"opt","dbg")) " (" AMD_BUILD_STRING ")"
#endif // ATI_PLATFORM_INFO

#endif // VERSIONS_HPP_
<|endoftext|>


<commit_before>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3034
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<commit_msg>P4 to Git Change 2027775 by chui@ocl-promo-incrementor on 2019/11/09 03:00:06<commit_after>//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//

#ifndef VERSIONS_HPP_
#define VERSIONS_HPP_

#include "utils/macros.hpp"

#ifndef AMD_PLATFORM_NAME
#define AMD_PLATFORM_NAME "AMD Accelerated Parallel Processing"
#endif  // AMD_PLATFORM_NAME

#ifndef AMD_PLATFORM_BUILD_NUMBER
#define AMD_PLATFORM_BUILD_NUMBER 3035
#endif  // AMD_PLATFORM_BUILD_NUMBER

#ifndef AMD_PLATFORM_REVISION_NUMBER
#define AMD_PLATFORM_REVISION_NUMBER 0
#endif  // AMD_PLATFORM_REVISION_NUMBER

#ifndef AMD_PLATFORM_RELEASE_INFO
#define AMD_PLATFORM_RELEASE_INFO
#endif  // AMD_PLATFORM_RELEASE_INFO

#define AMD_BUILD_STRING                                                                           \
  XSTR(AMD_PLATFORM_BUILD_NUMBER)                                                                  \
  "." XSTR(AMD_PLATFORM_REVISION_NUMBER)

#ifndef AMD_PLATFORM_INFO
#define AMD_PLATFORM_INFO                                                                          \
  "AMD-APP" AMD_PLATFORM_RELEASE_INFO DEBUG_ONLY(                                                  \
      "." IF(IS_OPTIMIZED, "opt", "dbg")) " (" AMD_BUILD_STRING ")"
#endif  // ATI_PLATFORM_INFO

#endif  // VERSIONS_HPP_
<|endoftext|>


<commit_before>// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
//    (See accompanying file LICENSE-Apache or copy at
//     http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE-Boost or copy at
//     https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

#include <math.h>
#include <inttypes.h>
#include <iostream>
#include <string.h>
#include <chrono>
#include <random>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(__linux__)
#include <sys/types.h>
#include <unistd.h>
#endif

#include "ryu/ryu.h"
#include "third_party/double-conversion/double-conversion/utils.h"
#include "third_party/double-conversion/double-conversion/double-conversion.h"

using double_conversion::StringBuilder;
using double_conversion::DoubleToStringConverter;
using namespace std::chrono;

constexpr int BUFFER_SIZE = 40;
static char buffer[BUFFER_SIZE];
static DoubleToStringConverter converter(
    DoubleToStringConverter::Flags::EMIT_TRAILING_DECIMAL_POINT
        | DoubleToStringConverter::Flags::EMIT_TRAILING_ZERO_AFTER_POINT,
    "Infinity",
    "NaN",
    'E',
    7,
    7,
    0,
    0);
static StringBuilder builder(buffer, BUFFER_SIZE);

void fcv(float value) {
  builder.Reset();
  converter.ToShortestSingle(value, &builder);
  builder.Finalize();
}

void dcv(double value) {
  builder.Reset();
  converter.ToShortest(value, &builder);
  builder.Finalize();
}

static float int32Bits2Float(uint32_t bits) {
  float f;
  memcpy(&f, &bits, sizeof(float));
  return f;
}

static double int64Bits2Double(uint64_t bits) {
  double f;
  memcpy(&f, &bits, sizeof(double));
  return f;
}

struct mean_and_variance {
  int64_t n = 0;
  double mean = 0;
  double m2 = 0;

  void update(double x) {
    ++n;
    double d = x - mean;
    mean += d / n;
    double d2 = x - mean;
    m2 += d * d2;
  }

  double variance() const {
    return m2 / (n - 1);
  }

  double stddev() const {
    return sqrt(variance());
  }
};

float generate_float(std::mt19937& mt32) {
  uint32_t r = mt32();
  float f = int32Bits2Float(r);
  return f;
}

static int bench32(int samples, int iterations, bool verbose, bool ryu_only, bool classic) {
  char bufferown[BUFFER_SIZE];
  std::mt19937 mt32(12345);
  mean_and_variance mv1;
  mean_and_variance mv2;
  int throwaway = 0;
  if (classic) {
    for (int i = 0; i < samples; ++i) {
      const float f = generate_float(mt32);

      auto t1 = steady_clock::now();
      for (int j = 0; j < iterations; ++j) {
        f2s_buffered(f, bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(iterations);
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!ryu_only) {
        t1 = steady_clock::now();
        for (int j = 0; j < iterations; ++j) {
          fcv(f);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(iterations);
        mv2.update(delta2);
      }

      if (verbose) {
        if (ryu_only) {
          printf("%.6a,%f\n", f, delta1);
        } else {
          printf("%.6a,%f,%f\n", f, delta1, delta2);
        }
      }

      if (!ryu_only && strcmp(bufferown, buffer) != 0) {
        printf("For %.6a %20s %20s\n", f, bufferown, buffer);
      }
    }
  } else {
    std::vector<float> vec(samples);
    for (int i = 0; i < samples; ++i) {
      vec[i] = generate_float(mt32);
    }

    for (int j = 0; j < iterations; ++j) {
      auto t1 = steady_clock::now();
      for (int i = 0; i < samples; ++i) {
        f2s_buffered(vec[i], bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(samples);
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!ryu_only) {
        t1 = steady_clock::now();
        for (int i = 0; i < samples; ++i) {
          fcv(vec[i]);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(samples);
        mv2.update(delta2);
      }

      if (verbose) {
        if (ryu_only) {
          printf("%f\n", delta1);
        } else {
          printf("%f,%f\n", delta1, delta2);
        }
      }
    }
  }
  if (!verbose) {
    printf("32: %8.3f %8.3f", mv1.mean, mv1.stddev());
    if (!ryu_only) {
      printf("     %8.3f %8.3f", mv2.mean, mv2.stddev());
    }
    printf("\n");
  }
  return throwaway;
}

double generate_double(std::mt19937& mt32) {
  uint64_t r = mt32();
  r <<= 32;
  r |= mt32(); // calling mt32() in separate statements guarantees order of evaluation
  double f = int64Bits2Double(r);
  return f;
}

static int bench64(int samples, int iterations, bool verbose, bool ryu_only, bool classic) {
  char bufferown[BUFFER_SIZE];
  std::mt19937 mt32(12345);
  mean_and_variance mv1;
  mean_and_variance mv2;
  int throwaway = 0;
  if (classic) {
    for (int i = 0; i < samples; ++i) {
      const double f = generate_double(mt32);

      auto t1 = steady_clock::now();
      for (int j = 0; j < iterations; ++j) {
        d2s_buffered(f, bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(iterations);
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!ryu_only) {
        t1 = steady_clock::now();
        for (int j = 0; j < iterations; ++j) {
          dcv(f);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(iterations);
        mv2.update(delta2);
      }

      if (verbose) {
        if (ryu_only) {
          printf("%.13a,%f\n", f, delta1);
        } else {
          printf("%.13a,%f,%f\n", f, delta1, delta2);
        }
      }

      if (!ryu_only && strcmp(bufferown, buffer) != 0) {
        printf("For %.13a %28s %28s\n", f, bufferown, buffer);
      }
    }
  } else {
    std::vector<double> vec(samples);
    for (int i = 0; i < samples; ++i) {
      vec[i] = generate_double(mt32);
    }

    for (int j = 0; j < iterations; ++j) {
      auto t1 = steady_clock::now();
      for (int i = 0; i < samples; ++i) {
        d2s_buffered(vec[i], bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(samples);
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!ryu_only) {
        t1 = steady_clock::now();
        for (int i = 0; i < samples; ++i) {
          dcv(vec[i]);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(samples);
        mv2.update(delta2);
      }

      if (verbose) {
        if (ryu_only) {
          printf("%f\n", delta1);
        } else {
          printf("%f,%f\n", delta1, delta2);
        }
      }
    }
  }
  if (!verbose) {
    printf("64: %8.3f %8.3f", mv1.mean, mv1.stddev());
    if (!ryu_only) {
      printf("     %8.3f %8.3f", mv2.mean, mv2.stddev());
    }
    printf("\n");
  }
  return throwaway;
}

int main(int argc, char** argv) {
#if defined(__linux__)
  // Also disable hyperthreading with something like this:
  // cat /sys/devices/system/cpu/cpu*/topology/core_id
  // sudo /bin/bash -c "echo 0 > /sys/devices/system/cpu/cpu6/online"
  cpu_set_t my_set;
  CPU_ZERO(&my_set);
  CPU_SET(2, &my_set);
  sched_setaffinity(getpid(), sizeof(cpu_set_t), &my_set);
#endif

  // By default, run both 32 and 64-bit benchmarks with 10000 samples and 1000 iterations each.
  bool run32 = true;
  bool run64 = true;
  int samples = 10000;
  int iterations = 1000;
  bool verbose = false;
  bool ryu_only = false;
  bool classic = false;
  for (int i = 1; i < argc; ++i) {
    if (strcmp(argv[i], "-32") == 0) {
      run32 = true;
      run64 = false;
    } else if (strcmp(argv[i], "-64") == 0) {
      run32 = false;
      run64 = true;
    } else if (strcmp(argv[i], "-v") == 0) {
      verbose = true;
    } else if (strcmp(argv[i], "-ryu") == 0) {
      ryu_only = true;
    } else if (strcmp(argv[i], "-classic") == 0) {
      classic = true;
    } else if (strncmp(argv[i], "-samples=", 9) == 0) {
      sscanf(argv[i], "-samples=%i", &samples);
    } else if (strncmp(argv[i], "-iterations=", 12) == 0) {
      sscanf(argv[i], "-iterations=%i", &iterations);
    } else {
      printf("Unrecognized option '%s'.\n", argv[i]);
      return EXIT_FAILURE;
    }
  }

  if (!verbose) {
    // No need to buffer the output if we're just going to print three lines.
    setbuf(stdout, NULL);
  }

  if (verbose) {
    printf("%sryu_time_in_ns%s\n", classic ? "hexfloat," : "", ryu_only ? "" : ",grisu3_time_in_ns");
  } else {
    printf("    Average & Stddev Ryu%s\n", ryu_only ? "" : "  Average & Stddev Grisu3");
  }
  int throwaway = 0;
  if (run32) {
    throwaway += bench32(samples, iterations, verbose, ryu_only, classic);
  }
  if (run64) {
    throwaway += bench64(samples, iterations, verbose, ryu_only, classic);
  }
  if (argc == 1000) {
    // Prevent the compiler from optimizing the code away.
    printf("%d\n", throwaway);
  }
  return 0;
}
<commit_msg>benchmark.cc: Extract benchmark_options.<commit_after>// Copyright 2018 Ulf Adams
//
// The contents of this file may be used under the terms of the Apache License,
// Version 2.0.
//
//    (See accompanying file LICENSE-Apache or copy at
//     http://www.apache.org/licenses/LICENSE-2.0)
//
// Alternatively, the contents of this file may be used under the terms of
// the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE-Boost or copy at
//     https://www.boost.org/LICENSE_1_0.txt)
//
// Unless required by applicable law or agreed to in writing, this software
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

#include <math.h>
#include <inttypes.h>
#include <iostream>
#include <string.h>
#include <chrono>
#include <random>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(__linux__)
#include <sys/types.h>
#include <unistd.h>
#endif

#include "ryu/ryu.h"
#include "third_party/double-conversion/double-conversion/utils.h"
#include "third_party/double-conversion/double-conversion/double-conversion.h"

using double_conversion::StringBuilder;
using double_conversion::DoubleToStringConverter;
using namespace std::chrono;

constexpr int BUFFER_SIZE = 40;
static char buffer[BUFFER_SIZE];
static DoubleToStringConverter converter(
    DoubleToStringConverter::Flags::EMIT_TRAILING_DECIMAL_POINT
        | DoubleToStringConverter::Flags::EMIT_TRAILING_ZERO_AFTER_POINT,
    "Infinity",
    "NaN",
    'E',
    7,
    7,
    0,
    0);
static StringBuilder builder(buffer, BUFFER_SIZE);

void fcv(float value) {
  builder.Reset();
  converter.ToShortestSingle(value, &builder);
  builder.Finalize();
}

void dcv(double value) {
  builder.Reset();
  converter.ToShortest(value, &builder);
  builder.Finalize();
}

static float int32Bits2Float(uint32_t bits) {
  float f;
  memcpy(&f, &bits, sizeof(float));
  return f;
}

static double int64Bits2Double(uint64_t bits) {
  double f;
  memcpy(&f, &bits, sizeof(double));
  return f;
}

struct mean_and_variance {
  int64_t n = 0;
  double mean = 0;
  double m2 = 0;

  void update(double x) {
    ++n;
    double d = x - mean;
    mean += d / n;
    double d2 = x - mean;
    m2 += d * d2;
  }

  double variance() const {
    return m2 / (n - 1);
  }

  double stddev() const {
    return sqrt(variance());
  }
};

class benchmark_options {
public:
  benchmark_options() = default;
  benchmark_options(const benchmark_options&) = delete;
  benchmark_options& operator=(const benchmark_options&) = delete;

  bool run32() const { return m_run32; }
  bool run64() const { return m_run64; }
  int samples() const { return m_samples; }
  int iterations() const { return m_iterations; }
  bool verbose() const { return m_verbose; }
  bool ryu_only() const { return m_ryu_only; }
  bool classic() const { return m_classic; }

  void parse(const char * const arg) {
    if (strcmp(arg, "-32") == 0) {
      m_run32 = true;
      m_run64 = false;
    } else if (strcmp(arg, "-64") == 0) {
      m_run32 = false;
      m_run64 = true;
    } else if (strcmp(arg, "-v") == 0) {
      m_verbose = true;
    } else if (strcmp(arg, "-ryu") == 0) {
      m_ryu_only = true;
    } else if (strcmp(arg, "-classic") == 0) {
      m_classic = true;
    } else if (strncmp(arg, "-samples=", 9) == 0) {
      sscanf(arg, "-samples=%i", &m_samples);
    } else if (strncmp(arg, "-iterations=", 12) == 0) {
      sscanf(arg, "-iterations=%i", &m_iterations);
    } else {
      printf("Unrecognized option '%s'.\n", arg);
      exit(EXIT_FAILURE);
    }
  }

private:
  // By default, run both 32 and 64-bit benchmarks with 10000 samples and 1000 iterations each.
  bool m_run32 = true;
  bool m_run64 = true;
  int m_samples = 10000;
  int m_iterations = 1000;
  bool m_verbose = false;
  bool m_ryu_only = false;
  bool m_classic = false;
};

float generate_float(std::mt19937& mt32) {
  uint32_t r = mt32();
  float f = int32Bits2Float(r);
  return f;
}

static int bench32(const benchmark_options& options) {
  char bufferown[BUFFER_SIZE];
  std::mt19937 mt32(12345);
  mean_and_variance mv1;
  mean_and_variance mv2;
  int throwaway = 0;
  if (options.classic()) {
    for (int i = 0; i < options.samples(); ++i) {
      const float f = generate_float(mt32);

      auto t1 = steady_clock::now();
      for (int j = 0; j < options.iterations(); ++j) {
        f2s_buffered(f, bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.iterations());
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!options.ryu_only()) {
        t1 = steady_clock::now();
        for (int j = 0; j < options.iterations(); ++j) {
          fcv(f);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.iterations());
        mv2.update(delta2);
      }

      if (options.verbose()) {
        if (options.ryu_only()) {
          printf("%.6a,%f\n", f, delta1);
        } else {
          printf("%.6a,%f,%f\n", f, delta1, delta2);
        }
      }

      if (!options.ryu_only() && strcmp(bufferown, buffer) != 0) {
        printf("For %.6a %20s %20s\n", f, bufferown, buffer);
      }
    }
  } else {
    std::vector<float> vec(options.samples());
    for (int i = 0; i < options.samples(); ++i) {
      vec[i] = generate_float(mt32);
    }

    for (int j = 0; j < options.iterations(); ++j) {
      auto t1 = steady_clock::now();
      for (int i = 0; i < options.samples(); ++i) {
        f2s_buffered(vec[i], bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.samples());
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!options.ryu_only()) {
        t1 = steady_clock::now();
        for (int i = 0; i < options.samples(); ++i) {
          fcv(vec[i]);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.samples());
        mv2.update(delta2);
      }

      if (options.verbose()) {
        if (options.ryu_only()) {
          printf("%f\n", delta1);
        } else {
          printf("%f,%f\n", delta1, delta2);
        }
      }
    }
  }
  if (!options.verbose()) {
    printf("32: %8.3f %8.3f", mv1.mean, mv1.stddev());
    if (!options.ryu_only()) {
      printf("     %8.3f %8.3f", mv2.mean, mv2.stddev());
    }
    printf("\n");
  }
  return throwaway;
}

double generate_double(std::mt19937& mt32) {
  uint64_t r = mt32();
  r <<= 32;
  r |= mt32(); // calling mt32() in separate statements guarantees order of evaluation
  double f = int64Bits2Double(r);
  return f;
}

static int bench64(const benchmark_options& options) {
  char bufferown[BUFFER_SIZE];
  std::mt19937 mt32(12345);
  mean_and_variance mv1;
  mean_and_variance mv2;
  int throwaway = 0;
  if (options.classic()) {
    for (int i = 0; i < options.samples(); ++i) {
      const double f = generate_double(mt32);

      auto t1 = steady_clock::now();
      for (int j = 0; j < options.iterations(); ++j) {
        d2s_buffered(f, bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.iterations());
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!options.ryu_only()) {
        t1 = steady_clock::now();
        for (int j = 0; j < options.iterations(); ++j) {
          dcv(f);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.iterations());
        mv2.update(delta2);
      }

      if (options.verbose()) {
        if (options.ryu_only()) {
          printf("%.13a,%f\n", f, delta1);
        } else {
          printf("%.13a,%f,%f\n", f, delta1, delta2);
        }
      }

      if (!options.ryu_only() && strcmp(bufferown, buffer) != 0) {
        printf("For %.13a %28s %28s\n", f, bufferown, buffer);
      }
    }
  } else {
    std::vector<double> vec(options.samples());
    for (int i = 0; i < options.samples(); ++i) {
      vec[i] = generate_double(mt32);
    }

    for (int j = 0; j < options.iterations(); ++j) {
      auto t1 = steady_clock::now();
      for (int i = 0; i < options.samples(); ++i) {
        d2s_buffered(vec[i], bufferown);
        throwaway += bufferown[2];
      }
      auto t2 = steady_clock::now();
      double delta1 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.samples());
      mv1.update(delta1);

      double delta2 = 0.0;
      if (!options.ryu_only()) {
        t1 = steady_clock::now();
        for (int i = 0; i < options.samples(); ++i) {
          dcv(vec[i]);
          throwaway += buffer[2];
        }
        t2 = steady_clock::now();
        delta2 = duration_cast<nanoseconds>(t2 - t1).count() / static_cast<double>(options.samples());
        mv2.update(delta2);
      }

      if (options.verbose()) {
        if (options.ryu_only()) {
          printf("%f\n", delta1);
        } else {
          printf("%f,%f\n", delta1, delta2);
        }
      }
    }
  }
  if (!options.verbose()) {
    printf("64: %8.3f %8.3f", mv1.mean, mv1.stddev());
    if (!options.ryu_only()) {
      printf("     %8.3f %8.3f", mv2.mean, mv2.stddev());
    }
    printf("\n");
  }
  return throwaway;
}

int main(int argc, char** argv) {
#if defined(__linux__)
  // Also disable hyperthreading with something like this:
  // cat /sys/devices/system/cpu/cpu*/topology/core_id
  // sudo /bin/bash -c "echo 0 > /sys/devices/system/cpu/cpu6/online"
  cpu_set_t my_set;
  CPU_ZERO(&my_set);
  CPU_SET(2, &my_set);
  sched_setaffinity(getpid(), sizeof(cpu_set_t), &my_set);
#endif

  benchmark_options options;

  for (int i = 1; i < argc; ++i) {
    options.parse(argv[i]);
  }

  if (!options.verbose()) {
    // No need to buffer the output if we're just going to print three lines.
    setbuf(stdout, NULL);
  }

  if (options.verbose()) {
    printf("%sryu_time_in_ns%s\n", options.classic() ? "hexfloat," : "", options.ryu_only() ? "" : ",grisu3_time_in_ns");
  } else {
    printf("    Average & Stddev Ryu%s\n", options.ryu_only() ? "" : "  Average & Stddev Grisu3");
  }
  int throwaway = 0;
  if (options.run32()) {
    throwaway += bench32(options);
  }
  if (options.run64()) {
    throwaway += bench64(options);
  }
  if (argc == 1000) {
    // Prevent the compiler from optimizing the code away.
    printf("%d\n", throwaway);
  }
  return 0;
}
<|endoftext|>