<commit_before>/*
 * Presentation.cpp
 *
 * Copyright (C) 2009-14 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "Presentation.hpp"

#include <boost/regex.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <core/FileSerializer.hpp>

using namespace core;

namespace session {
namespace modules {
namespace rmarkdown {
namespace presentation {

namespace {

struct SlideNavigationItem
{
   SlideNavigationItem(const std::string& title,
                       int indent,
                       int index,
                       int line)
      : title(title), indent(indent), index(index), line(line)
   {
   }

   std::string title;
   int indent;
   int index;
   int line;
};

json::Value itemAsJson(const SlideNavigationItem& item)
{
   json::Object slideJson;
   slideJson["title"] = item.title;
   slideJson["indent"] = item.indent;
   slideJson["index"] = item.index;
   slideJson["line"] = item.line;
   return slideJson;
}

} // anonymous namespace

void ammendResults(const std::string& formatName,
                   core::FilePath& targetFile,
                   int sourceLine,
                   json::Object* pResultJson)
{
   // provide slide navigation for ioslides_presentation
   if (formatName != "ioslides_presentation")
      return;

   // alias for nicer map syntax
   json::Object& resultJson = *pResultJson;

   // read the input file
   std::vector<std::string> lines;
   Error error = core::readStringVectorFromFile(targetFile, &lines, false);
   if (error)
   {
      LOG_ERROR(error);
      return;
   }

   // scan the input file looking for headers and slide breaks
   int totalSlides = 0;
   std::vector<SlideNavigationItem> slideNavigationItems;
   bool inCode = false;
   bool inYaml = false;
   bool haveTitle = false;
   boost::regex reYaml("^\\-{3}\\s*$");
   boost::regex reTitle("^title\\:(.*)$");
   boost::regex reCode("^`{3,}.*$");
   boost::regex reTitledSlide("^#(#)?([^|\\{]+).*$");
   boost::regex reUntitledSlide("^(\\-{4,}|\\*{4,})\\w*$");
   for (int i = 0; i<lines.size(); i++)
   {
      // alias line
      const std::string& line = lines.at(i);

      // toggle code state
      if (boost::regex_search(line, reCode))
         inCode = !inCode;

      // bail if we are in code
      if (inCode)
         continue;

      // toggle yaml state
      if (boost::regex_search(line, reYaml))
      {
         if (!inYaml)
         {
            inYaml = true;
         }
         else if (inYaml && !haveTitle) // no title found in first
                                        // yaml block, bail
         {
            break;
         }
      }

      // look for a title if we don't have one
      if (!haveTitle)
      {
         // titles only valid in yaml
         if (inYaml)
         {
            boost::smatch match;
            if (boost::regex_search(line, match, reTitle))
            {
               std::string title = match[1];
               boost::algorithm::trim(title);
               string_utils::stripQuotes(&title);
               if (title.empty())
                  title = "Untitled Slide";
               SlideNavigationItem item(title, 0, totalSlides++, 1);
               slideNavigationItems.push_back(item);
               haveTitle = true;

            }
         }
      }
      // if we already have the title look for slides
      else
      {
         // titled slides
         boost::smatch match;
         if (boost::regex_search(line, match, reTitledSlide))
         {
            std::string title = match[2];
            boost::algorithm::trim(title);
            if (title.empty())
               title = "Untitled Slide";

            int indent = std::string(match[1]).empty() ? 0 : 1;
            SlideNavigationItem item(title, indent, totalSlides++, i+1);
            slideNavigationItems.push_back(item);
         }
         // untitled slides
         else if (boost::regex_search(line, reUntitledSlide))
         {
            SlideNavigationItem item("Untitled Slide", 1, totalSlides++, i+1);
            slideNavigationItems.push_back(item);
         }
      }
   }

   // did we find slides?
   if (totalSlides > 0)
   {
      // determine which slide the cursor is on
      int previewSlide = 1;
      for (int i = (slideNavigationItems.size()-1); i>=0; i--)
      {
         const SlideNavigationItem& item = slideNavigationItems.at(i);
         if (sourceLine >= item.line)
         {
            previewSlide = item.index + 1;
            break;
         }
      }

      // return as json
      resultJson["preview_slide"] = previewSlide;
      json::Array jsonSlideNavigationItems;
      std::transform(slideNavigationItems.begin(),
                     slideNavigationItems.end(),
                     std::back_inserter(jsonSlideNavigationItems),
                     itemAsJson);
      json::Object jsonSlideNavigation;
      jsonSlideNavigation["total_slides"] = totalSlides;
      jsonSlideNavigation["items"] = jsonSlideNavigationItems;
      resultJson["slide_navigation"] = jsonSlideNavigation;
   }
}

} // namespace presentation
} // namepsace rmarkdown
} // namespace modules
} // namesapce session

<commit_msg>quiet compiler warning on gcc<commit_after>/*
 * Presentation.cpp
 *
 * Copyright (C) 2009-14 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "Presentation.hpp"

#include <boost/regex.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include <core/FileSerializer.hpp>

using namespace core;

namespace session {
namespace modules {
namespace rmarkdown {
namespace presentation {

namespace {

struct SlideNavigationItem
{
   SlideNavigationItem(const std::string& title,
                       int indent,
                       int index,
                       int line)
      : title(title), indent(indent), index(index), line(line)
   {
   }

   std::string title;
   int indent;
   int index;
   int line;
};

json::Value itemAsJson(const SlideNavigationItem& item)
{
   json::Object slideJson;
   slideJson["title"] = item.title;
   slideJson["indent"] = item.indent;
   slideJson["index"] = item.index;
   slideJson["line"] = item.line;
   return slideJson;
}

} // anonymous namespace

void ammendResults(const std::string& formatName,
                   core::FilePath& targetFile,
                   int sourceLine,
                   json::Object* pResultJson)
{
   // provide slide navigation for ioslides_presentation
   if (formatName != "ioslides_presentation")
      return;

   // alias for nicer map syntax
   json::Object& resultJson = *pResultJson;

   // read the input file
   std::vector<std::string> lines;
   Error error = core::readStringVectorFromFile(targetFile, &lines, false);
   if (error)
   {
      LOG_ERROR(error);
      return;
   }

   // scan the input file looking for headers and slide breaks
   int totalSlides = 0;
   std::vector<SlideNavigationItem> slideNavigationItems;
   bool inCode = false;
   bool inYaml = false;
   bool haveTitle = false;
   boost::regex reYaml("^\\-{3}\\s*$");
   boost::regex reTitle("^title\\:(.*)$");
   boost::regex reCode("^`{3,}.*$");
   boost::regex reTitledSlide("^#(#)?([^|\\{]+).*$");
   boost::regex reUntitledSlide("^(\\-{4,}|\\*{4,})\\w*$");
   for (unsigned i = 0; i<lines.size(); i++)
   {
      // alias line
      const std::string& line = lines.at(i);

      // toggle code state
      if (boost::regex_search(line, reCode))
         inCode = !inCode;

      // bail if we are in code
      if (inCode)
         continue;

      // toggle yaml state
      if (boost::regex_search(line, reYaml))
      {
         if (!inYaml)
         {
            inYaml = true;
         }
         else if (inYaml && !haveTitle) // no title found in first
                                        // yaml block, bail
         {
            break;
         }
      }

      // look for a title if we don't have one
      if (!haveTitle)
      {
         // titles only valid in yaml
         if (inYaml)
         {
            boost::smatch match;
            if (boost::regex_search(line, match, reTitle))
            {
               std::string title = match[1];
               boost::algorithm::trim(title);
               string_utils::stripQuotes(&title);
               if (title.empty())
                  title = "Untitled Slide";
               SlideNavigationItem item(title, 0, totalSlides++, 1);
               slideNavigationItems.push_back(item);
               haveTitle = true;

            }
         }
      }
      // if we already have the title look for slides
      else
      {
         // titled slides
         boost::smatch match;
         if (boost::regex_search(line, match, reTitledSlide))
         {
            std::string title = match[2];
            boost::algorithm::trim(title);
            if (title.empty())
               title = "Untitled Slide";

            int indent = std::string(match[1]).empty() ? 0 : 1;
            SlideNavigationItem item(title, indent, totalSlides++, i+1);
            slideNavigationItems.push_back(item);
         }
         // untitled slides
         else if (boost::regex_search(line, reUntitledSlide))
         {
            SlideNavigationItem item("Untitled Slide", 1, totalSlides++, i+1);
            slideNavigationItems.push_back(item);
         }
      }
   }

   // did we find slides?
   if (totalSlides > 0)
   {
      // determine which slide the cursor is on
      int previewSlide = 1;
      for (int i = (slideNavigationItems.size()-1); i>=0; i--)
      {
         const SlideNavigationItem& item = slideNavigationItems.at(i);
         if (sourceLine >= item.line)
         {
            previewSlide = item.index + 1;
            break;
         }
      }

      // return as json
      resultJson["preview_slide"] = previewSlide;
      json::Array jsonSlideNavigationItems;
      std::transform(slideNavigationItems.begin(),
                     slideNavigationItems.end(),
                     std::back_inserter(jsonSlideNavigationItems),
                     itemAsJson);
      json::Object jsonSlideNavigation;
      jsonSlideNavigation["total_slides"] = totalSlides;
      jsonSlideNavigation["items"] = jsonSlideNavigationItems;
      resultJson["slide_navigation"] = jsonSlideNavigation;
   }
}

} // namespace presentation
} // namepsace rmarkdown
} // namespace modules
} // namesapce session

<|endoftext|>


<commit_before>//
//  rbtree.cpp
//  rbtree
//
//  Created by Sunil on 3/22/17.
//  Copyright © 2017 Sunil. All rights reserved.
//

#include "rbtree.hpp"

#include <list>
#include <tuple>
#include <stack>
#include <queue>
#include <iostream>

using namespace std;

rbtree::rbtree() {
    root = nullptr;
}

rbtree::~rbtree() {
    remove_all(root);
}

void rbtree::remove_all(rbnode* node) {
    if (!node) {
        // no node to delete
        return;
    }

    if (node->left)
        remove_all(node->left);
    if (node->right)
        remove_all(node->right);

    delete node;
}

bool rbtree::violates(bool constraint) {
    // just negate the constraint and return
    return !constraint;
}

void rbtree::insert(int key) {
    auto node = new rbnode(key, rbcolor::black);
    if (!root) {
        // empty tree. first node to add.
        // create a black node and add it to the rbtree.
        root = node;
        return;
    }

    auto temp = root;
    rbnode* parent = nullptr;

    // add node as you would in a BST.
    while(temp) {
        parent = temp;
        if (key > temp->key)
            temp = temp->right;
        else
            temp = temp->left;
    }

    // parent shouldn't be nullptr at this point.
    node->parent = parent;
    if (key > parent->key)
        parent->right = node;
    else
        parent->left = node;

    // adding node would have disturbed the rb tree.
    // Retore the it's properties by rebalancing it.
    balance(node);
}

bool rbtree::has_only_red_black_nodes(rbnode* node) {
    if (!node) {
        // no nodes, no color.
        return false;
    }

    // use any tree traversal and check the color

    // everynode has to be red or black.
    if (!node->is_red_node() && !node->is_black_node()) {
        // this node is neither red nor black. It's a invalid rb tree.
        return false;
    }

    // node has red/black color but doesn't have left or right subtree.
    if (!node->left && !node->right) {
        return true;
    }

    // only right subtree is available.
    if (!node->left && node->right) {
        return has_only_red_black_nodes(node->right);
    }

    // only left subtree is available.
    if (!node->right && node->left) {
        return has_only_red_black_nodes(node->left);
    }

    // Both left "and" right subtree should have only red/black nodes.
    return (
        has_only_red_black_nodes(node->left) && has_only_red_black_nodes(node->right)
            );
}

bool rbtree::rednode_has_black_children(rbnode* parent) {
    if (!parent) {
        // no node, no children. Nothing to check
        return false;
    }

    // if node is red, then check it's children
    if (parent->is_red_node()) {

        // if left and right children are null treat them as black.
        if (!parent->left && !parent->right) {
            return true;
        }

        // both left and right are available.
        if ((parent->left && parent->left->is_red_node())
            || (parent->right && parent->right->is_red_node())) {
            return false;
        }

        // left child is not null. make sure its color is black
        if (parent->left && parent->left->is_red_node()) {
            // left child is not black.
            return false;
        }

        // right child is not null. make sure its color is black
        if (parent->right && parent->right->is_red_node()) {
            // right child is not black.
            return false;
        }
    }

    // only right subtree is available.
    if (!parent->left && parent->right) {
        return has_only_red_black_nodes(parent->right);
    }

    // only left subtree is available.
    if (!parent->right && parent->left) {
        return has_only_red_black_nodes(parent->left);
    }

    // Both left "and" right subtree
    return (
            has_only_red_black_nodes(parent->left) && has_only_red_black_nodes(parent->right)
            );
}

bool rbtree::has_equal_black_nodes_all_path(rbnode* parent) {
    // do a depth first search traversal and count the black nodes
    // along all path from root to leaf node.
    if (!parent) {
        // no nodes. return true or false ?
        return true;
    }
    // stack of tuple of (node, count of black nodes) pair.
    stack<tuple<rbnode*, int>> stk;
    list<int> paths;

    auto count_if_black = [](rbnode* node) {
        return (node->is_black_node() ? 1 : 0);
    };

    stk.push(make_tuple(parent, count_if_black(parent)));

    while (!stk.empty()) {
        auto pair = stk.top();
        stk.pop();

        auto node = std::get<0>(pair);
        auto count = std::get<1>(pair);

        if (node->right) {
            auto right = node->right;
            stk.push(make_tuple(right, count + count_if_black(right)));
        } else {
            // right child is null. count it as a black node.
            paths.push_front(count + 1);
        }

        if (node->left) {
            auto left = node->left;
            stk.push(make_tuple(left, count + count_if_black(left)));
        } else {
            // left child is null. count it as a black node.
            paths.push_front(count + 1);
        }
    }

    // now check if black node count on all paths are same.
    auto first = paths.front();

#if DEBUG
    for (auto count : paths) cout << count << "|";
    cout << endl;
#endif

    for (auto count : paths) {
        if (count != first)
            return false;
    }

    return true;
}

bool rbtree::is_valid_rbtree() {
    // rb tree properties:
    //  P.1: every node is red/black.
    //  P.2: root is always black.
    //  P.3: leaf nodes are black.
    //  P.4: red node should have only black children.
    //  P.5: for any node x, # of black nodes along all
    //       paths from x to leaf nodes should be the same.

    if (!root) {
        // no nodes in the tree, is a valid RB tree
        return true;
    }

    // P.1: check if all nodes are red/ black.
    if (violates(has_only_red_black_nodes(root))) {
        // some nodes are of different color. It's not a red black tree
        return false;
    }

    // P.2: If root is not black then it's invalid.
    if (violates(root->is_black_node()))
        return false;

    // P.3: I take all null nodes to be black.
    // I treat all null nodes as black. So I don't have to
    // check for black null nodes.

    // P.4: all red nodes should have black children.
    if (violates(rednode_has_black_children(root))) {
        // some/all of red nodes doesn't have a black children
        return false;
    }

    // P.5:  check #black nodes along all possible path from root
    //  to leaf nodes.
    if (violates(has_equal_black_nodes_all_path(root))) {
        // unequal number of black nodes.
        return false;
    }

    return true;
}

rbnode* rbtree::search(int key) {
    if (!root) {
        // no nodes.
        return nullptr;
    }
    auto node = root;
    while(node) {
        if (node->key == key)
            return node;
        else if (key < node->key)
            node = node->left;
        else
            node = node->right;
    }

    return nullptr;
}

void rbtree::bfs() {
    // breadth first search traversal.
    if (!root) {
        cout << "rb tree is empty" << endl;
        return;
    }

    deque<rbnode*> queue;
    queue.push_back(root);

    while(!queue.empty()) {
        auto node = queue.front();
        queue.pop_front();

        cout << node->key << endl;

        if (node->left) {
            queue.push_back(node->left);
        }

        if (node->right) {
            queue.push_back(node->right);
        }
    }

}

void rbtree::dfs() {
    // depth first search traversal.
    if (!root) {
        cout << "rb tree is empty!" << endl;
        return;
    }

    stack<rbnode*> stk;
    stk.push(root);

    while (!stk.empty()) {
        auto node = stk.top();
        stk.pop();

        cout << node->key << endl;

        if (node->right) {
            auto right = node->right;
            stk.push(right);
        }

        if (node->left) {
            auto left = node->left;
            stk.push(left);
        }
    }
}

void rbtree::prune(int min, int max) {
    throw new runtime_error("not implemented");
}

void rbtree::balance(rbnode* node) {
    throw new runtime_error("not implemented");
}

void rbtree::right_rotate(rbnode* y) {
    /*
             y                                        x
            / \        right rotate around y         / \
           x   c     ----------------------->       a   y
          / \                                          / \
         a   b                                        b   c

     */

    auto x = y->left;
    auto c = y->right;

    // get right subtree of x if available.
    // otherwise set it to nullptr.
    auto b = x ? x->right : nullptr;

    // turn x's right subtree into a y's left subtree.
    y->left = b;

    if (b) {
        b->parent = y;
    }

    // set parent of x to y's parent.
    x->parent = y->parent;

    // if y doesn't have a parent, make x as root.
    if (!y->parent) {
        root = x;
    }
    // parent is not null, see if y is to left/right of parent.
    else if (y->parent->left == y) {
        y->parent->left = x;
    }
    else {
        y->parent->right = x;
    }

    y->left = b;
    y->parent = x;
}

void rbtree::left_rotate(rbnode* x) {
    /*
            x                                          y
           / \          left rotate around x          / \
          a   y       ------------------------>      x   c
             / \                                    / \
            b   c                                  a   b
     */

    auto y = x->right;
    auto a = x->left;

    // get left subtree of y if available.
    // otherwise set it to nullptr.
    auto b = y ? y->left : nullptr;

    // no need to get c, as it stays unaffected by left rotation.

    // turn y's left subtree into a x's right subtree.
    x->right = b;
    if (b) {
        b->parent = x;
    }

    // set parent of y to x's parent.
    y->parent = x->parent;

    // if x doesn't have a parent, make y as root.
    if (!x->parent) {
        root = y;
    }
    // parent is not null, see if x is to left/right of parent.
    else if (x->parent->left == x) {
        x->parent->left = y;
    }
    else {
        x->parent->right = y;
    }

    x->left = a;
    x->parent = y;
}

void rbtree::remove(int key) {
    // TODO: after removing the node, rebalance the tree.
    throw new runtime_error("not implemented");
}
<commit_msg>bug fix for right rotation of tree<commit_after>//
//  rbtree.cpp
//  rbtree
//
//  Created by Sunil on 3/22/17.
//  Copyright © 2017 Sunil. All rights reserved.
//

#include "rbtree.hpp"

#include <list>
#include <tuple>
#include <stack>
#include <queue>
#include <iostream>

using namespace std;

rbtree::rbtree() {
    root = nullptr;
}

rbtree::~rbtree() {
    remove_all(root);
}

void rbtree::remove_all(rbnode* node) {
    if (!node) {
        // no node to delete
        return;
    }

    if (node->left)
        remove_all(node->left);
    if (node->right)
        remove_all(node->right);

    delete node;
}

bool rbtree::violates(bool constraint) {
    // just negate the constraint and return
    return !constraint;
}

void rbtree::insert(int key) {
    auto node = new rbnode(key, rbcolor::black);
    if (!root) {
        // empty tree. first node to add.
        // create a black node and add it to the rbtree.
        root = node;
        return;
    }

    auto temp = root;
    rbnode* parent = nullptr;

    // add node as you would in a BST.
    while(temp) {
        parent = temp;
        if (key > temp->key)
            temp = temp->right;
        else
            temp = temp->left;
    }

    // parent shouldn't be nullptr at this point.
    node->parent = parent;
    if (key > parent->key)
        parent->right = node;
    else
        parent->left = node;

    // adding node would have disturbed the rb tree.
    // Retore the it's properties by rebalancing it.
    balance(node);
}

bool rbtree::has_only_red_black_nodes(rbnode* node) {
    if (!node) {
        // no nodes, no color.
        return false;
    }

    // use any tree traversal and check the color

    // everynode has to be red or black.
    if (!node->is_red_node() && !node->is_black_node()) {
        // this node is neither red nor black. It's a invalid rb tree.
        return false;
    }

    // node has red/black color but doesn't have left or right subtree.
    if (!node->left && !node->right) {
        return true;
    }

    // only right subtree is available.
    if (!node->left && node->right) {
        return has_only_red_black_nodes(node->right);
    }

    // only left subtree is available.
    if (!node->right && node->left) {
        return has_only_red_black_nodes(node->left);
    }

    // Both left "and" right subtree should have only red/black nodes.
    return (
        has_only_red_black_nodes(node->left) && has_only_red_black_nodes(node->right)
            );
}

bool rbtree::rednode_has_black_children(rbnode* parent) {
    if (!parent) {
        // no node, no children. Nothing to check
        return false;
    }

    // if node is red, then check it's children
    if (parent->is_red_node()) {

        // if left and right children are null treat them as black.
        if (!parent->left && !parent->right) {
            return true;
        }

        // both left and right are available.
        if ((parent->left && parent->left->is_red_node())
            || (parent->right && parent->right->is_red_node())) {
            return false;
        }

        // left child is not null. make sure its color is black
        if (parent->left && parent->left->is_red_node()) {
            // left child is not black.
            return false;
        }

        // right child is not null. make sure its color is black
        if (parent->right && parent->right->is_red_node()) {
            // right child is not black.
            return false;
        }
    }

    // only right subtree is available.
    if (!parent->left && parent->right) {
        return has_only_red_black_nodes(parent->right);
    }

    // only left subtree is available.
    if (!parent->right && parent->left) {
        return has_only_red_black_nodes(parent->left);
    }

    // Both left "and" right subtree
    return (
            has_only_red_black_nodes(parent->left) && has_only_red_black_nodes(parent->right)
            );
}

bool rbtree::has_equal_black_nodes_all_path(rbnode* parent) {
    // do a depth first search traversal and count the black nodes
    // along all path from root to leaf node.
    if (!parent) {
        // no nodes. return true or false ?
        return true;
    }
    // stack of tuple of (node, count of black nodes) pair.
    stack<tuple<rbnode*, int>> stk;
    list<int> paths;

    auto count_if_black = [](rbnode* node) {
        return (node->is_black_node() ? 1 : 0);
    };

    stk.push(make_tuple(parent, count_if_black(parent)));

    while (!stk.empty()) {
        auto pair = stk.top();
        stk.pop();

        auto node = std::get<0>(pair);
        auto count = std::get<1>(pair);

        if (node->right) {
            auto right = node->right;
            stk.push(make_tuple(right, count + count_if_black(right)));
        } else {
            // right child is null. count it as a black node.
            paths.push_front(count + 1);
        }

        if (node->left) {
            auto left = node->left;
            stk.push(make_tuple(left, count + count_if_black(left)));
        } else {
            // left child is null. count it as a black node.
            paths.push_front(count + 1);
        }
    }

    // now check if black node count on all paths are same.
    auto first = paths.front();

#if DEBUG
    for (auto count : paths) cout << count << "|";
    cout << endl;
#endif

    for (auto count : paths) {
        if (count != first)
            return false;
    }

    return true;
}

bool rbtree::is_valid_rbtree() {
    // rb tree properties:
    //  P.1: every node is red/black.
    //  P.2: root is always black.
    //  P.3: leaf nodes are black.
    //  P.4: red node should have only black children.
    //  P.5: for any node x, # of black nodes along all
    //       paths from x to leaf nodes should be the same.

    if (!root) {
        // no nodes in the tree, is a valid RB tree
        return true;
    }

    // P.1: check if all nodes are red/ black.
    if (violates(has_only_red_black_nodes(root))) {
        // some nodes are of different color. It's not a red black tree
        return false;
    }

    // P.2: If root is not black then it's invalid.
    if (violates(root->is_black_node()))
        return false;

    // P.3: I take all null nodes to be black.
    // I treat all null nodes as black. So I don't have to
    // check for black null nodes.

    // P.4: all red nodes should have black children.
    if (violates(rednode_has_black_children(root))) {
        // some/all of red nodes doesn't have a black children
        return false;
    }

    // P.5:  check #black nodes along all possible path from root
    //  to leaf nodes.
    if (violates(has_equal_black_nodes_all_path(root))) {
        // unequal number of black nodes.
        return false;
    }

    return true;
}

rbnode* rbtree::search(int key) {
    if (!root) {
        // no nodes.
        return nullptr;
    }
    auto node = root;
    while(node) {
        if (node->key == key)
            return node;
        else if (key < node->key)
            node = node->left;
        else
            node = node->right;
    }

    return nullptr;
}

void rbtree::bfs() {
    // breadth first search traversal.
    if (!root) {
        cout << "rb tree is empty" << endl;
        return;
    }

    deque<rbnode*> queue;
    queue.push_back(root);

    while(!queue.empty()) {
        auto node = queue.front();
        queue.pop_front();

        cout << node->key << endl;

        if (node->left) {
            queue.push_back(node->left);
        }

        if (node->right) {
            queue.push_back(node->right);
        }
    }

}

void rbtree::dfs() {
    // depth first search traversal.
    if (!root) {
        cout << "rb tree is empty!" << endl;
        return;
    }

    stack<rbnode*> stk;
    stk.push(root);

    while (!stk.empty()) {
        auto node = stk.top();
        stk.pop();

        cout << node->key << endl;

        if (node->right) {
            auto right = node->right;
            stk.push(right);
        }

        if (node->left) {
            auto left = node->left;
            stk.push(left);
        }
    }
}

void rbtree::prune(int min, int max) {
    throw new runtime_error("not implemented");
}

void rbtree::balance(rbnode* node) {
    throw new runtime_error("not implemented");
}

void rbtree::right_rotate(rbnode* y) {
    /*
             y                                        x
            / \        right rotate around y         / \
           x   c     ----------------------->       a   y
          / \                                          / \
         a   b                                        b   c

     */

    auto x = y->left;

    // get right subtree of x if available.
    // otherwise set it to nullptr.
    auto b = x ? x->right : nullptr;

    // turn x's right subtree into a y's left subtree.
    y->left = b;

    if (b) {
        b->parent = y;
    }

    // set parent of x to y's parent.
    x->parent = y->parent;

    // if y doesn't have a parent, make x as root.
    if (!y->parent) {
        root = x;
    }
    // parent is not null, see if y is to left/right of parent.
    else if (y->parent->left == y) {
        y->parent->left = x;
    }
    else {
        y->parent->right = x;
    }

    x->right = y;
    y->parent = x;
}

void rbtree::left_rotate(rbnode* x) {
    /*
            x                                          y
           / \          left rotate around x          / \
          a   y       ------------------------>      x   c
             / \                                    / \
            b   c                                  a   b
     */

    auto y = x->right;

    // get left subtree of y if available.
    // otherwise set it to nullptr.
    auto b = y ? y->left : nullptr;

    // no need to get c, as it stays unaffected by left rotation.

    // turn y's left subtree into a x's right subtree.
    x->right = b;
    if (b) {
        b->parent = x;
    }

    // set parent of y to x's parent.
    y->parent = x->parent;

    // if x doesn't have a parent, make y as root.
    if (!x->parent) {
        root = y;
    }
    // parent is not null, see if x is to left/right of parent.
    else if (x->parent->left == x) {
        x->parent->left = y;
    }
    else {
        x->parent->right = y;
    }

    y->left = x;
    x->parent = y;
}

void rbtree::remove(int key) {
    // TODO: after removing the node, rebalance the tree.
    throw new runtime_error("not implemented");
}
<|endoftext|>


<commit_before>#ifdef __PX4_NUTTX

#include "gpio.h"

constexpr uint32_t CameraInterfaceGPIO::_gpios[6];

CameraInterfaceGPIO::CameraInterfaceGPIO():
	CameraInterface(),
	_polarity(0)
{
	_p_polarity = param_find("TRIG_POLARITY");
	param_get(_p_polarity, &_polarity);

	get_pins();
	setup();
}

CameraInterfaceGPIO::~CameraInterfaceGPIO()
{
}

void CameraInterfaceGPIO::setup()
{
	for (unsigned i = 0; i < arraySize(_pins); i++) {
		// Pin range is ranges from 1 to 6
		if (_pins[i] > 0 && _pins[i] < (int)arraySize(_gpios)) {
			px4_arch_configgpio(_gpios[_pins[i]]);
			px4_arch_gpiowrite(_gpios[_pins[i]], !_polarity);
		}
	}
}

void CameraInterfaceGPIO::trigger(bool enable)
{
	if (enable) {
		for (unsigned i = 0; i < arraySize(_pins); i++) {
			if (_pins[i] >= 0) {
				// ACTIVE_LOW == 1
				px4_arch_gpiowrite(_gpios[_pins[i]], _polarity);
			}
		}

	} else {
		for (unsigned i = 0; i < arraySize(_pins); i++) {
			if (_pins[i] >= 0) {
				// ACTIVE_LOW == 1
				px4_arch_gpiowrite(_gpios[_pins[i]], !_polarity);
			}
		}
	}
}

void CameraInterfaceGPIO::info()
{
	PX4_INFO("GPIO trigger mode, pins enabled : [%d][%d][%d][%d][%d][%d], polarity : %s",
		 _pins[5], _pins[4], _pins[3], _pins[2], _pins[1], _pins[0],
		 _polarity ? "ACTIVE_HIGH" : "ACTIVE_LOW");
}

#endif /* ifdef __PX4_NUTTX */
<commit_msg>fix camera_trigger gpio: _pins[i] == 0 is valid<commit_after>#ifdef __PX4_NUTTX

#include "gpio.h"

constexpr uint32_t CameraInterfaceGPIO::_gpios[6];

CameraInterfaceGPIO::CameraInterfaceGPIO():
	CameraInterface(),
	_polarity(0)
{
	_p_polarity = param_find("TRIG_POLARITY");
	param_get(_p_polarity, &_polarity);

	get_pins();
	setup();
}

CameraInterfaceGPIO::~CameraInterfaceGPIO()
{
}

void CameraInterfaceGPIO::setup()
{
	for (unsigned i = 0; i < arraySize(_pins); i++) {
		// Pin range is from 0 to 5
		if (_pins[i] >= 0 && _pins[i] < (int)arraySize(_gpios)) {
			px4_arch_configgpio(_gpios[_pins[i]]);
			px4_arch_gpiowrite(_gpios[_pins[i]], !_polarity);
		}
	}
}

void CameraInterfaceGPIO::trigger(bool enable)
{
	if (enable) {
		for (unsigned i = 0; i < arraySize(_pins); i++) {
			if (_pins[i] >= 0 && _pins[i] < (int)arraySize(_gpios)) {
				// ACTIVE_LOW == 1
				px4_arch_gpiowrite(_gpios[_pins[i]], _polarity);
			}
		}

	} else {
		for (unsigned i = 0; i < arraySize(_pins); i++) {
			if (_pins[i] >= 0 && _pins[i] < (int)arraySize(_gpios)) {
				// ACTIVE_LOW == 1
				px4_arch_gpiowrite(_gpios[_pins[i]], !_polarity);
			}
		}
	}
}

void CameraInterfaceGPIO::info()
{
	PX4_INFO("GPIO trigger mode, pins enabled : [%d][%d][%d][%d][%d][%d], polarity : %s",
		 _pins[5], _pins[4], _pins[3], _pins[2], _pins[1], _pins[0],
		 _polarity ? "ACTIVE_HIGH" : "ACTIVE_LOW");
}

#endif /* ifdef __PX4_NUTTX */
<|endoftext|>


<commit_before>#ifndef GROUP__BY__HPP
#define GROUP__BY__HPP

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret =
                decltype(std::declval<KeyFunc>()(
                            std::declval<iterator_deref<Container>>()));

            GroupBy(Container container, KeyFunc key_func)
                : container(std::forward<Container>(container)),
                key_func(key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

            class Iterator {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    const iterator_type<Container> sub_end;
                    KeyFunc key_func;

                    using KeyGroupPair =
                        std::pair<key_func_ret, Group>;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func)
                        : sub_iter{si},
                        sub_end{end},
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return KeyGroupPair(
                                this->key_func(*this->sub_iter),
                                Group(
                                    *this,
                                    this->key_func(*this->sub_iter)));
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    bool operator!=(const Iterator&) const {
                        return !this->exhausted();
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return this->sub_iter == this->sub_end;
                    }

                    iterator_deref<Container> current() const {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() const {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    mutable bool completed = false;

                    Group(Iterator& owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // movable, non-copyable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator {
                        private:
                            const key_func_ret key;
                            const Group& group;

                            bool not_at_end() const {
                                return !this->group.owner.exhausted()&&
                                    this->group.owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(const Group& group,
                                          key_func_ret key)
                                : key{key},
                                group{group}
                            { }

                            GroupIterator(const GroupIterator&) = default;

                            bool operator!=(const GroupIterator&) const {
                                if (this->not_at_end()) {
                                    return true;
                                } else {
                                    this->group.completed = true;
                                    return false;
                                }
                            }

                            GroupIterator& operator++() {
                                this->group.owner.increment_iterator();
                                return *this;
                            }

                            iterator_deref<Container> operator*() const {
                                return this->group.owner.current();
                            }
                    };

                    GroupIterator begin() {
                        return {*this, key};
                    }

                    GroupIterator end() {
                        return {*this, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            ItemReturner() = default;
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif //#ifndef GROUP__BY__HPP
<commit_msg>const correctness<commit_after>#ifndef GROUP__BY__HPP
#define GROUP__BY__HPP

#include "iterbase.hpp"

#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret =
                decltype(std::declval<KeyFunc>()(
                            std::declval<iterator_deref<Container>>()));

            GroupBy(Container container, KeyFunc key_func)
                : container(std::forward<Container>(container)),
                key_func(key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

            class Iterator {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_iter_peek;
                    const iterator_type<Container> sub_end;
                    KeyFunc key_func;

                    using KeyGroupPair =
                        std::pair<key_func_ret, Group>;

                public:
                    Iterator (iterator_type<Container> si,
                              iterator_type<Container> end,
                              KeyFunc key_func)
                        : sub_iter{si},
                        sub_end{end},
                        key_func(key_func)
                    { }

                    KeyGroupPair operator*() {
                        return KeyGroupPair(
                                this->key_func(*this->sub_iter),
                                Group(
                                    *this,
                                    this->key_func(*this->sub_iter)));
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    bool operator!=(const Iterator&) const {
                        return !this->exhausted();
                    }

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                        }
                    }

                    bool exhausted() const {
                        return this->sub_iter == this->sub_end;
                    }

                    iterator_deref<Container> current() {
                        return *this->sub_iter;
                    }

                    key_func_ret next_key() const {
                        return this->key_func(*this->sub_iter);
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    mutable bool completed = false;

                    Group(Iterator& owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // movable, non-copyable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator {
                        private:
                            const key_func_ret key;
                            const Group& group;

                            bool not_at_end() const {
                                return !this->group.owner.exhausted()&&
                                    this->group.owner.next_key() == this->key;
                            }

                        public:
                            GroupIterator(const Group& group,
                                          key_func_ret key)
                                : key{key},
                                group{group}
                            { }

                            GroupIterator(const GroupIterator&) = default;

                            bool operator!=(const GroupIterator&) const {
                                if (this->not_at_end()) {
                                    return true;
                                } else {
                                    this->group.completed = true;
                                    return false;
                                }
                            }

                            GroupIterator& operator++() {
                                this->group.owner.increment_iterator();
                                return *this;
                            }

                            iterator_deref<Container> operator*() {
                                return this->group.owner.current();
                            }
                    };

                    GroupIterator begin() {
                        return {*this, key};
                    }

                    GroupIterator end() {
                        return {*this, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            ItemReturner() = default;
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif //#ifndef GROUP__BY__HPP
<|endoftext|>


<commit_before>// This program test streaming through ports.

#include "mpi.h"
#include "vtkImageReader.h"
#include "vtkSynchronizedTemplates3D.h"
#include "vtkPolyDataCollector.h"
#include "vtkUpStreamPort.h"
#include "vtkDownStreamPort.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkMath.h"
#include "vtkDataInformation.h"

// callback to test streaming / ports by seeing what extents are being read in.
void reader_start_callback(void *arg)
{
  vtkImageReader *reader = (vtkImageReader*)(arg);
  int *e;

  e = reader->GetOutput()->GetUpdateExtent();

  cerr << "Reading: " << e[0] << ", " << e[1] << ", " << e[2] << ", "
       << e[3] << ", " << e[4] << ", " << e[5] << endl;
}

// callback to see if iso has data
void iso_end_callback(void *arg)
{
  vtkPolyData *out = (vtkPolyData*)(arg);

  cerr << "iso out: " << *out << endl;
}

// call back to exit program
// This should really be embedded in the controller.
void exit_callback(void *arg, int id)
{
  // clean up controller ?
  exit(0);
}

VTK_THREAD_RETURN_TYPE process_a( void *vtkNotUsed(arg) )
{
  vtkMultiProcessController *controller;
  vtkImageReader *reader;
  vtkSynchronizedTemplates3D *iso;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);

  reader = vtkImageReader::New();
  reader->SetDataByteOrderToLittleEndian();
  reader->SetDataExtent(0, 127, 0, 127, 1, 93);
  reader->SetFilePrefix("../../../vtkdata/headsq/half");
  reader->SetDataSpacing(1.6, 1.6, 1.5);
  reader->SetStartMethod(reader_start_callback, (void*)(reader));

  iso = vtkSynchronizedTemplates3D::New();
  iso->SetInput(reader->GetOutput());
  iso->SetValue(0, 500);
  iso->ComputeScalarsOff();
  iso->ComputeGradientsOff();
  //iso->SetEndMethod(iso_end_callback, (void*)(iso->GetOutput()));
  // This should be automatically determined by controller.
  iso->SetNumberOfThreads(1);

  // Send data throug port.
  vtkUpStreamPort *upPort = vtkUpStreamPort::New();
  upPort->SetInput(iso->GetOutput());
  upPort->SetTag(999);

  // last, set up a RMI call backs.
  controller->AddRMI(exit_callback, (void *)iso, 666);

  // wait for the call back to execute.
  upPort->WaitForUpdate();

  // last call never returns, but ...
  upPort->Delete();

  return VTK_THREAD_RETURN_VALUE;
}

VTK_THREAD_RETURN_TYPE process_b( void *vtkNotUsed(arg) )
{
  vtkMultiProcessController *controller;
  vtkDownStreamPort *downPort;
  vtkPolyDataCollector *collector = vtkPolyDataCollector::New();
  vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
  vtkActor *actor = vtkActor::New();
  vtkRenderer *ren = vtkRenderer::New();
  vtkRenderWindow *renWindow = vtkRenderWindow::New();
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  vtkCamera *cam = vtkCamera::New();
  int myid, otherid;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);
  myid = controller->GetLocalProcessId();
  otherid = ( ! myid);

  downPort = vtkDownStreamPort::New();
  downPort->SetUpStreamProcessId(otherid);
  downPort->SetTag(999);

  collector->SetInput(downPort->GetPolyDataOutput());
  collector->SetInputMemoryLimit(1000);

  mapper->SetInput(collector->GetOutput());
  actor->SetMapper(mapper);

  putenv("DISPLAY=:0.0");

  renWindow->AddRenderer(ren);
  iren->SetRenderWindow(renWindow);
  ren->SetBackground(0.9, 0.9, 0.9);
  renWindow->SetSize( 400, 400);

  // assign our actor to the renderer
  ren->AddActor(actor);

  cam->SetFocalPoint(100, 100, 65);
  cam->SetPosition(100, 450, 65);
  cam->SetViewUp(0, 0, -1);
  cam->SetViewAngle(30);
  cam->ComputeViewPlaneNormal();
  // this was causing an update.
  //ren->ResetCameraClippingRange();
  //{
  //double *range = ren->GetActiveCamera()->GetClippingRange();
  //cerr << range[0] << ", " << range[1] << endl;
  //}
  cam->SetClippingRange(177.0, 536.0);
  ren->SetActiveCamera(cam);

  collector->Update();
  collector->Update();
  cerr << "WholeMemorySize: "
       << collector->GetOutput()->GetDataInformation()->GetEstimatedWholeMemorySize()
       << endl;

  renWindow->Render();

  // just exit
  //controller->TriggerRMI(otherid, 666);
  //exit(0);

  //  Begin mouse interaction
  iren->Start();

  // Clean up
  collector->Delete();
  ren->Delete();
  renWindow->Delete();
  iren->Delete();
  mapper->Delete();
  actor->Delete();

  // clean up objects in all processes.
  controller->UnRegister(NULL);

  return VTK_THREAD_RETURN_VALUE;
}

void main( int argc, char *argv[] )
{
  vtkMultiProcessController *controller;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);

  controller->Initialize(argc, argv);
  controller->SetNumberOfProcesses(2);
  controller->SetMultipleMethod(1, process_a, NULL);
  controller->SetMultipleMethod(0, process_b, NULL);
  controller->MultipleMethodExecute();

  controller->UnRegister(NULL);
}

<commit_msg>input/output (not up/down)<commit_after>// This program test streaming through ports.

#include "mpi.h"
#include "vtkImageReader.h"
#include "vtkSynchronizedTemplates3D.h"
#include "vtkPolyDataCollector.h"
#include "vtkOutputPort.h"
#include "vtkInputPort.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkMath.h"
#include "vtkDataInformation.h"

// callback to test streaming / ports by seeing what extents are being read in.
void reader_start_callback(void *arg)
{
  vtkImageReader *reader = (vtkImageReader*)(arg);
  int *e;

  e = reader->GetOutput()->GetUpdateExtent();

  cerr << "Reading: " << e[0] << ", " << e[1] << ", " << e[2] << ", "
       << e[3] << ", " << e[4] << ", " << e[5] << endl;
}

// callback to see if iso has data
void iso_end_callback(void *arg)
{
  vtkPolyData *out = (vtkPolyData*)(arg);

  cerr << "iso out: " << *out << endl;
}

// call back to exit program
// This should really be embedded in the controller.
void exit_callback(void *arg, int id)
{
  // clean up controller ?
  exit(0);
}

VTK_THREAD_RETURN_TYPE process_a( void *vtkNotUsed(arg) )
{
  vtkMultiProcessController *controller;
  vtkImageReader *reader;
  vtkSynchronizedTemplates3D *iso;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);

  reader = vtkImageReader::New();
  reader->SetDataByteOrderToLittleEndian();
  reader->SetDataExtent(0, 127, 0, 127, 1, 93);
  reader->SetFilePrefix("../../../vtkdata/headsq/half");
  reader->SetDataSpacing(1.6, 1.6, 1.5);
  reader->SetStartMethod(reader_start_callback, (void*)(reader));

  iso = vtkSynchronizedTemplates3D::New();
  iso->SetInput(reader->GetOutput());
  iso->SetValue(0, 500);
  iso->ComputeScalarsOff();
  iso->ComputeGradientsOff();
  //iso->SetEndMethod(iso_end_callback, (void*)(iso->GetOutput()));
  // This should be automatically determined by controller.
  iso->SetNumberOfThreads(1);

  // Send data throug port.
  vtkOutputPort *upPort = vtkOutputPort::New();
  upPort->SetInput(iso->GetOutput());
  upPort->SetTag(999);

  // last, set up a RMI call backs.
  controller->AddRMI(exit_callback, (void *)iso, 666);

  // wait for the call back to execute.
  upPort->WaitForUpdate();

  // last call never returns, but ...
  upPort->Delete();

  return VTK_THREAD_RETURN_VALUE;
}

VTK_THREAD_RETURN_TYPE process_b( void *vtkNotUsed(arg) )
{
  vtkMultiProcessController *controller;
  vtkInputPort *downPort;
  vtkPolyDataCollector *collector = vtkPolyDataCollector::New();
  vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
  vtkActor *actor = vtkActor::New();
  vtkRenderer *ren = vtkRenderer::New();
  vtkRenderWindow *renWindow = vtkRenderWindow::New();
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  vtkCamera *cam = vtkCamera::New();
  int myid, otherid;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);
  myid = controller->GetLocalProcessId();
  otherid = ( ! myid);

  downPort = vtkInputPort::New();
  downPort->SetRemoteProcessId(otherid);
  downPort->SetTag(999);

  collector->SetInput(downPort->GetPolyDataOutput());
  collector->SetInputMemoryLimit(1000);

  mapper->SetInput(collector->GetOutput());
  actor->SetMapper(mapper);

  putenv("DISPLAY=:0.0");

  renWindow->AddRenderer(ren);
  iren->SetRenderWindow(renWindow);
  ren->SetBackground(0.9, 0.9, 0.9);
  renWindow->SetSize( 400, 400);

  // assign our actor to the renderer
  ren->AddActor(actor);

  cam->SetFocalPoint(100, 100, 65);
  cam->SetPosition(100, 450, 65);
  cam->SetViewUp(0, 0, -1);
  cam->SetViewAngle(30);
  cam->ComputeViewPlaneNormal();
  // this was causing an update.
  //ren->ResetCameraClippingRange();
  //{
  //double *range = ren->GetActiveCamera()->GetClippingRange();
  //cerr << range[0] << ", " << range[1] << endl;
  //}
  cam->SetClippingRange(177.0, 536.0);
  ren->SetActiveCamera(cam);

  collector->Update();
  collector->Update();
  cerr << "WholeMemorySize: "
       << collector->GetOutput()->GetDataInformation()->GetEstimatedWholeMemorySize()
       << endl;

  renWindow->Render();

  // just exit
  //controller->TriggerRMI(otherid, 666);
  //exit(0);

  //  Begin mouse interaction
  iren->Start();

  // Clean up
  collector->Delete();
  ren->Delete();
  renWindow->Delete();
  iren->Delete();
  mapper->Delete();
  actor->Delete();

  // clean up objects in all processes.
  controller->UnRegister(NULL);

  return VTK_THREAD_RETURN_VALUE;
}

void main( int argc, char *argv[] )
{
  vtkMultiProcessController *controller;

  controller = vtkMultiProcessController::RegisterAndGetGlobalController(NULL);

  controller->Initialize(argc, argv);
  controller->SetNumberOfProcesses(2);
  controller->SetMultipleMethod(1, process_a, NULL);
  controller->SetMultipleMethod(0, process_b, NULL);
  controller->MultipleMethodExecute();

  controller->UnRegister(NULL);
}

<|endoftext|>


<commit_before>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

#include "iterbase.hpp"

#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret = typename
                std::result_of<KeyFunc(iterator_deref<Container>)>::type;

            GroupBy(Container&& container, KeyFunc key_func)
                : container(std::forward<Container>(container)),
                key_func(key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

        private:
            using KeyGroupPair =
                std::pair<key_func_ret, Group>;
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, KeyGroupPair>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_end;
                    DerefHolder<iterator_deref<Container>> item;
                    KeyFunc *key_func;

                public:
                    Iterator(iterator_type<Container>&& si,
                              iterator_type<Container>&& end,
                              KeyFunc& key_func)
                        : sub_iter{std::move(si)},
                        sub_end{std::move(end)},
                        key_func(&key_func)
                    {
                        if (this->sub_iter != this->sub_end) {
                            this->item.reset(*this->sub_iter);
                        }
                    }

                    KeyGroupPair operator*() {
                        // FIXME double deref
                        return {
                            (*this->key_func)(this->item.get()),
                            Group{*this, (*this->key_func)(this->item.get())}
                        };
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

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

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                            if (this->sub_iter != this->sub_end) {
                                this->item.reset(*this->sub_iter);
                            }
                        }
                    }

                    bool exhausted() const {
                        return !(this->sub_iter != this->sub_end);
                    }

                    iterator_deref<Container> pull() {
                        return this->item.pull();
                    }

                    // FIXME double deref. Two deref holders?
                    key_func_ret next_key() {
                        return (*this->key_func)(this->item.get());
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    bool completed = false;

                    Group(Iterator& owner, key_func_ret key) :
                        owner(owner),
                        key(key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // move-constructible, non-copy-constructible,
                    // non-assignable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator
                        : public std::iterator<std::input_iterator_tag,
                                iterator_traits_deref<Container>>
                    {
                        private:
                            typename std::remove_reference<key_func_ret>::type  *key;
                            Group *group_p;

                            bool not_at_end() {
                                return !this->group_p->owner.exhausted()&&
                                    this->group_p->owner.next_key() == *this->key;
                            }

                        public:
                            GroupIterator(Group *in_group_p,
                                          key_func_ret& key)
                                : key{&key},
                                group_p{in_group_p}
                            { }

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

                            bool operator==(const GroupIterator& other) const {
                                return this->group_p == other.group_p;
                            }

                            GroupIterator& operator++() {
                                this->group_p->owner.increment_iterator();
                                if (!this->not_at_end()) {
                                    this->group_p->completed = true;
                                    this->group_p = nullptr;
                                }
                                return *this;
                            }

                            GroupIterator operator++(int) {
                                auto ret = *this;
                                ++*this;
                                return ret;
                            }

                            iterator_deref<Container> operator*() {
                                return this->group_p->owner.pull();
                            }
                    };

                    GroupIterator begin() {
                        return {this, key};
                    }

                    GroupIterator end() {
                        return {nullptr, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif
<commit_msg>eliminates shadow warnings from groupby<commit_after>#ifndef ITER_GROUP_BY_HPP_
#define ITER_GROUP_BY_HPP_

#include "iterbase.hpp"

#include <type_traits>
#include <utility>
#include <iterator>
#include <initializer_list>

namespace iter {

    template <typename Container, typename KeyFunc>
    class GroupBy;

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(Container&&, KeyFunc);

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T>, KeyFunc);

    template <typename Container, typename KeyFunc>
    class GroupBy  {
        private:
            Container container;
            KeyFunc key_func;

            friend GroupBy groupby<Container, KeyFunc>(Container&&, KeyFunc);

            template <typename T, typename KF>
            friend GroupBy<std::initializer_list<T>, KF> groupby(
                    std::initializer_list<T>, KF);

            using key_func_ret = typename
                std::result_of<KeyFunc(iterator_deref<Container>)>::type;

            GroupBy(Container&& in_container, KeyFunc in_key_func)
                : container(std::forward<Container>(in_container)),
                key_func(in_key_func)
            { }

        public:
            GroupBy() = delete;
            GroupBy(const GroupBy&) = delete;
            GroupBy& operator=(const GroupBy&) = delete;
            GroupBy& operator=(GroupBy&&) = delete;

            GroupBy(GroupBy&&) = default;

            class Iterator;
            class Group;

        private:
            using KeyGroupPair =
                std::pair<key_func_ret, Group>;
        public:

            class Iterator
                : public std::iterator<std::input_iterator_tag, KeyGroupPair>
            {
                private:
                    iterator_type<Container> sub_iter;
                    iterator_type<Container> sub_end;
                    DerefHolder<iterator_deref<Container>> item;
                    KeyFunc *key_func;

                public:
                    Iterator(iterator_type<Container>&& si,
                              iterator_type<Container>&& end,
                              KeyFunc& in_key_func)
                        : sub_iter{std::move(si)},
                        sub_end{std::move(end)},
                        key_func(&in_key_func)
                    {
                        if (this->sub_iter != this->sub_end) {
                            this->item.reset(*this->sub_iter);
                        }
                    }

                    KeyGroupPair operator*() {
                        // FIXME double deref
                        return {
                            (*this->key_func)(this->item.get()),
                            Group{*this, (*this->key_func)(this->item.get())}
                        };
                    }

                    Iterator& operator++() {
                        return *this;
                    }

                    Iterator operator++(int) {
                        auto ret = *this;
                        ++*this;
                        return ret;
                    }

                    bool operator!=(const Iterator& other) const {
                        return this->sub_iter != other.sub_iter;
                    }

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

                    void increment_iterator() {
                        if (this->sub_iter != this->sub_end) {
                            ++this->sub_iter;
                            if (this->sub_iter != this->sub_end) {
                                this->item.reset(*this->sub_iter);
                            }
                        }
                    }

                    bool exhausted() const {
                        return !(this->sub_iter != this->sub_end);
                    }

                    iterator_deref<Container> pull() {
                        return this->item.pull();
                    }

                    // FIXME double deref. Two deref holders?
                    key_func_ret next_key() {
                        return (*this->key_func)(this->item.get());
                    }
            };

            class Group {
                private:
                    friend Iterator;
                    friend class GroupIterator;
                    Iterator& owner;
                    key_func_ret key;

                    // completed is set if a Group is iterated through
                    // completely.  It is checked in the destructor, and
                    // if the Group has not been completed, the destructor
                    // exhausts it.  This ensures that the next Group starts
                    // at the correct position when the user short-circuits
                    // iteration over a Group.
                    // The move constructor sets the rvalue's completed
                    // attribute to true, so its destructor doesn't do anything
                    // when called.
                    bool completed = false;

                    Group(Iterator& in_owner, key_func_ret in_key) :
                        owner(in_owner),
                        key(in_key)
                    { }

                public:
                    ~Group() {
                        if (!this->completed) {
                            for (auto iter = this->begin(), end = this->end();
                                    iter != end;
                                    ++iter) { }
                        }
                    }

                    // move-constructible, non-copy-constructible,
                    // non-assignable
                    Group() = delete;
                    Group(const Group&) = delete;
                    Group& operator=(const Group&) = delete;
                    Group& operator=(Group&&) = delete;

                    Group(Group&& other)
                            : owner{other.owner},
                            key{other.key},
                            completed{other.completed} {
                        other.completed = true;
                    }

                    class GroupIterator
                        : public std::iterator<std::input_iterator_tag,
                                iterator_traits_deref<Container>>
                    {
                        private:
                            typename std::remove_reference<key_func_ret>::type  *key;
                            Group *group_p;

                            bool not_at_end() {
                                return !this->group_p->owner.exhausted()&&
                                    this->group_p->owner.next_key() == *this->key;
                            }

                        public:
                            GroupIterator(Group *in_group_p,
                                          key_func_ret& in_key)
                                : key{&in_key},
                                group_p{in_group_p}
                            { }

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

                            bool operator==(const GroupIterator& other) const {
                                return this->group_p == other.group_p;
                            }

                            GroupIterator& operator++() {
                                this->group_p->owner.increment_iterator();
                                if (!this->not_at_end()) {
                                    this->group_p->completed = true;
                                    this->group_p = nullptr;
                                }
                                return *this;
                            }

                            GroupIterator operator++(int) {
                                auto ret = *this;
                                ++*this;
                                return ret;
                            }

                            iterator_deref<Container> operator*() {
                                return this->group_p->owner.pull();
                            }
                    };

                    GroupIterator begin() {
                        return {this, key};
                    }

                    GroupIterator end() {
                        return {nullptr, key};
                    }

            };

            Iterator begin() {
                return {std::begin(this->container),
                        std::end(this->container),
                        this->key_func};
            }

            Iterator end() {
                return {std::end(this->container),
                        std::end(this->container),
                        this->key_func};
            }

    };

    // Takes something and returns it, used for default key of comparing
    // items in the sequence directly
    template <typename Container>
    class ItemReturner {
        public:
            iterator_deref<Container> operator() (
                    iterator_deref<Container> item) const {
                return item;
            }
    };

    template <typename Container, typename KeyFunc>
    GroupBy<Container, KeyFunc> groupby(
            Container&& container, KeyFunc key_func) {
        return {std::forward<Container>(container), key_func};
    }

    template <typename Container>
    auto groupby(Container&& container) ->
            decltype(groupby(std::forward<Container>(container),
                        ItemReturner<Container>())) {
        return groupby(std::forward<Container>(container),
                ItemReturner<Container>());
    }

    template <typename T, typename KeyFunc>
    GroupBy<std::initializer_list<T>, KeyFunc> groupby(
            std::initializer_list<T> il, KeyFunc key_func) {
        return {std::move(il), key_func};
    }

    template <typename T>
    auto groupby(std::initializer_list<T> il) ->
            decltype(groupby(std::move(il),
                        ItemReturner<std::initializer_list<T>>())) {
        return groupby(
                std::move(il),
                ItemReturner<std::initializer_list<T>>());
    }

}

#endif
<|endoftext|>