<commit_before>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
#include <aws/core/platform/FileSystem.h>

#include <aws/core/platform/Android.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>

#include <unistd.h>
#include <sys/stat.h>
#include <cerrno>
#include <dirent.h>
#include <cassert>

#include <mutex>

namespace Aws
{
namespace FileSystem
{

static const char* FILE_SYSTEM_UTILS_LOG_TAG = "FileSystem";

    class AndroidDirectory : public Directory
    {
    public:
        AndroidDirectory(const Aws::String& path, const Aws::String& relativePath) : Directory(path, relativePath), m_dir(nullptr)
        {
            m_dir = opendir(m_directoryEntry.path.c_str());

            if(m_dir)
            {
                m_directoryEntry.fileType = FileType::Directory;
            }
        }

        ~AndroidDirectory()
        {
            if (m_dir)
            {
                closedir(m_dir);
            }
        }

        DirectoryEntry Next() override
        {
            assert(m_dir);
            DirectoryEntry entry;

            dirent* dirEntry;
            bool invalidEntry(true);

            while(invalidEntry)
            {
                if ((dirEntry = readdir(m_dir)))
                {
                    Aws::String entryName = dirEntry->d_name;
                    if(entryName != ".." && entryName != ".")
                    {
                        entry = ParseFileInfo(dirEntry, true);
                        invalidEntry = false;
                    }
                }
                else
                {
                    break;
                }
            }

            return entry;
        }

    private:
        DirectoryEntry ParseFileInfo(dirent* dirEnt, bool computePath)
        {
            DirectoryEntry entry;

            if(computePath)
            {
                Aws::StringStream ss;
                ss << m_directoryEntry.path << PATH_DELIM << dirEnt->d_name;
                entry.path = ss.str();

                ss.str("");
                if(m_directoryEntry.relativePath.empty())
                {
                    ss << dirEnt->d_name;
                }
                else
                {
                    ss << m_directoryEntry.relativePath << PATH_DELIM << dirEnt->d_name;
                }
                entry.relativePath = ss.str();
            }
            else
            {
                entry.path = m_directoryEntry.path;
                entry.relativePath = m_directoryEntry.relativePath;
            }

            if(dirEnt->d_type == DT_DIR)
            {
                entry.fileType = FileType::Directory;
            }
            else if(dirEnt->d_type == DT_LNK)
            {
                entry.fileType = FileType::Symlink;
            }
            else
            {
                entry.fileType = FileType::File;
                FILE* fp = fopen(entry.path.c_str(), "r");
                if(fp)
                {
                    auto pos = ftell(fp);
                    fseek(fp, 0, SEEK_END);
                    auto end = ftell(fp);
                    fseek(fp, pos, SEEK_SET);
                    entry.fileSize = static_cast<int64_t>(end);
                    fclose(fp);
                }
            }

            return entry;
        }

        DIR* m_dir;
    };

Aws::String GetHomeDirectory()
{
    return Aws::Platform::GetCacheDirectory();
}

bool CreateDirectoryIfNotExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Creating directory " << path);

    int errorCode = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << path << " returned code: " << errno);
    return errorCode == 0 || errno == EEXIST;
}

bool RemoveFileIfExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting file: " << path);

    int errorCode = unlink(path);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of file: " << path << " Returned error code: " << errno);
    return errorCode == 0 || errno == ENOENT;
}

bool RemoveDirectoryIfExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting directory: " << path);
    int errorCode = rmdir(path);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of directory: " << path << " Returned error code: " << errno);
    return errorCode == 0 || errno == ENOTDIR || errno == ENOENT;
}

bool RelocateFileOrDirectory(const char* from, const char* to)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Moving file at " << from << " to " << to);

    int errorCode = rename(from, to);

    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG,  "The moving operation of file at " << from << " to " << to << " Returned error code of " << errno);
    return errorCode == 0;
}

std::mutex tempFileMutex;
uint32_t tempFileIndex(0);

Aws::String CreateTempFilePath()
{
    std::lock_guard<std::mutex> tempFileLock(tempFileMutex);

    Aws::StringStream pathStream;
    pathStream << Aws::Platform::GetCacheDirectory();
    pathStream << PATH_DELIM << "temp" << tempFileIndex;
    ++tempFileIndex;

    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "CreateTempFilePath generated: " << pathStream.str());

    return pathStream.str();
}

std::shared_ptr<Directory> OpenDirectory(const Aws::String& path, const Aws::String& relativePath)
{
    assert(directoryEntry.fileType != FileType::File);
    return Aws::MakeShared<AndroidDirectory>(FILE_SYSTEM_UTILS_LOG_TAG, path, relativePath);
}

} // namespace FileSystem
} // namespace Aws

<commit_msg>Fixed android build caused by Directory traversal additions.<commit_after>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
#include <aws/core/platform/FileSystem.h>

#include <aws/core/platform/Android.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/core/utils/StringUtils.h>

#include <unistd.h>
#include <sys/stat.h>
#include <cerrno>
#include <dirent.h>
#include <cassert>

#include <mutex>

namespace Aws
{
namespace FileSystem
{

static const char* FILE_SYSTEM_UTILS_LOG_TAG = "FileSystem";

    class AndroidDirectory : public Directory
    {
    public:
        AndroidDirectory(const Aws::String& path, const Aws::String& relativePath) : Directory(path, relativePath), m_dir(nullptr)
        {
            m_dir = opendir(m_directoryEntry.path.c_str());

            if(m_dir)
            {
                m_directoryEntry.fileType = FileType::Directory;
            }
        }

        ~AndroidDirectory()
        {
            if (m_dir)
            {
                closedir(m_dir);
            }
        }

        DirectoryEntry Next() override
        {
            assert(m_dir);
            DirectoryEntry entry;

            dirent* dirEntry;
            bool invalidEntry(true);

            while(invalidEntry)
            {
                if ((dirEntry = readdir(m_dir)))
                {
                    Aws::String entryName = dirEntry->d_name;
                    if(entryName != ".." && entryName != ".")
                    {
                        entry = ParseFileInfo(dirEntry, true);
                        invalidEntry = false;
                    }
                }
                else
                {
                    break;
                }
            }

            return entry;
        }

    private:
        DirectoryEntry ParseFileInfo(dirent* dirEnt, bool computePath)
        {
            DirectoryEntry entry;

            if(computePath)
            {
                Aws::StringStream ss;
                ss << m_directoryEntry.path << PATH_DELIM << dirEnt->d_name;
                entry.path = ss.str();

                ss.str("");
                if(m_directoryEntry.relativePath.empty())
                {
                    ss << dirEnt->d_name;
                }
                else
                {
                    ss << m_directoryEntry.relativePath << PATH_DELIM << dirEnt->d_name;
                }
                entry.relativePath = ss.str();
            }
            else
            {
                entry.path = m_directoryEntry.path;
                entry.relativePath = m_directoryEntry.relativePath;
            }

            if(dirEnt->d_type == DT_DIR)
            {
                entry.fileType = FileType::Directory;
            }
            else if(dirEnt->d_type == DT_LNK)
            {
                entry.fileType = FileType::Symlink;
            }
            else
            {
                entry.fileType = FileType::File;
                FILE* fp = fopen(entry.path.c_str(), "r");
                if(fp)
                {
                    auto pos = ftell(fp);
                    fseek(fp, 0, SEEK_END);
                    auto end = ftell(fp);
                    fseek(fp, pos, SEEK_SET);
                    entry.fileSize = static_cast<int64_t>(end);
                    fclose(fp);
                }
            }

            return entry;
        }

        DIR* m_dir;
    };

Aws::String GetHomeDirectory()
{
    return Aws::Platform::GetCacheDirectory();
}

bool CreateDirectoryIfNotExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Creating directory " << path);

    int errorCode = mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Creation of directory " << path << " returned code: " << errno);
    return errorCode == 0 || errno == EEXIST;
}

bool RemoveFileIfExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting file: " << path);

    int errorCode = unlink(path);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of file: " << path << " Returned error code: " << errno);
    return errorCode == 0 || errno == ENOENT;
}

bool RemoveDirectoryIfExists(const char* path)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Deleting directory: " << path);
    int errorCode = rmdir(path);
    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "Deletion of directory: " << path << " Returned error code: " << errno);
    return errorCode == 0 || errno == ENOTDIR || errno == ENOENT;
}

bool RelocateFileOrDirectory(const char* from, const char* to)
{
    AWS_LOGSTREAM_INFO(FILE_SYSTEM_UTILS_LOG_TAG, "Moving file at " << from << " to " << to);

    int errorCode = rename(from, to);

    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG,  "The moving operation of file at " << from << " to " << to << " Returned error code of " << errno);
    return errorCode == 0;
}

std::mutex tempFileMutex;
uint32_t tempFileIndex(0);

Aws::String CreateTempFilePath()
{
    std::lock_guard<std::mutex> tempFileLock(tempFileMutex);

    Aws::StringStream pathStream;
    pathStream << Aws::Platform::GetCacheDirectory();
    pathStream << PATH_DELIM << "temp" << tempFileIndex;
    ++tempFileIndex;

    AWS_LOGSTREAM_DEBUG(FILE_SYSTEM_UTILS_LOG_TAG, "CreateTempFilePath generated: " << pathStream.str());

    return pathStream.str();
}

std::shared_ptr<Directory> OpenDirectory(const Aws::String& path, const Aws::String& relativePath)
{
    return Aws::MakeShared<AndroidDirectory>(FILE_SYSTEM_UTILS_LOG_TAG, path, relativePath);
}

} // namespace FileSystem
} // namespace Aws

<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2015 Ericsson Telecom AB
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
///////////////////////////////////////////////////////////////////////////////
#ifndef EVENT_HANDLER_HH
#define EVENT_HANDLER_HH

#include "Types.h"

/**
* The definitions in this header file are needed for TITAN.
* These classes should not be used in user code.
* These classes are used as base classes for class PORT.
*/

class Fd_Event_Handler {
  virtual void Handle_Fd_Event(int fd,
    boolean is_readable, boolean is_writeable, boolean is_error) = 0;

public:
  Fd_Event_Handler() {}
  virtual ~Fd_Event_Handler() {}
  virtual void log() const;
private:
  Fd_Event_Handler(const Fd_Event_Handler&);
  const Fd_Event_Handler & operator= (const Fd_Event_Handler &);
  friend class Fd_And_Timeout_User;
  friend class Handler_List;
};

class Handler_List;
class FdSets;

class Fd_And_Timeout_Event_Handler : public Fd_Event_Handler {
  virtual void Handle_Fd_Event(int fd,
    boolean is_readable, boolean is_writeable, boolean is_error);
  virtual void Handle_Timeout(double time_since_last_call);
  /// Copy constructor disabled
  Fd_And_Timeout_Event_Handler(const Fd_And_Timeout_Event_Handler&);
  /// Assignment disabled
  Fd_And_Timeout_Event_Handler& operator=(const Fd_And_Timeout_Event_Handler&);
public:
  virtual void Event_Handler(const fd_set *read_fds, const fd_set *write_fds,
    const fd_set *error_fds, double time_since_last_call);

public:
  inline Fd_And_Timeout_Event_Handler() :
  callInterval(0.0), last_called(0.0), list(0), prev(0), next(0),
  fdSets(0), fdCount(0),
  isTimeout(TRUE), callAnyway(TRUE), isPeriodic(TRUE),
  hasEvent(FALSE)
  {}
  virtual ~Fd_And_Timeout_Event_Handler();
  virtual void log() const;

  friend class Fd_And_Timeout_User;
  friend class Handler_List;
private:
  double callInterval, last_called;
  Handler_List * list;
  Fd_And_Timeout_Event_Handler * prev, * next;
  FdSets * fdSets;
  int fdCount;
  boolean isTimeout, callAnyway, isPeriodic;
  boolean hasEvent;
protected:
  boolean getIsOldApi() { return fdSets != 0; }
};

#endif
<commit_msg>Added file descriptor set library (Cygwin bug)<commit_after>///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2015 Ericsson Telecom AB
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
///////////////////////////////////////////////////////////////////////////////
#ifndef EVENT_HANDLER_HH
#define EVENT_HANDLER_HH

#include "Types.h"
#include <sys/select.h>

/**
* The definitions in this header file are needed for TITAN.
* These classes should not be used in user code.
* These classes are used as base classes for class PORT.
*/

class Fd_Event_Handler {
  virtual void Handle_Fd_Event(int fd,
    boolean is_readable, boolean is_writeable, boolean is_error) = 0;

public:
  Fd_Event_Handler() {}
  virtual ~Fd_Event_Handler() {}
  virtual void log() const;
private:
  Fd_Event_Handler(const Fd_Event_Handler&);
  const Fd_Event_Handler & operator= (const Fd_Event_Handler &);
  friend class Fd_And_Timeout_User;
  friend class Handler_List;
};

class Handler_List;
class FdSets;

class Fd_And_Timeout_Event_Handler : public Fd_Event_Handler {
  virtual void Handle_Fd_Event(int fd,
    boolean is_readable, boolean is_writeable, boolean is_error);
  virtual void Handle_Timeout(double time_since_last_call);
  /// Copy constructor disabled
  Fd_And_Timeout_Event_Handler(const Fd_And_Timeout_Event_Handler&);
  /// Assignment disabled
  Fd_And_Timeout_Event_Handler& operator=(const Fd_And_Timeout_Event_Handler&);
public:
  virtual void Event_Handler(const fd_set *read_fds, const fd_set *write_fds,
    const fd_set *error_fds, double time_since_last_call);

public:
  inline Fd_And_Timeout_Event_Handler() :
  callInterval(0.0), last_called(0.0), list(0), prev(0), next(0),
  fdSets(0), fdCount(0),
  isTimeout(TRUE), callAnyway(TRUE), isPeriodic(TRUE),
  hasEvent(FALSE)
  {}
  virtual ~Fd_And_Timeout_Event_Handler();
  virtual void log() const;

  friend class Fd_And_Timeout_User;
  friend class Handler_List;
private:
  double callInterval, last_called;
  Handler_List * list;
  Fd_And_Timeout_Event_Handler * prev, * next;
  FdSets * fdSets;
  int fdCount;
  boolean isTimeout, callAnyway, isPeriodic;
  boolean hasEvent;
protected:
  boolean getIsOldApi() { return fdSets != 0; }
};

#endif
<|endoftext|>


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

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        int len = num.size();
        int left, right, sum;
        sort(num.begin(), num.end());
        vector<vector<int>> res;
        for (int i = 0; i < len - 3; ++i) {
            if (i && num[i] == num[i - 1]) {
                continue;
            }
            for (int j = i + 1; j < len - 2; ++j) {
                if (j != i + 1 && num[j] == num[j - 1]) {
                    continue;
                }
                sum = target - num[i] - num[j];
                left = j + 1, right = len - 1;
                while (left < right) {
                    if (num[left] + num[right] == sum) {
                        res.emplace_back(move(vector<int>{num[i], num[j], num[left], num[right]}));
                        ++left, --right;
                        while (left < right && num[left] == num[left - 1]) {
                            ++left;
                        }
                        while (left < right && num[right] == num[right + 1]) {
                            --right;
                        }
                    } else {
                        if (num[left] + num[right] > sum) {
                            --right;
                        } else {
                            ++left;
                        }
                    }
                }
            }
        }
        return res;
    }
};

// Time:  O(n^4)
// Space: O(n^2)
class Solution2 {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int>> ans;
        if (num.size() < 4)  {
            return ans;
        }
        sort(num.begin(), num.end());
        unordered_multimap<int, pair<int, int>> cache;

        for (int i = 0; i + 1 < num.size(); ++i) {
            for (int j = i + 1; j < num.size(); ++j) {
                cache.emplace(num[i] + num[j], make_pair(i, j));
            }
        }

        for (auto i = cache.begin(); i != cache.end(); ++i) {
            int x = target - i->first;
            auto range = cache.equal_range(x);
            for (auto j = range.first; j != range.second; ++j) {
                auto a = i->second.first;
                auto b = i->second.second;
                auto c = j->second.first;
                auto d = j->second.second;
                if (b < c) {
                    ans.emplace_back(move(vector<int>{num[a], num[b], num[c], num[d]}));
                }
            }
        }
        sort(ans.begin(), ans.end());
        ans.erase(unique(ans.begin(), ans.end()), ans.end());
        return ans;
    }
};
<commit_msg>Update 4sum.cpp<commit_after>// Time:  O(n^3)
// Space: O(1)

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        int len = num.size();
        int left, right, sum;
        sort(num.begin(), num.end());
        vector<vector<int>> res;
        for (int i = 0; i < len - 3; ++i) {
            if (i && num[i] == num[i - 1]) {
                continue;
            }
            for (int j = i + 1; j < len - 2; ++j) {
                if (j != i + 1 && num[j] == num[j - 1]) {
                    continue;
                }
                sum = target - num[i] - num[j];
                left = j + 1, right = len - 1;
                while (left < right) {
                    if (num[left] + num[right] == sum) {
                        res.emplace_back(move(vector<int>{num[i], num[j], num[left], num[right]}));
                        ++left, --right;
                        while (left < right && num[left] == num[left - 1]) {
                            ++left;
                        }
                        while (left < right && num[right] == num[right + 1]) {
                            --right;
                        }
                    } else {
                        if (num[left] + num[right] > sum) {
                            --right;
                        } else {
                            ++left;
                        }
                    }
                }
            }
        }
        return res;
    }
};

// Time:  O(n^4)
// Space: O(n^2)
class Solution2 {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        vector<vector<int>> ans;
        if (num.size() < 4)  {
            return ans;
        }
        sort(num.begin(), num.end());
        unordered_multimap<int, pair<int, int>> cache;

        for (int i = 0; i < num.size(); ++i) {
            for (int j = i + 1; j < num.size(); ++j) {
                cache.emplace(num[i] + num[j], make_pair(i, j));
            }
        }

        for (auto i = cache.begin(); i != cache.end(); ++i) {
            auto a = i->second.first;
            auto b = i->second.second;
            int x = target - i->first;
            auto range = cache.equal_range(x);
            for (auto j = range.first; j != range.second; ++j) {
                auto c = j->second.first;
                auto d = j->second.second;
                if (b < c) {
                    ans.emplace_back(move(vector<int>{num[a], num[b], num[c], num[d]}));
                }
            }
        }
        sort(ans.begin(), ans.end());
        ans.erase(unique(ans.begin(), ans.end()), ans.end());
        return ans;
    }
};
<|endoftext|>


<commit_before>#include "caffe2/core/net.h"
#include "caffe2/core/operator.h"
#include "caffe2/proto/caffe2.pb.h"

namespace caffe2 {

NetBase* CreateNet(const NetDef& net_def, Workspace* ws) {
  if (!net_def.has_net_type() || net_def.net_type() == "simple") {
    VLOG(1) << "Creating simple net.";
    return new SimpleNet(net_def, ws);
  } else if (net_def.net_type() == "parallel") {
    VLOG(1) << "Creating parallel net.";
    return new ParallelNet(net_def, ws);
  } else {
    LOG(ERROR) << "Unknown net type: " << net_def.net_type();
    return nullptr;
  }
  // Just to suppress compiler warning
  return nullptr;
}

SimpleNet::SimpleNet(const NetDef& net_def, Workspace* ws)
    : NetBase(net_def, ws) {
  bool net_def_has_device_option = net_def.has_device_option();
  // Initialize the operators
  for (const OperatorDef& operator_def : net_def.op()) {
    VLOG(1) << "Creating operator " << operator_def.name()
            << ":" << operator_def.type();
    if (!operator_def.has_device_option() && net_def_has_device_option) {
      // In the case that the operator def does not specify a device option but
      // the net def has a default option, we copy the device option over to the
      // operator def.
      OperatorDef temp_def(operator_def);
      temp_def.mutable_device_option()->CopyFrom(net_def.device_option());
      operators_.emplace_back(CreateOperator(temp_def, ws));
    } else {
      operators_.emplace_back(CreateOperator(operator_def, ws));
    }
  }
}

bool SimpleNet::Verify() {
  for (auto& op : operators_) {
    VLOG(1) << "Verifying operator " << op->def().name()
            << "(" << op->def().type() << ").";
    if (op.get() == nullptr || !op->Verify()) {
      return false;
    }
  }
  return true;
}

bool SimpleNet::Run() {
  VLOG(1) << "Running net.";
  for (const auto& op : operators_) {
    VLOG(1) << "Running operator " << op->def().name()
            << "(" << op->def().type() << ").";
    // TODO(Yangqing): convert this sequential run to event-based.
    if (!op->Run()) return false;
  }
  return true;
}

ParallelNet::ParallelNet(const NetDef& net_def, Workspace* ws)
    : NetBase(net_def, ws), operator_nodes_(net_def.op_size()) {
  // Blob creator allows us to track which operator created which blob.
  std::map<string, int> blob_creator;
  bool net_def_has_device_option = net_def.has_device_option();
  // Initialize the operators
  for (int idx = 0; idx < net_def.op_size(); ++idx) {
    const OperatorDef& op_def = net_def.op(idx);
    VLOG(1) << "Creating operator #" << idx << ": "
            << op_def.name() << ":" << op_def.type();
    if (!op_def.has_device_option() && net_def_has_device_option) {
      OperatorDef temp_def(op_def);
      temp_def.mutable_device_option()->CopyFrom(net_def.device_option());
      operator_nodes_[idx].operator_.reset(CreateOperator(temp_def, ws));
    } else {
      operator_nodes_[idx].operator_.reset(CreateOperator(op_def, ws));
    }
    // Check the inputs, and set up parents if necessary.
    for (const string& input : op_def.input()) {
      if (blob_creator.count(input) == 0) {
        VLOG(1) << "Input " << input << " not produced by this net. "
                << "Assuming it is pre-existing.";
      } else {
        int parent = blob_creator[input];
        VLOG(1) << "op dependency: " << parent << "->" << idx;
        operator_nodes_[idx].parents_.push_back(parent);
        operator_nodes_[parent].children_.push_back(idx);
      }
    }
    for (const string& output : op_def.output()) {
      if (blob_creator.count(output) != 0) {
        LOG(WARNING) << "Output " << output << " produced again. "
                     << "Such operation is not strictly tested. "
                     << "Use at your own risk.";
      }
      blob_creator[output] = idx;
    }
  }
  // Figure out the initial frontier - this is the one we will feed into the job
  // queue to start a run.
  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].parents_.size() == 0) {
      initial_frontier_.push_back(idx);
    }
  }
  // Finally, start the workers.
  int num_workers = net_def.has_num_workers() ? net_def.num_workers() : 1;
  CHECK_GT(num_workers, 0) << "Must have a nonnegative number of workers";
  if (num_workers == 1) {
    LOG(WARNING) << "Number of workers is 1: this means that all operators "
                 << "will be executed sequentially. Did you forget to set "
                 << "num_workers in the NetDef?";
  }
  for (int i = 0; i < num_workers; ++i) {
    VLOG(1) << "Start worker #" << i;
    workers_.push_back(std::thread(&ParallelNet::WorkerFunction, this));
  }
}

ParallelNet::~ParallelNet() {
  // Safely join all the workers before exiting.
  job_queue_.NoMoreJobs();
  VLOG(1) << "Joining workers.";
  for (auto& worker : workers_) {
    worker.join();
  }
}

bool ParallelNet::Verify() {
  for (auto& op_node : operator_nodes_) {
    auto& op = op_node.operator_;
    VLOG(1) << "Verifying operator " << op->def().name()
            << "(" << op->def().type() << ").";
    if (op.get() == nullptr || !op->Verify()) {
      return false;
    }
  }
  return true;
}

bool ParallelNet::Run() {
  VLOG(1) << "Running parallel net.";
  // First, set up job queue.
  remaining_ops_ = operator_nodes_.size();
  success_ = true;
  // TODO(jiayq): Start all worker threads.
  // Initialize the runtime parent count.
  for (auto& node : operator_nodes_) {
    node.runtime_parent_count_ = node.parents_.size();
  }
  // Kickstart the job queue.
  for (auto& value : initial_frontier_) {
    job_queue_.Push(value);
  }
  std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
  while (remaining_ops_ > 0) {
    VLOG(2) << "Remaining ops to run: " << remaining_ops_;
    cv_.wait(mutex_lock);
  }
  VLOG(2) << "All ops finished running.";
  // If the above while loop finished, we know that the current run finished.
  return success_;
}

void ParallelNet::WorkerFunction() {
  // WorkerFunctions() is an infinite loop until there are no more jobs to run.
  while (true) {
    int idx;
    // If there is no more jobs - meaning that the ParallelNet is destructing -
    // we will exit safely.
    if (!job_queue_.Pop(&idx)) {
      return;
    }
    VLOG(1) << "Running operator #" << idx << " "
            << operator_nodes_[idx].operator_->def().name()
            << "(" << operator_nodes_[idx].operator_->def().type() << ").";
    bool this_success = operator_nodes_[idx].operator_->Run();
    for (int child : operator_nodes_[idx].children_) {
      int count = --operator_nodes_[child].runtime_parent_count_;
      // The count should never be smaller than zero.
      DCHECK_GE(count, 0)
          << "Found runtime parent count smaller than zero for "
          << "operator node "
          << operator_nodes_[child].operator_->def().name()
          << "(" << operator_nodes_[child].operator_->def().type() << ").";
      if (count == 0) {
        VLOG(2) << "Pushing operator #" << child << " to queue.";
        job_queue_.Push(child);
      }
    }
    // Notify that the processed op is incremented by one.
    std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
    --remaining_ops_;
    success_ &= this_success;
    DCHECK_GE(remaining_ops_, 0);
    cv_.notify_one();
    VLOG(2) << "Finished executing operator #" << idx;
  }
}

}  // namespace caffe2
<commit_msg>Add an execution chain option to force operator orders.<commit_after>#include "caffe2/core/net.h"
#include "caffe2/core/operator.h"
#include "caffe2/proto/caffe2.pb.h"

namespace caffe2 {

NetBase* CreateNet(const NetDef& net_def, Workspace* ws) {
  if (!net_def.has_net_type() || net_def.net_type() == "simple") {
    VLOG(1) << "Creating simple net.";
    return new SimpleNet(net_def, ws);
  } else if (net_def.net_type() == "parallel") {
    VLOG(1) << "Creating parallel net.";
    return new ParallelNet(net_def, ws);
  } else {
    LOG(ERROR) << "Unknown net type: " << net_def.net_type();
    return nullptr;
  }
  // Just to suppress compiler warning
  return nullptr;
}

SimpleNet::SimpleNet(const NetDef& net_def, Workspace* ws)
    : NetBase(net_def, ws) {
  bool net_def_has_device_option = net_def.has_device_option();
  // Initialize the operators
  for (const OperatorDef& operator_def : net_def.op()) {
    VLOG(1) << "Creating operator " << operator_def.name()
            << ":" << operator_def.type();
    if (!operator_def.has_device_option() && net_def_has_device_option) {
      // In the case that the operator def does not specify a device option but
      // the net def has a default option, we copy the device option over to the
      // operator def.
      OperatorDef temp_def(operator_def);
      temp_def.mutable_device_option()->CopyFrom(net_def.device_option());
      operators_.emplace_back(CreateOperator(temp_def, ws));
    } else {
      operators_.emplace_back(CreateOperator(operator_def, ws));
    }
  }
}

bool SimpleNet::Verify() {
  for (auto& op : operators_) {
    VLOG(1) << "Verifying operator " << op->def().name()
            << "(" << op->def().type() << ").";
    if (op.get() == nullptr || !op->Verify()) {
      return false;
    }
  }
  return true;
}

bool SimpleNet::Run() {
  VLOG(1) << "Running net.";
  for (const auto& op : operators_) {
    VLOG(1) << "Running operator " << op->def().name()
            << "(" << op->def().type() << ").";
    // TODO(Yangqing): convert this sequential run to event-based.
    if (!op->Run()) return false;
  }
  return true;
}

ParallelNet::ParallelNet(const NetDef& net_def, Workspace* ws)
    : NetBase(net_def, ws), operator_nodes_(net_def.op_size()) {
  // Blob creator allows us to track which operator created which blob.
  std::map<string, int> blob_creator;
  std::map<string, int> execution_chains;
  bool net_def_has_device_option = net_def.has_device_option();
  // Initialize the operators
  for (int idx = 0; idx < net_def.op_size(); ++idx) {
    const OperatorDef& op_def = net_def.op(idx);
    VLOG(1) << "Creating operator #" << idx << ": "
            << op_def.name() << ":" << op_def.type();
    if (!op_def.has_device_option() && net_def_has_device_option) {
      OperatorDef temp_def(op_def);
      temp_def.mutable_device_option()->CopyFrom(net_def.device_option());
      operator_nodes_[idx].operator_.reset(CreateOperator(temp_def, ws));
    } else {
      operator_nodes_[idx].operator_.reset(CreateOperator(op_def, ws));
    }
    // Check the inputs, and set up parents if necessary.
    for (const string& input : op_def.input()) {
      if (blob_creator.count(input) == 0) {
        VLOG(1) << "Input " << input << " not produced by this net. "
                << "Assuming it is pre-existing.";
      } else {
        int parent = blob_creator[input];
        VLOG(1) << "op dependency: " << parent << "->" << idx;
        operator_nodes_[idx].parents_.push_back(parent);
        operator_nodes_[parent].children_.push_back(idx);
      }
    }
    for (const string& output : op_def.output()) {
      if (blob_creator.count(output) != 0) {
        LOG(WARNING) << "Output " << output << " produced again. "
                     << "Such operation is not strictly tested. "
                     << "Use at your own risk.";
      }
      blob_creator[output] = idx;
    }

    for (const auto& arg : op_def.arg()) {
      if (arg.name() == "execution_chain") {
        for (const string& name : arg.strings()) {
          if (execution_chains.count(name) == 0) {
            // New execution chain. Do nothing but add it.
            execution_chains[name] = idx;
          } else {
            int parent = execution_chains[name];
            VLOG(1) << "op dependency due to execution chain " << name
                    << ": " << parent << "->" << idx;
            operator_nodes_[idx].parents_.push_back(parent);
            operator_nodes_[parent].children_.push_back(idx);
            // update the tail of the current execution chain.
            execution_chains[name] = idx;
          }
        }
      }
    }
  }
  // Figure out the initial frontier - this is the one we will feed into the job
  // queue to start a run.
  for (int idx = 0; idx < operator_nodes_.size(); ++idx) {
    if (operator_nodes_[idx].parents_.size() == 0) {
      initial_frontier_.push_back(idx);
    }
  }
  // Finally, start the workers.
  int num_workers = net_def.has_num_workers() ? net_def.num_workers() : 1;
  CHECK_GT(num_workers, 0) << "Must have a nonnegative number of workers";
  if (num_workers == 1) {
    LOG(WARNING) << "Number of workers is 1: this means that all operators "
                 << "will be executed sequentially. Did you forget to set "
                 << "num_workers in the NetDef?";
  }
  for (int i = 0; i < num_workers; ++i) {
    VLOG(1) << "Start worker #" << i;
    workers_.push_back(std::thread(&ParallelNet::WorkerFunction, this));
  }
}

ParallelNet::~ParallelNet() {
  // Safely join all the workers before exiting.
  job_queue_.NoMoreJobs();
  VLOG(1) << "Joining workers.";
  for (auto& worker : workers_) {
    worker.join();
  }
}

bool ParallelNet::Verify() {
  for (auto& op_node : operator_nodes_) {
    auto& op = op_node.operator_;
    VLOG(1) << "Verifying operator " << op->def().name()
            << "(" << op->def().type() << ").";
    if (op.get() == nullptr || !op->Verify()) {
      return false;
    }
  }
  return true;
}

bool ParallelNet::Run() {
  VLOG(1) << "Running parallel net.";
  // First, set up job queue.
  remaining_ops_ = operator_nodes_.size();
  success_ = true;
  // TODO(jiayq): Start all worker threads.
  // Initialize the runtime parent count.
  for (auto& node : operator_nodes_) {
    node.runtime_parent_count_ = node.parents_.size();
  }
  // Kickstart the job queue.
  for (auto& value : initial_frontier_) {
    job_queue_.Push(value);
  }
  std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
  while (remaining_ops_ > 0) {
    VLOG(2) << "Remaining ops to run: " << remaining_ops_;
    cv_.wait(mutex_lock);
  }
  VLOG(2) << "All ops finished running.";
  // If the above while loop finished, we know that the current run finished.
  return success_;
}

void ParallelNet::WorkerFunction() {
  // WorkerFunctions() is an infinite loop until there are no more jobs to run.
  while (true) {
    int idx;
    // If there is no more jobs - meaning that the ParallelNet is destructing -
    // we will exit safely.
    if (!job_queue_.Pop(&idx)) {
      return;
    }
    VLOG(1) << "Running operator #" << idx << " "
            << operator_nodes_[idx].operator_->def().name()
            << "(" << operator_nodes_[idx].operator_->def().type() << ").";
    bool this_success = operator_nodes_[idx].operator_->Run();
    for (int child : operator_nodes_[idx].children_) {
      int count = --operator_nodes_[child].runtime_parent_count_;
      // The count should never be smaller than zero.
      DCHECK_GE(count, 0)
          << "Found runtime parent count smaller than zero for "
          << "operator node "
          << operator_nodes_[child].operator_->def().name()
          << "(" << operator_nodes_[child].operator_->def().type() << ").";
      if (count == 0) {
        VLOG(2) << "Pushing operator #" << child << " to queue.";
        job_queue_.Push(child);
      }
    }
    // Notify that the processed op is incremented by one.
    std::unique_lock<std::mutex> mutex_lock(remaining_ops_mutex_);
    --remaining_ops_;
    success_ &= this_success;
    DCHECK_GE(remaining_ops_, 0);
    cv_.notify_one();
    VLOG(2) << "Finished executing operator #" << idx;
  }
}

}  // namespace caffe2
<|endoftext|>


<commit_before>#include "opencv2/opencv.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
namespace ptime = boost::posix_time;

#include <boost/format.hpp>
typedef boost::format fmt;

#include "Pipeline.hpp"
#include "Associativity.hpp"
#include "Viewer.hpp"
#include "util.hpp"

float _intrinsic_array[9]= {524,0,316.7,0,524,238.5,0,0,1};
float _distcoeff_array[4] = {0.2402,-0.6861,-0.0015,0.0003};

Pipeline::Pipeline(std::string _folder_path)
:
	cameraMatrix(cv::Mat(3, 3, CV_32F, _intrinsic_array)),
	distCoeffs(cv::Mat(1, 4, CV_32F, _distcoeff_array))
{
	folder_path = _folder_path;
}

void Pipeline::run()
{
	Logger _log("Pipeline");

	/**
	 * Stage 0: Load images from file
	 */
	Images images;
	load_images(folder_path, images);

	/**
	 * Stage 1: Detect features in loaded images
	 */
	CamFrames cam_Frames;
	DescriptorsVec descriptors_vec;
	extract_features(images, cam_Frames, descriptors_vec);

	// Free Image.gray
	for (int i = 0; i < images.size(); i++)
		const_cast<cv::Mat&>(images[i].gray).release();

	/**
	 * Stage 2: Calculate descriptors and find image pairs through matching
	 */
	ImagePairs image_pairs;
	find_matching_pairs(images, cam_Frames, descriptors_vec, image_pairs);

	// Free some memory
	DescriptorsVec().swap(descriptors_vec);

	/**
	 * State 3: Compute pairwise R and t
	 */
	register_camera(image_pairs, cam_Frames);

	/**
	 * Stage 4: Construct associativity matrix and spanning tree
	 */
	Associativity assocMat(cam_Frames.size());
	for (int p = 0; p < image_pairs.size(); p++)
	{
		ImagePair* pair = &image_pairs[p];
		int i = pair->pair_index.first,
		    j = pair->pair_index.second;

		if (pair -> R.empty()) continue;

		assocMat(i, j) = pair;
		assocMat(j, i) = pair;

		assert(assocMat(i, j) == assocMat(j, i));
		assert(assocMat(i, j)->pair_index.first  == i &&
		       assocMat(i, j)->pair_index.second == j);
	}

	Associativity tree;
	const int camera_num = build_spanning_tree(image_pairs, assocMat, tree);

	/**
	 * Stage 5: Compute global Rs and ts
	 */
	CameraPoses gCameraPoses;
	glo_cam_poses(images, gCameraPoses, image_pairs, tree);

	/**
	 * Stage 6: Find and cluster depth points from local camera frame to global camera frame
	 */
	PointClusters pointClusters;
	PointMap pointMap;
	find_clusters(assocMat, gCameraPoses, cam_Frames, pointClusters, pointMap);

	// Free some memory
	ImagePairs().swap(image_pairs);

	/**
	 * Stage 7: get center of mass from clusters
	 */
	PointCloud pointCloud(pointClusters.size());
	find_CoM(pointClusters, pointCloud);

	// Free pointClusters
	for (int i = 0; i < pointClusters.size(); i++)
		PointCluster().swap(pointClusters[i]);
	PointClusters().swap(pointClusters);

	// Save cloud before BA
	Viewer viewer;
	auto cloud  = viewer.createPointCloud(images, gCameraPoses, cameraMatrix);
	int  n      = cloud->points.size();
	auto time   = ptime::second_clock::local_time();
	auto tstamp = ptime::to_iso_string(time);
	auto fname  = (fmt("output_%s_%d_noBA.pcd") % tstamp % n).str().c_str();
	viewer.saveCloud(cloud, fname);

	/**
	 * State 8: Bundle Adjustment
	 */
	bundle_adjustment(pointMap, cam_Frames, gCameraPoses, pointCloud);

	// Free some memory
	PointMap().swap(pointMap);
	CamFrames().swap(cam_Frames);
	PointCloud().swap(pointCloud);

	_log.tok();

	/**
	 * Show calculated point cloud
	 */
	cloud = viewer.createPointCloud(images, gCameraPoses, cameraMatrix);
	n     = cloud->points.size();
	fname = (fmt("output_%s_%d_BA.pcd") % tstamp % n).str().c_str();

	// Free some memory
	Images().swap(images);
	CameraPoses().swap(gCameraPoses);

	viewer.saveCloud(cloud, fname);
	viewer.showCloudPoints(cloud);
}
<commit_msg>pipeline viewer change<commit_after>#include "opencv2/opencv.hpp"

#include <boost/date_time/posix_time/posix_time.hpp>
namespace ptime = boost::posix_time;

#include <boost/format.hpp>
typedef boost::format fmt;

#include "Pipeline.hpp"
#include "Associativity.hpp"
#include "Viewer.hpp"
#include "util.hpp"

float _intrinsic_array[9]= {524,0,316.7,0,524,238.5,0,0,1};
float _distcoeff_array[4] = {0.2402,-0.6861,-0.0015,0.0003};

Pipeline::Pipeline(std::string _folder_path)
:
	cameraMatrix(cv::Mat(3, 3, CV_32F, _intrinsic_array)),
	distCoeffs(cv::Mat(1, 4, CV_32F, _distcoeff_array))
{
	folder_path = _folder_path;
}

void Pipeline::run()
{
	Logger _log("Pipeline");

	/**
	 * Stage 0: Load images from file
	 */
	Images images;
	load_images(folder_path, images);

	/**
	 * Stage 1: Detect features in loaded images
	 */
	CamFrames cam_Frames;
	DescriptorsVec descriptors_vec;
	extract_features(images, cam_Frames, descriptors_vec);

	// Free Image.gray
	for (int i = 0; i < images.size(); i++)
		const_cast<cv::Mat&>(images[i].gray).release();

	/**
	 * Stage 2: Calculate descriptors and find image pairs through matching
	 */
	ImagePairs image_pairs;
	find_matching_pairs(images, cam_Frames, descriptors_vec, image_pairs);

	// Free some memory
	DescriptorsVec().swap(descriptors_vec);

	/**
	 * State 3: Compute pairwise R and t
	 */
	register_camera(image_pairs, cam_Frames);

	/**
	 * Stage 4: Construct associativity matrix and spanning tree
	 */
	Associativity assocMat(cam_Frames.size());
	for (int p = 0; p < image_pairs.size(); p++)
	{
		ImagePair* pair = &image_pairs[p];
		int i = pair->pair_index.first,
		    j = pair->pair_index.second;

		if (pair -> R.empty()) continue;

		assocMat(i, j) = pair;
		assocMat(j, i) = pair;

		assert(assocMat(i, j) == assocMat(j, i));
		assert(assocMat(i, j)->pair_index.first  == i &&
		       assocMat(i, j)->pair_index.second == j);
	}

	Associativity tree;
	const int camera_num = build_spanning_tree(image_pairs, assocMat, tree);

	/**
	 * Stage 5: Compute global Rs and ts
	 */
	CameraPoses gCameraPoses;
	glo_cam_poses(images, gCameraPoses, image_pairs, tree);

	/**
	 * Stage 6: Find and cluster depth points from local camera frame to global camera frame
	 */
	PointClusters pointClusters;
	PointMap pointMap;
	find_clusters(assocMat, gCameraPoses, cam_Frames, pointClusters, pointMap);

	// Free some memory
	ImagePairs().swap(image_pairs);

	/**
	 * Stage 7: get center of mass from clusters
	 */
	PointCloud pointCloud(pointClusters.size());
	find_CoM(pointClusters, pointCloud);

	// Free pointClusters
	for (int i = 0; i < pointClusters.size(); i++)
		PointCluster().swap(pointClusters[i]);
	PointClusters().swap(pointClusters);

	// Save cloud before BA
	Viewer viewer;
	auto cloud  = viewer.createPointCloud(images, gCameraPoses, cameraMatrix);
	int  n      = cloud->points.size();
	auto time   = ptime::second_clock::local_time();
	auto tstamp = ptime::to_iso_string(time);
	auto fname  = (fmt("output_%s_%d_noBA.pcd") % tstamp % n).str().c_str();
	// viewer.saveCloud(cloud, fname);
	viewer.showCloudPoints(cloud,false);

	/**
	 * State 8: Bundle Adjustment
	 */
	bundle_adjustment(pointMap, cam_Frames, gCameraPoses, pointCloud);

	// Free some memory
	PointMap().swap(pointMap);
	CamFrames().swap(cam_Frames);
	PointCloud().swap(pointCloud);

	_log.tok();

	/**
	 * Show calculated point cloud
	 */
	Viewer viewer_ba;
	cloud = viewer_ba.createPointCloud(images, gCameraPoses, cameraMatrix);
	n     = cloud->points.size();
	fname = (fmt("output_%s_%d_BA.pcd") % tstamp % n).str().c_str();

	// Free some memory
	Images().swap(images);
	CameraPoses().swap(gCameraPoses);
	// viewer.saveCloud(cloud, fname);
	viewer_ba.showCloudPoints(cloud);
}
<|endoftext|>


<commit_before><commit_msg>Repeat after me: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9 :)<commit_after><|endoftext|>


<commit_before>

#include "Property.h"
#include "base_types.h"
#include "tis_logging.h"

#include <cstring>
#include <algorithm>

using namespace tis_imaging;

Property::Property ()
    : value_type(UNDEFINED), prop(), ref_prop()
{}

Property::Property (const camera_property& _property, const VALUE_TYPE& t)
    : prop(_property), ref_prop(_property), value_type(t)
{}

Property::Property (const camera_property& _property,
                    const std::map<std::string, int>& _map,
                    const VALUE_TYPE& t)
    : prop(_property), ref_prop(_property), string_map(_map), value_type(t)
{}

Property::~Property ()
{}

void Property::reset ()
{
    tis_log(TIS_LOG_INFO, "Resetting property to initial values.");
    prop = ref_prop;

    notifyImpl();
}

std::string Property::getName () const
{
    return prop.name;
}

PROPERTY_TYPE Property::getType () const
{
    return prop.type;
}

bool Property::isReadOnly () const
{
    return (prop.flags & (1 << PROPERTY_FLAG_READ_ONLY));
}

bool Property::isWriteOnly () const
{
    return (prop.flags & ((long)1 << PROPERTY_FLAG_WRITE_ONLY));
}

bool Property::isDisabled () const
{
    return (prop.flags & (1 << PROPERTY_FLAG_DISABLED));
}

uint32_t Property::getFlags () const
{
    return prop.flags;
}

struct camera_property Property::getStruct () const
{
    return prop;
}

bool Property::setStruct (const struct camera_property& p)
{
    switch (prop.type)
    {
        case PROPERTY_TYPE_STRING:
            std::strncpy(prop.value.s.value, p.value.s.value, sizeof(prop.value.s.value));
        case PROPERTY_TYPE_STRING_TABLE:
            prop.value.i.value = p.value.i.value;
            break;
        case PROPERTY_TYPE_INTEGER:
            prop.value.i.value = p.value.i.value;
            break;
        case PROPERTY_TYPE_DOUBLE:
            prop.value.d.value = p.value.d.value;
            break;
        case PROPERTY_TYPE_BUTTON:
            // do nothing
            break;
        case PROPERTY_TYPE_BOOLEAN:
            prop.value.b.value = p.value.b.value;
            break;
        case PROPERTY_TYPE_UNKNOWN:
        default:
            return false;
    }
    return true;
}

Property::VALUE_TYPE Property::getValueType () const
{
    return value_type;
}

bool Property::setReadOnly (const bool only_read)
{
    if (only_read)
    {
        prop.flags |= 1 << PROPERTY_FLAG_READ_ONLY;
    }
    else
    {
        prop.flags &= ~(1 << PROPERTY_FLAG_READ_ONLY);
    }

    return true;
}

bool Property::setWriteOnly (const bool only_write)
{
    long val = 1;
    if (only_write)
    {
        prop.flags |= val << PROPERTY_FLAG_WRITE_ONLY;
    }
    else
    {
        prop.flags &= ~(val << PROPERTY_FLAG_WRITE_ONLY);
    }

    return true;
}

bool Property::setInactive (const bool is_disabled)
{
    if (is_disabled)
    {
        prop.flags |= 1 << PROPERTY_FLAG_INACTIVE;
    }
    else
    {
        prop.flags &= ~(1 << PROPERTY_FLAG_INACTIVE);
    }

    return true;
}

bool Property::isAvailable (const Property&)
{
    // TODO:
    return false;
}

bool Property::setProperty (const Property&)
{
    if (impl.expired())
    {
        return false;
    }
    notifyImpl();

    return true;
}

bool Property::getProperty (Property&)
{
    // TODO:
    return true;
}

void Property::notifyImpl ()
{
    if (impl.expired())
    {
        tis_log(TIS_LOG_ERROR, "PropertyImpl expired. Property %s is corrupted.", this->getName().c_str());
    }

    auto ptr(impl.lock());

    // tis_log(TIS_LOG_DEBUG, "Notifying impl about property change.");
    ptr->setProperty(*this);
}
<commit_msg>Added implementation to Property::getProperty<commit_after>

#include "Property.h"
#include "base_types.h"
#include "tis_logging.h"

#include <cstring>
#include <algorithm>

using namespace tis_imaging;

Property::Property ()
    : value_type(UNDEFINED), prop(), ref_prop()
{}

Property::Property (const camera_property& _property, const VALUE_TYPE& t)
    : prop(_property), ref_prop(_property), value_type(t)
{}

Property::Property (const camera_property& _property,
                    const std::map<std::string, int>& _map,
                    const VALUE_TYPE& t)
    : prop(_property), ref_prop(_property), string_map(_map), value_type(t)
{}

Property::~Property ()
{}

void Property::reset ()
{
    tis_log(TIS_LOG_INFO, "Resetting property to initial values.");
    prop = ref_prop;

    notifyImpl();
}

std::string Property::getName () const
{
    return prop.name;
}

PROPERTY_TYPE Property::getType () const
{
    return prop.type;
}

bool Property::isReadOnly () const
{
    return (prop.flags & (1 << PROPERTY_FLAG_READ_ONLY));
}

bool Property::isWriteOnly () const
{
    return (prop.flags & ((long)1 << PROPERTY_FLAG_WRITE_ONLY));
}

bool Property::isDisabled () const
{
    return (prop.flags & (1 << PROPERTY_FLAG_DISABLED));
}

uint32_t Property::getFlags () const
{
    return prop.flags;
}

struct camera_property Property::getStruct () const
{
    return prop;
}

bool Property::setStruct (const struct camera_property& p)
{
    switch (prop.type)
    {
        case PROPERTY_TYPE_STRING:
            std::strncpy(prop.value.s.value, p.value.s.value, sizeof(prop.value.s.value));
        case PROPERTY_TYPE_STRING_TABLE:
            prop.value.i.value = p.value.i.value;
            break;
        case PROPERTY_TYPE_INTEGER:
            prop.value.i.value = p.value.i.value;
            break;
        case PROPERTY_TYPE_DOUBLE:
            prop.value.d.value = p.value.d.value;
            break;
        case PROPERTY_TYPE_BUTTON:
            // do nothing
            break;
        case PROPERTY_TYPE_BOOLEAN:
            prop.value.b.value = p.value.b.value;
            break;
        case PROPERTY_TYPE_UNKNOWN:
        default:
            return false;
    }
    return true;
}

Property::VALUE_TYPE Property::getValueType () const
{
    return value_type;
}

bool Property::setReadOnly (const bool only_read)
{
    if (only_read)
    {
        prop.flags |= 1 << PROPERTY_FLAG_READ_ONLY;
    }
    else
    {
        prop.flags &= ~(1 << PROPERTY_FLAG_READ_ONLY);
    }

    return true;
}

bool Property::setWriteOnly (const bool only_write)
{
    long val = 1;
    if (only_write)
    {
        prop.flags |= val << PROPERTY_FLAG_WRITE_ONLY;
    }
    else
    {
        prop.flags &= ~(val << PROPERTY_FLAG_WRITE_ONLY);
    }

    return true;
}

bool Property::setInactive (const bool is_disabled)
{
    if (is_disabled)
    {
        prop.flags |= 1 << PROPERTY_FLAG_INACTIVE;
    }
    else
    {
        prop.flags &= ~(1 << PROPERTY_FLAG_INACTIVE);
    }

    return true;
}

bool Property::isAvailable (const Property&)
{
    // TODO:
    return false;
}

bool Property::setProperty (const Property&)
{
    if (impl.expired())
    {
        return false;
    }
    notifyImpl();

    return true;
}

bool Property::getProperty (Property& p)
{
    p.setStruct(this->prop);
    return true;
}

void Property::notifyImpl ()
{
    if (impl.expired())
    {
        tis_log(TIS_LOG_ERROR, "PropertyImpl expired. Property %s is corrupted.", this->getName().c_str());
    }

    auto ptr(impl.lock());

    // tis_log(TIS_LOG_DEBUG, "Notifying impl about property change.");
    ptr->setProperty(*this);
}
<|endoftext|>


<commit_before>#include "condor_common.h"
#include "classad_collection.h"
#include "gahp-client.h"
#include "Functor.h"
#include "GenerateConfigFile.h"

#include "condor_config.h"
#include "filename_tools.h"
#include "directory.h"
#include "safe_fopen.h"

int
GenerateConfigFile::operator() () {
	dprintf( D_FULLDEBUG, "GenerateConfigFile::operator()\n" );

	std::map< std::string, std::string > mapping;
	mapping[ "S3BucketName" ] = "ANNEX_DEFAULT_S3_BUCKET";
	mapping[ "odiLeaseFunctionARN" ] = "ANNEX_DEFAULT_ODI_LEASE_FUNCTION_ARN";
	mapping[ "sfrLeaseFunctionARN" ] = "ANNEX_DEFAULT_SFR_LEASE_FUNCTION_ARN";
	mapping[ "InstanceProfileARN" ] = "ANNEX_DEFAULT_ODI_INSTANCE_PROFILE_ARN";
	mapping[ "SecurityGroupID" ] = "ANNEX_DEFAULT_ODI_SECURITY_GROUP_IDS";
	mapping[ "KeyName" ] = "ANNEX_DEFAULT_ODI_KEY_NAME";
	mapping[ "AccessKeyFile" ] = "ANNEX_DEFAULT_ACCESS_KEY_FILE";
	mapping[ "SecretKeyFile" ] = "ANNEX_DEFAULT_SECRET_KEY_FILE";

	// FIXME: Do something clever for versioning.
	// (Should these be in the param table?)
	scratchpad->Assign( "odiDefaultInstanceType", "m4.large" );
	mapping[ "odiDefaultInstanceType" ] = "ANNEX_DEFAULT_ODI_INSTANCE_TYPE";
	scratchpad->Assign( "odiDefaultImageID", "ami-83269195" );
	mapping[ "odiDefaultImageID" ] = "ANNEX_DEFAULT_ODI_IMAGE_ID";

	// Append the annex configuration to the user config file.
	FILE * configFile = NULL;

	// Consider using createUserConfigDir() from CreateKeyPair.cpp.
	std::string userConfigName;
	MyString userConfigSource;
	param( userConfigName, "USER_CONFIG_FILE" );
	if(! userConfigName.empty()) {
		find_user_file( userConfigSource, userConfigName.c_str(), false );
		if(! userConfigSource.empty()) {
			// Create the containing directory if necessary, and only the
			// containing directory -- don't do anything stupid if the
			// user configuration directory is misconfigured.
			std::string dir, file;
			filename_split( userConfigSource.c_str(), dir, file );
			if(! IsDirectory( dir.c_str() )) {
				mkdir( dir.c_str(), 0755 );
			}

			configFile = safe_fcreate_keep_if_exists_follow( userConfigSource.c_str(),
				"a", 0644 );
			if( configFile == NULL ) {
				fprintf( stderr, "Failed to open user configuration file '%s': %s (%d).  Printing configuration...\n",
					userConfigSource.c_str(), strerror( errno ), errno );
				configFile = stdout;
			}
		} else {
			fprintf( stderr, "Unable to locate your user configuration file.  Printing configuration...\n" );
			configFile = stdout;
		}
	} else {
		fprintf( stderr, "Your HTCondor installation is configured to ignore user configuration files.  Contact your system administrator.  Printing configuration...\n" );
		configFile = stdout;
	}

	fprintf( configFile, "\n" );
	fprintf( configFile, "# Generated by condor_annex -setup.\n" );

	std::string value;
	for( auto i = mapping.begin(); i != mapping.end(); ++i ) {
		value.clear();
		scratchpad->LookupString( i->first.c_str(), value );
		if(! value.empty()) {
			fprintf( configFile, "%s = %s\n", i->second.c_str(), value.c_str() );
		}
	}

	std::string keyPath;
	scratchpad->LookupString( "KeyPath", keyPath );
	if(! keyPath.empty()) {
		fprintf( configFile, "# For debugging:\n" );
		fprintf( configFile, "# ssh -i %s +ec2-user@<address>\n", keyPath.c_str() );
	}

	fprintf( configFile, "\n" );

	daemonCore->Reset_Timer( gahp->getNotificationTimerId(), 0, TIMER_NEVER );
	return PASS_STREAM;
}

int
GenerateConfigFile::rollback() {
	dprintf( D_FULLDEBUG, "GenerateConfigFile::rollback()\n" );

	// This functor does nothing (to the service), so don't undo anything.

	daemonCore->Reset_Timer( gahp->getNotificationTimerId(), 0, TIMER_NEVER );
	return PASS_STREAM;
}
<commit_msg>(#6216)  Update the default AMI.<commit_after>#include "condor_common.h"
#include "classad_collection.h"
#include "gahp-client.h"
#include "Functor.h"
#include "GenerateConfigFile.h"

#include "condor_config.h"
#include "filename_tools.h"
#include "directory.h"
#include "safe_fopen.h"

int
GenerateConfigFile::operator() () {
	dprintf( D_FULLDEBUG, "GenerateConfigFile::operator()\n" );

	std::map< std::string, std::string > mapping;
	mapping[ "S3BucketName" ] = "ANNEX_DEFAULT_S3_BUCKET";
	mapping[ "odiLeaseFunctionARN" ] = "ANNEX_DEFAULT_ODI_LEASE_FUNCTION_ARN";
	mapping[ "sfrLeaseFunctionARN" ] = "ANNEX_DEFAULT_SFR_LEASE_FUNCTION_ARN";
	mapping[ "InstanceProfileARN" ] = "ANNEX_DEFAULT_ODI_INSTANCE_PROFILE_ARN";
	mapping[ "SecurityGroupID" ] = "ANNEX_DEFAULT_ODI_SECURITY_GROUP_IDS";
	mapping[ "KeyName" ] = "ANNEX_DEFAULT_ODI_KEY_NAME";
	mapping[ "AccessKeyFile" ] = "ANNEX_DEFAULT_ACCESS_KEY_FILE";
	mapping[ "SecretKeyFile" ] = "ANNEX_DEFAULT_SECRET_KEY_FILE";

	// FIXME: Do something clever for versioning.
	scratchpad->Assign( "odiDefaultInstanceType", "m4.large" );
	mapping[ "odiDefaultInstanceType" ] = "ANNEX_DEFAULT_ODI_INSTANCE_TYPE";
	scratchpad->Assign( "odiDefaultImageID", "ami-35b13223" );
	mapping[ "odiDefaultImageID" ] = "ANNEX_DEFAULT_ODI_IMAGE_ID";

	// Append the annex configuration to the user config file.
	FILE * configFile = NULL;

	// Consider using createUserConfigDir() from CreateKeyPair.cpp.
	std::string userConfigName;
	MyString userConfigSource;
	param( userConfigName, "USER_CONFIG_FILE" );
	if(! userConfigName.empty()) {
		find_user_file( userConfigSource, userConfigName.c_str(), false );
		if(! userConfigSource.empty()) {
			// Create the containing directory if necessary, and only the
			// containing directory -- don't do anything stupid if the
			// user configuration directory is misconfigured.
			std::string dir, file;
			filename_split( userConfigSource.c_str(), dir, file );
			if(! IsDirectory( dir.c_str() )) {
				mkdir( dir.c_str(), 0755 );
			}

			configFile = safe_fcreate_keep_if_exists_follow( userConfigSource.c_str(),
				"a", 0644 );
			if( configFile == NULL ) {
				fprintf( stderr, "Failed to open user configuration file '%s': %s (%d).  Printing configuration...\n",
					userConfigSource.c_str(), strerror( errno ), errno );
				configFile = stdout;
			}
		} else {
			fprintf( stderr, "Unable to locate your user configuration file.  Printing configuration...\n" );
			configFile = stdout;
		}
	} else {
		fprintf( stderr, "Your HTCondor installation is configured to ignore user configuration files.  Contact your system administrator.  Printing configuration...\n" );
		configFile = stdout;
	}

	fprintf( configFile, "\n" );
	fprintf( configFile, "# Generated by condor_annex -setup.\n" );

	std::string value;
	for( auto i = mapping.begin(); i != mapping.end(); ++i ) {
		value.clear();
		scratchpad->LookupString( i->first.c_str(), value );
		if(! value.empty()) {
			fprintf( configFile, "%s = %s\n", i->second.c_str(), value.c_str() );
		}
	}

	std::string keyPath;
	scratchpad->LookupString( "KeyPath", keyPath );
	if(! keyPath.empty()) {
		fprintf( configFile, "# For debugging:\n" );
		fprintf( configFile, "# ssh -i %s +ec2-user@<address>\n", keyPath.c_str() );
	}

	fprintf( configFile, "\n" );

	daemonCore->Reset_Timer( gahp->getNotificationTimerId(), 0, TIMER_NEVER );
	return PASS_STREAM;
}

int
GenerateConfigFile::rollback() {
	dprintf( D_FULLDEBUG, "GenerateConfigFile::rollback()\n" );

	// This functor does nothing (to the service), so don't undo anything.

	daemonCore->Reset_Timer( gahp->getNotificationTimerId(), 0, TIMER_NEVER );
	return PASS_STREAM;
}
<|endoftext|>


<commit_before>#include "Func.h"
#include "Function.h"
#include "IR.h"
#include "IRMutator.h"
#include "Schedule.h"
#include "Var.h"

namespace Halide {

LoopLevel::LoopLevel(Internal::IntrusivePtr<Internal::FunctionContents> f,
                     const std::string &var_name,
                     bool is_rvar)
    : function_contents(f), var_name(var_name), is_rvar(is_rvar) {}
LoopLevel::LoopLevel(Internal::Function f, VarOrRVar v) : LoopLevel(f.get_contents(), v.name(), v.is_rvar) {}
LoopLevel::LoopLevel(Func f, VarOrRVar v) : LoopLevel(f.function().get_contents(), v.name(), v.is_rvar) {}

std::string LoopLevel::func_name() const {
    if (function_contents.defined()) {
        return Internal::Function(function_contents).name();
    }
    return "";
}

Func LoopLevel::func() const {
    internal_assert(!is_inline() && !is_root());
    internal_assert(function_contents.defined());
    return Func(Internal::Function(function_contents));
}

VarOrRVar LoopLevel::var() const {
    internal_assert(!is_inline() && !is_root());
    return VarOrRVar(var_name, is_rvar);
}

bool LoopLevel::is_inline() const {
    return var_name.empty();
}

/*static*/
LoopLevel LoopLevel::root() {
    return LoopLevel(nullptr, "__root", false);
}

bool LoopLevel::is_root() const {
    return var_name == "__root";
}

std::string LoopLevel::to_string() const {
    return (function_contents.defined() ? Internal::Function(function_contents).name() : "") + "." + var_name;
}

bool LoopLevel::match(const std::string &loop) const {
    return Internal::starts_with(loop, func_name() + ".") &&
           Internal::ends_with(loop, "." + var_name);
}

bool LoopLevel::match(const LoopLevel &other) const {
    // Must compare by name, not by pointer, since in() can make copies
    // that we need to consider equivalent
    return (func_name() == other.func_name() &&
            (var_name == other.var_name ||
             Internal::ends_with(var_name, "." + other.var_name) ||
             Internal::ends_with(other.var_name, "." + var_name)));
}

bool LoopLevel::operator==(const LoopLevel &other) const {
    // Must compare by name, not by pointer, since in() can make copies
    // that we need to consider equivalent
    return func_name() == other.func_name() && var_name == other.var_name;
}

namespace Internal {

typedef std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> DeepCopyMap;

IntrusivePtr<FunctionContents> deep_copy_function_contents_helper(
    const IntrusivePtr<FunctionContents> &src,
    DeepCopyMap &copied_map);

/** A schedule for a halide function, which defines where, when, and
 * how it should be evaluated. */
struct ScheduleContents {
    mutable RefCount ref_count;

    LoopLevel store_level, compute_level;
    std::vector<ReductionVariable> rvars;
    std::vector<Split> splits;
    std::vector<Dim> dims;
    std::vector<StorageDim> storage_dims;
    std::vector<Bound> bounds;
    std::vector<Prefetch> prefetches;
    std::map<std::string, IntrusivePtr<Internal::FunctionContents>> wrappers;
    bool memoized;
    bool touched;
    bool allow_race_conditions;

    ScheduleContents() : memoized(false), touched(false), allow_race_conditions(false) {};

    // Pass an IRMutator through to all Exprs referenced in the ScheduleContents
    void mutate(IRMutator *mutator) {
        for (ReductionVariable &r : rvars) {
            if (r.min.defined()) {
                r.min = mutator->mutate(r.min);
            }
            if (r.extent.defined()) {
                r.extent = mutator->mutate(r.extent);
            }
        }
        for (Split &s : splits) {
            if (s.factor.defined()) {
                s.factor = mutator->mutate(s.factor);
            }
        }
        for (Bound &b : bounds) {
            if (b.min.defined()) {
                b.min = mutator->mutate(b.min);
            }
            if (b.extent.defined()) {
                b.extent = mutator->mutate(b.extent);
            }
            if (b.modulus.defined()) {
                b.modulus = mutator->mutate(b.modulus);
            }
            if (b.remainder.defined()) {
                b.remainder = mutator->mutate(b.remainder);
            }
        }
        for (Prefetch &p : prefetches) {
            if (p.offset.defined()) {
                p.offset = mutator->mutate(p.offset);
            }
        }
    }
};

template<>
EXPORT RefCount &ref_count<ScheduleContents>(const ScheduleContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<ScheduleContents>(const ScheduleContents *p) {
    delete p;
}

Schedule::Schedule() : contents(new ScheduleContents) {}

Schedule Schedule::deep_copy(
        std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> &copied_map) const {

    internal_assert(contents.defined()) << "Cannot deep-copy undefined Schedule\n";
    Schedule copy;
    copy.contents->store_level = contents->store_level;
    copy.contents->compute_level = contents->compute_level;
    copy.contents->rvars = contents->rvars;
    copy.contents->splits = contents->splits;
    copy.contents->dims = contents->dims;
    copy.contents->storage_dims = contents->storage_dims;
    copy.contents->bounds = contents->bounds;
    copy.contents->prefetches = contents->prefetches;
    copy.contents->memoized = contents->memoized;
    copy.contents->touched = contents->touched;
    copy.contents->allow_race_conditions = contents->allow_race_conditions;

    // Deep-copy wrapper functions. If function has already been deep-copied before,
    // i.e. it's in the 'copied_map', use the deep-copied version from the map instead
    // of creating a new deep-copy
    for (const auto &iter : contents->wrappers) {
        IntrusivePtr<FunctionContents> &copied_func = copied_map[iter.second];
        if (copied_func.defined()) {
            copy.contents->wrappers[iter.first] = copied_func;
        } else {
            copy.contents->wrappers[iter.first] = deep_copy_function_contents_helper(iter.second, copied_map);
            copied_map[iter.second] = copy.contents->wrappers[iter.first];
        }
    }
    internal_assert(copy.contents->wrappers.size() == contents->wrappers.size());
    return copy;
}

bool &Schedule::memoized() {
    return contents->memoized;
}

bool Schedule::memoized() const {
    return contents->memoized;
}

bool &Schedule::touched() {
    return contents->touched;
}

bool Schedule::touched() const {
    return contents->touched;
}

const std::vector<Split> &Schedule::splits() const {
    return contents->splits;
}

std::vector<Split> &Schedule::splits() {
    return contents->splits;
}

std::vector<Dim> &Schedule::dims() {
    return contents->dims;
}

const std::vector<Dim> &Schedule::dims() const {
    return contents->dims;
}

std::vector<StorageDim> &Schedule::storage_dims() {
    return contents->storage_dims;
}

const std::vector<StorageDim> &Schedule::storage_dims() const {
    return contents->storage_dims;
}

std::vector<Bound> &Schedule::bounds() {
    return contents->bounds;
}

const std::vector<Bound> &Schedule::bounds() const {
    return contents->bounds;
}

std::vector<Prefetch> &Schedule::prefetches() {
    return contents->prefetches;
}

const std::vector<Prefetch> &Schedule::prefetches() const {
    return contents->prefetches;
}

std::vector<ReductionVariable> &Schedule::rvars() {
    return contents->rvars;
}

const std::vector<ReductionVariable> &Schedule::rvars() const {
    return contents->rvars;
}

std::map<std::string, IntrusivePtr<Internal::FunctionContents>> &Schedule::wrappers() {
    return contents->wrappers;
}

const std::map<std::string, IntrusivePtr<Internal::FunctionContents>> &Schedule::wrappers() const {
    return contents->wrappers;
}

void Schedule::add_wrapper(const std::string &f,
                           const IntrusivePtr<Internal::FunctionContents> &wrapper) {
    if (contents->wrappers.count(f)) {
        if (f.empty()) {
            user_warning << "Replacing previous definition of global wrapper in function \""
                         << f << "\"\n";
        } else {
            internal_error << "Wrapper redefinition in function \"" << f << "\" is not allowed\n";
        }
    }
    contents->wrappers[f] = wrapper;
}

LoopLevel &Schedule::store_level() {
    return contents->store_level;
}

LoopLevel &Schedule::compute_level() {
    return contents->compute_level;
}

const LoopLevel &Schedule::store_level() const {
    return contents->store_level;
}

const LoopLevel &Schedule::compute_level() const {
    return contents->compute_level;
}

bool &Schedule::allow_race_conditions() {
    return contents->allow_race_conditions;
}

bool Schedule::allow_race_conditions() const {
    return contents->allow_race_conditions;
}

void Schedule::accept(IRVisitor *visitor) const {
    for (const ReductionVariable &r : rvars()) {
        if (r.min.defined()) {
            r.min.accept(visitor);
        }
        if (r.extent.defined()) {
            r.extent.accept(visitor);
        }
    }
    for (const Split &s : splits()) {
        if (s.factor.defined()) {
            s.factor.accept(visitor);
        }
    }
    for (const Bound &b : bounds()) {
        if (b.min.defined()) {
            b.min.accept(visitor);
        }
        if (b.extent.defined()) {
            b.extent.accept(visitor);
        }
        if (b.modulus.defined()) {
            b.modulus.accept(visitor);
        }
        if (b.remainder.defined()) {
            b.remainder.accept(visitor);
        }
    }
    for (const Prefetch &p : prefetches()) {
        debug(4) << "Schedule::accept prefetches\n";
        if (p.offset.defined()) {
            debug(4) << "Prefetch: " << p.var
                               << " " << p.offset << "\n";
            p.offset.accept(visitor);
        }
    }
}

void Schedule::mutate(IRMutator *mutator) {
    if (contents.defined()) {
        contents->mutate(mutator);
    }
}

}  // namespace Internal
}  // namespace Halide

<commit_msg>One more debug update missed in previous commit<commit_after>#include "Func.h"
#include "Function.h"
#include "IR.h"
#include "IRMutator.h"
#include "Schedule.h"
#include "Var.h"

namespace Halide {

LoopLevel::LoopLevel(Internal::IntrusivePtr<Internal::FunctionContents> f,
                     const std::string &var_name,
                     bool is_rvar)
    : function_contents(f), var_name(var_name), is_rvar(is_rvar) {}
LoopLevel::LoopLevel(Internal::Function f, VarOrRVar v) : LoopLevel(f.get_contents(), v.name(), v.is_rvar) {}
LoopLevel::LoopLevel(Func f, VarOrRVar v) : LoopLevel(f.function().get_contents(), v.name(), v.is_rvar) {}

std::string LoopLevel::func_name() const {
    if (function_contents.defined()) {
        return Internal::Function(function_contents).name();
    }
    return "";
}

Func LoopLevel::func() const {
    internal_assert(!is_inline() && !is_root());
    internal_assert(function_contents.defined());
    return Func(Internal::Function(function_contents));
}

VarOrRVar LoopLevel::var() const {
    internal_assert(!is_inline() && !is_root());
    return VarOrRVar(var_name, is_rvar);
}

bool LoopLevel::is_inline() const {
    return var_name.empty();
}

/*static*/
LoopLevel LoopLevel::root() {
    return LoopLevel(nullptr, "__root", false);
}

bool LoopLevel::is_root() const {
    return var_name == "__root";
}

std::string LoopLevel::to_string() const {
    return (function_contents.defined() ? Internal::Function(function_contents).name() : "") + "." + var_name;
}

bool LoopLevel::match(const std::string &loop) const {
    return Internal::starts_with(loop, func_name() + ".") &&
           Internal::ends_with(loop, "." + var_name);
}

bool LoopLevel::match(const LoopLevel &other) const {
    // Must compare by name, not by pointer, since in() can make copies
    // that we need to consider equivalent
    return (func_name() == other.func_name() &&
            (var_name == other.var_name ||
             Internal::ends_with(var_name, "." + other.var_name) ||
             Internal::ends_with(other.var_name, "." + var_name)));
}

bool LoopLevel::operator==(const LoopLevel &other) const {
    // Must compare by name, not by pointer, since in() can make copies
    // that we need to consider equivalent
    return func_name() == other.func_name() && var_name == other.var_name;
}

namespace Internal {

typedef std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> DeepCopyMap;

IntrusivePtr<FunctionContents> deep_copy_function_contents_helper(
    const IntrusivePtr<FunctionContents> &src,
    DeepCopyMap &copied_map);

/** A schedule for a halide function, which defines where, when, and
 * how it should be evaluated. */
struct ScheduleContents {
    mutable RefCount ref_count;

    LoopLevel store_level, compute_level;
    std::vector<ReductionVariable> rvars;
    std::vector<Split> splits;
    std::vector<Dim> dims;
    std::vector<StorageDim> storage_dims;
    std::vector<Bound> bounds;
    std::vector<Prefetch> prefetches;
    std::map<std::string, IntrusivePtr<Internal::FunctionContents>> wrappers;
    bool memoized;
    bool touched;
    bool allow_race_conditions;

    ScheduleContents() : memoized(false), touched(false), allow_race_conditions(false) {};

    // Pass an IRMutator through to all Exprs referenced in the ScheduleContents
    void mutate(IRMutator *mutator) {
        for (ReductionVariable &r : rvars) {
            if (r.min.defined()) {
                r.min = mutator->mutate(r.min);
            }
            if (r.extent.defined()) {
                r.extent = mutator->mutate(r.extent);
            }
        }
        for (Split &s : splits) {
            if (s.factor.defined()) {
                s.factor = mutator->mutate(s.factor);
            }
        }
        for (Bound &b : bounds) {
            if (b.min.defined()) {
                b.min = mutator->mutate(b.min);
            }
            if (b.extent.defined()) {
                b.extent = mutator->mutate(b.extent);
            }
            if (b.modulus.defined()) {
                b.modulus = mutator->mutate(b.modulus);
            }
            if (b.remainder.defined()) {
                b.remainder = mutator->mutate(b.remainder);
            }
        }
        for (Prefetch &p : prefetches) {
            if (p.offset.defined()) {
                p.offset = mutator->mutate(p.offset);
            }
        }
    }
};

template<>
EXPORT RefCount &ref_count<ScheduleContents>(const ScheduleContents *p) {
    return p->ref_count;
}

template<>
EXPORT void destroy<ScheduleContents>(const ScheduleContents *p) {
    delete p;
}

Schedule::Schedule() : contents(new ScheduleContents) {}

Schedule Schedule::deep_copy(
        std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> &copied_map) const {

    internal_assert(contents.defined()) << "Cannot deep-copy undefined Schedule\n";
    Schedule copy;
    copy.contents->store_level = contents->store_level;
    copy.contents->compute_level = contents->compute_level;
    copy.contents->rvars = contents->rvars;
    copy.contents->splits = contents->splits;
    copy.contents->dims = contents->dims;
    copy.contents->storage_dims = contents->storage_dims;
    copy.contents->bounds = contents->bounds;
    copy.contents->prefetches = contents->prefetches;
    copy.contents->memoized = contents->memoized;
    copy.contents->touched = contents->touched;
    copy.contents->allow_race_conditions = contents->allow_race_conditions;

    // Deep-copy wrapper functions. If function has already been deep-copied before,
    // i.e. it's in the 'copied_map', use the deep-copied version from the map instead
    // of creating a new deep-copy
    for (const auto &iter : contents->wrappers) {
        IntrusivePtr<FunctionContents> &copied_func = copied_map[iter.second];
        if (copied_func.defined()) {
            copy.contents->wrappers[iter.first] = copied_func;
        } else {
            copy.contents->wrappers[iter.first] = deep_copy_function_contents_helper(iter.second, copied_map);
            copied_map[iter.second] = copy.contents->wrappers[iter.first];
        }
    }
    internal_assert(copy.contents->wrappers.size() == contents->wrappers.size());
    return copy;
}

bool &Schedule::memoized() {
    return contents->memoized;
}

bool Schedule::memoized() const {
    return contents->memoized;
}

bool &Schedule::touched() {
    return contents->touched;
}

bool Schedule::touched() const {
    return contents->touched;
}

const std::vector<Split> &Schedule::splits() const {
    return contents->splits;
}

std::vector<Split> &Schedule::splits() {
    return contents->splits;
}

std::vector<Dim> &Schedule::dims() {
    return contents->dims;
}

const std::vector<Dim> &Schedule::dims() const {
    return contents->dims;
}

std::vector<StorageDim> &Schedule::storage_dims() {
    return contents->storage_dims;
}

const std::vector<StorageDim> &Schedule::storage_dims() const {
    return contents->storage_dims;
}

std::vector<Bound> &Schedule::bounds() {
    return contents->bounds;
}

const std::vector<Bound> &Schedule::bounds() const {
    return contents->bounds;
}

std::vector<Prefetch> &Schedule::prefetches() {
    return contents->prefetches;
}

const std::vector<Prefetch> &Schedule::prefetches() const {
    return contents->prefetches;
}

std::vector<ReductionVariable> &Schedule::rvars() {
    return contents->rvars;
}

const std::vector<ReductionVariable> &Schedule::rvars() const {
    return contents->rvars;
}

std::map<std::string, IntrusivePtr<Internal::FunctionContents>> &Schedule::wrappers() {
    return contents->wrappers;
}

const std::map<std::string, IntrusivePtr<Internal::FunctionContents>> &Schedule::wrappers() const {
    return contents->wrappers;
}

void Schedule::add_wrapper(const std::string &f,
                           const IntrusivePtr<Internal::FunctionContents> &wrapper) {
    if (contents->wrappers.count(f)) {
        if (f.empty()) {
            user_warning << "Replacing previous definition of global wrapper in function \""
                         << f << "\"\n";
        } else {
            internal_error << "Wrapper redefinition in function \"" << f << "\" is not allowed\n";
        }
    }
    contents->wrappers[f] = wrapper;
}

LoopLevel &Schedule::store_level() {
    return contents->store_level;
}

LoopLevel &Schedule::compute_level() {
    return contents->compute_level;
}

const LoopLevel &Schedule::store_level() const {
    return contents->store_level;
}

const LoopLevel &Schedule::compute_level() const {
    return contents->compute_level;
}

bool &Schedule::allow_race_conditions() {
    return contents->allow_race_conditions;
}

bool Schedule::allow_race_conditions() const {
    return contents->allow_race_conditions;
}

void Schedule::accept(IRVisitor *visitor) const {
    for (const ReductionVariable &r : rvars()) {
        if (r.min.defined()) {
            r.min.accept(visitor);
        }
        if (r.extent.defined()) {
            r.extent.accept(visitor);
        }
    }
    for (const Split &s : splits()) {
        if (s.factor.defined()) {
            s.factor.accept(visitor);
        }
    }
    for (const Bound &b : bounds()) {
        if (b.min.defined()) {
            b.min.accept(visitor);
        }
        if (b.extent.defined()) {
            b.extent.accept(visitor);
        }
        if (b.modulus.defined()) {
            b.modulus.accept(visitor);
        }
        if (b.remainder.defined()) {
            b.remainder.accept(visitor);
        }
    }
    for (const Prefetch &p : prefetches()) {
        if (p.offset.defined()) {
            p.offset.accept(visitor);
        }
    }
}

void Schedule::mutate(IRMutator *mutator) {
    if (contents.defined()) {
        contents->mutate(mutator);
    }
}

}  // namespace Internal
}  // namespace Halide

<|endoftext|>


<commit_before>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////

#include <cstring>
#include <iostream>
#include "ShBitSet.hpp"
#include "ShDebug.hpp"
#include "ShError.hpp"

#define WORD_SIZE sizeof(unsigned int)

namespace {

std::size_t wordsize(std::size_t size)
{
  return size / WORD_SIZE + (size % WORD_SIZE ? 1 : 0);
}

std::size_t fullwordsize(std::size_t size)
{
  return size / WORD_SIZE;
}

}

namespace SH {

ShBitRef::operator bool() const
{
  return (*m_byte) & m_mask;
}

ShBitRef& ShBitRef::operator=(bool b)
{
  if (b) {
    *m_byte |= m_mask;
  } else {
    *m_byte &= ~m_mask;
  }
}

ShBitRef::ShBitRef(unsigned int* byte, unsigned int mask)
  : m_byte(byte), m_mask(mask)
{
}

ShBitSet::ShBitSet()
  : m_size(0), m_data(0)
{
}

ShBitSet::ShBitSet(std::size_t size)
  : m_size(size), m_data(new unsigned int[wordsize(m_size)])
{
  for (std::size_t i = 0; i < wordsize(m_size); i++) {
    m_data[i] = 0;
  }
}

ShBitSet::ShBitSet(const ShBitSet& other)
  : m_size(other.m_size), m_data(new unsigned int[wordsize(m_size)])
{
  memcpy(m_data, other.m_data, wordsize(m_size) * WORD_SIZE);
}

ShBitSet::~ShBitSet()
{
  delete [] m_data;
}

ShBitSet& ShBitSet::operator=(const ShBitSet& other)
{
  delete [] m_data;
  m_size = other.m_size;
  m_data = new unsigned int[wordsize(m_size)];
  memcpy(m_data, other.m_data, wordsize(m_size) * WORD_SIZE);
}

ShBitSet& ShBitSet::operator&=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of &= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] &= other.m_data[i];
  return *this;
}

ShBitSet& ShBitSet::operator|=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of |= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] |= other.m_data[i];
  return *this;
}

ShBitSet& ShBitSet::operator^=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of ^= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] ^= other.m_data[i];
  return *this;
}

ShBitSet ShBitSet::operator&(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret &= other;
  return ret;
}

ShBitSet ShBitSet::operator|(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret |= other;
  return ret;
}

ShBitSet ShBitSet::operator^(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret ^= other;
  return ret;
}

ShBitSet ShBitSet::operator~() const
{
  ShBitSet ret(m_size);
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    ret.m_data[i] = ~m_data[i];
  return ret;
}

bool ShBitSet::operator==(const ShBitSet& other) const
{
  if (m_size != other.m_size) return false;
  for (int i = 0; i < fullwordsize(m_size); i++) {
    if (m_data[i] != other.m_data[i]) return false;
  }
  if (m_size % WORD_SIZE) {
    unsigned int mask = (1 << ((m_size % WORD_SIZE) + 1)) - 1;
    return ((m_data[m_size / WORD_SIZE] & mask) == (other.m_data[m_size / WORD_SIZE] & mask));
  }
  return true;
}

bool ShBitSet::operator!=(const ShBitSet& other) const
{
  return !(*this == other);
}

std::size_t ShBitSet::size() const
{
  return m_size;
}

bool ShBitSet::operator[](std::size_t i) const
{
  return m_data[i / WORD_SIZE] & (1 << (i % WORD_SIZE));
}

ShBitRef ShBitSet::operator[](std::size_t i)
{
  return ShBitRef(m_data + (i / WORD_SIZE), 1 << (i % WORD_SIZE));
}

std::ostream& operator<<(std::ostream& out, const ShBitSet& bitset)
{
  for (std::size_t i = 0; i < bitset.size(); i++) {
    out << bitset[i] ? '1' : '0';
  }
  return out;
}

}
<commit_msg>cleanup for Win32 side warning...<commit_after>// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
//          Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////

#include <cstring>
#include <iostream>
#include "ShBitSet.hpp"
#include "ShDebug.hpp"
#include "ShError.hpp"

#define WORD_SIZE sizeof(unsigned int)

namespace {

std::size_t wordsize(std::size_t size)
{
  return size / WORD_SIZE + (size % WORD_SIZE ? 1 : 0);
}

std::size_t fullwordsize(std::size_t size)
{
  return size / WORD_SIZE;
}

}

namespace SH {

ShBitRef::operator bool() const
{
  return (((*m_byte) & m_mask) == m_mask);
}

ShBitRef& ShBitRef::operator=(bool b)
{
  if (b) {
    *m_byte |= m_mask;
  } else {
    *m_byte &= ~m_mask;
  }
}

ShBitRef::ShBitRef(unsigned int* byte, unsigned int mask)
  : m_byte(byte), m_mask(mask)
{
}

ShBitSet::ShBitSet()
  : m_size(0), m_data(0)
{
}

ShBitSet::ShBitSet(std::size_t size)
  : m_size(size), m_data(new unsigned int[wordsize(m_size)])
{
  for (std::size_t i = 0; i < wordsize(m_size); i++) {
    m_data[i] = 0;
  }
}

ShBitSet::ShBitSet(const ShBitSet& other)
  : m_size(other.m_size), m_data(new unsigned int[wordsize(m_size)])
{
  memcpy(m_data, other.m_data, wordsize(m_size) * WORD_SIZE);
}

ShBitSet::~ShBitSet()
{
  delete [] m_data;
}

ShBitSet& ShBitSet::operator=(const ShBitSet& other)
{
  delete [] m_data;
  m_size = other.m_size;
  m_data = new unsigned int[wordsize(m_size)];
  memcpy(m_data, other.m_data, wordsize(m_size) * WORD_SIZE);
}

ShBitSet& ShBitSet::operator&=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of &= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] &= other.m_data[i];
  return *this;
}

ShBitSet& ShBitSet::operator|=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of |= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] |= other.m_data[i];
  return *this;
}

ShBitSet& ShBitSet::operator^=(const ShBitSet& other)
{
  if (m_size != other.m_size) ShError( ShException( "ShBitSet operands of ^= must be the same size." ) );
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    m_data[i] ^= other.m_data[i];
  return *this;
}

ShBitSet ShBitSet::operator&(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret &= other;
  return ret;
}

ShBitSet ShBitSet::operator|(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret |= other;
  return ret;
}

ShBitSet ShBitSet::operator^(const ShBitSet& other) const
{
  ShBitSet ret(*this);
  ret ^= other;
  return ret;
}

ShBitSet ShBitSet::operator~() const
{
  ShBitSet ret(m_size);
  for (std::size_t i = 0; i < wordsize(m_size); i++)
    ret.m_data[i] = ~m_data[i];
  return ret;
}

bool ShBitSet::operator==(const ShBitSet& other) const
{
  if (m_size != other.m_size) return false;
  for (unsigned int i = 0; i < fullwordsize(m_size); i++) {
    if (m_data[i] != other.m_data[i]) return false;
  }
  if (m_size % WORD_SIZE) {
    unsigned int mask = (1 << ((m_size % WORD_SIZE) + 1)) - 1;
    return ((m_data[m_size / WORD_SIZE] & mask) == (other.m_data[m_size / WORD_SIZE] & mask));
  }
  return true;
}

bool ShBitSet::operator!=(const ShBitSet& other) const
{
  return !(*this == other);
}

std::size_t ShBitSet::size() const
{
  return m_size;
}

bool ShBitSet::operator[](std::size_t i) const
{
  return ((m_data[i / WORD_SIZE] & (1 << (i % WORD_SIZE))) != 0);
}

ShBitRef ShBitSet::operator[](std::size_t i)
{
  return ShBitRef(m_data + (i / WORD_SIZE), 1 << (i % WORD_SIZE));
}

std::ostream& operator<<(std::ostream& out, const ShBitSet& bitset)
{
  for (std::size_t i = 0; i < bitset.size(); i++) {
    out << bitset[i] ? '1' : '0';
  }
  return out;
}

}
<|endoftext|>


<commit_before>#include <stdexcept>

#include "VarStack.h"
#include "Random.h"
#include "Scope.h"

using namespace std;

char randChar() {
	return g_randGen.drawNumber('a', 'z');
}

bool VarStack::doesVarExist(string name) {
	unsigned numScopeVars = currScope->getVarCount();
	if (names.size() < numScopeVars) {
		throw runtime_error("More scope variables than contained in VarStack somehow?!");
	}
	if (names.size()) {
		for (int i = names.size() - 1; i >= (int)(names.size() - numScopeVars); i--) {
			if (names[i] == name) {
				return true;
			}
		}
	}
	return false;
}

void VarStack::addVar(SupportedType type, string name) {
	// names.insert(name);
	names.push_back(name);
	types[type].push_back(name);
	currScope->incVarCount(type);
}

string VarStack::newVar(SupportedType type) {
	string name = g_varNameGen.getRandVarName();
	// name += randChar();

	// while (names.count(name))
	// 	name += randChar();
	while (doesVarExist(name)) {
		// name += randChar();
		string newWord;
		do {
			newWord = g_varNameGen.getRandVarName();
		} while (name.find(newWord) != string::npos);
		name += "_" + newWord;
	}

	addVar(type, name);
	return name;
}

string VarStack::newVar(SupportedType type, string name) {
	// add a number to the end of the proposed name
	int counter = 1;
	string newName = name;
	// while (names.count(newName))
	// 	newName = name + to_string(counter++);
	while (doesVarExist(name))
		newName = name + to_string(counter++);
	addVar(type, newName);
	return newName;
}

string VarStack::getVar(SupportedType type) {
	if (types[type].empty())
		throw runtime_error("VarStack has no variables of type " + type);

	int random = g_randGen.drawNumber(0, types[type].size() - 1);
	return types[type][random];
}

void VarStack::setScope(Scope *newScope) {
	currScope = newScope;
}

bool VarStack::popVars() {
	unsigned numScopeVars = currScope->getVarCount();
	if (names.size() < numScopeVars) {
		throw runtime_error("More scope variables than contained in VarStack somehow?!");
	}
	for (unsigned i = 0; i < numScopeVars; i++) {
		names.pop_back();
	}
	auto varTypeCounts = currScope->getVarTypeCounts();
	for (auto it : varTypeCounts) {
		SupportedType type = (SupportedType)it.first;
		unsigned numTypeVars = it.second;
		if (types[type].size() < numTypeVars) {
			throw runtime_error("More scope variables of a certain type than contained in VarStack somehow?!");
		}
		for (unsigned i = 0; i < numTypeVars; i++) {
			types[type].pop_back();
		}
	}
	return true;
}<commit_msg>Clean up unneeded commented code<commit_after>#include <stdexcept>

#include "VarStack.h"
#include "Random.h"
#include "Scope.h"

using namespace std;

char randChar() {
	return g_randGen.drawNumber('a', 'z');
}

bool VarStack::doesVarExist(string name) {
	unsigned numScopeVars = currScope->getVarCount();
	if (names.size() < numScopeVars) {
		throw runtime_error("More scope variables than contained in VarStack somehow?!");
	}
	if (names.size()) {
		for (int i = names.size() - 1; i >= (int)(names.size() - numScopeVars); i--) {
			if (names[i] == name) {
				return true;
			}
		}
	}
	return false;
}

void VarStack::addVar(SupportedType type, string name) {
	// names.insert(name);
	names.push_back(name);
	types[type].push_back(name);
	currScope->incVarCount(type);
}

string VarStack::newVar(SupportedType type) {
	string name = g_varNameGen.getRandVarName();
	while (doesVarExist(name)) {
		string newWord;
		do {
			newWord = g_varNameGen.getRandVarName();
		} while (name.find(newWord) != string::npos);
		name += "_" + newWord;
	}

	addVar(type, name);
	return name;
}

string VarStack::newVar(SupportedType type, string name) {
	// add a number to the end of the proposed name
	int counter = 1;
	string newName = name;
	while (doesVarExist(name))
		newName = name + to_string(counter++);
	addVar(type, newName);
	return newName;
}

string VarStack::getVar(SupportedType type) {
	if (types[type].empty())
		throw runtime_error("VarStack has no variables of type " + type);

	int random = g_randGen.drawNumber(0, types[type].size() - 1);
	return types[type][random];
}

void VarStack::setScope(Scope *newScope) {
	currScope = newScope;
}

bool VarStack::popVars() {
	unsigned numScopeVars = currScope->getVarCount();
	if (names.size() < numScopeVars) {
		throw runtime_error("More scope variables than contained in VarStack somehow?!");
	}
	for (unsigned i = 0; i < numScopeVars; i++) {
		names.pop_back();
	}
	auto varTypeCounts = currScope->getVarTypeCounts();
	for (auto it : varTypeCounts) {
		SupportedType type = (SupportedType)it.first;
		unsigned numTypeVars = it.second;
		if (types[type].size() < numTypeVars) {
			throw runtime_error("More scope variables of a certain type than contained in VarStack somehow?!");
		}
		for (unsigned i = 0; i < numTypeVars; i++) {
			types[type].pop_back();
		}
	}
	return true;
}<|endoftext|>