<commit_before>/*
 * Copyright (C) 2012 Kolibre
 *
 * This file is part of kolibre-naviengine.
 *
 * Kolibre-naviengine is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Kolibre-naviengine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with kolibre-naviengine. If not, see <http://www.gnu.org/licenses/>.
 */

#include "NaviEngine.h"

using namespace naviengine;

int currentSibling(const AnyNode* node)
{
    if (node->parent_->firstChild() == NULL)
    {
        return 0;
    }

    const AnyNode* tmp = node;
    int num = 1;
    while (tmp != node->parent_->firstChild() && tmp != NULL)
    {
        tmp = tmp->prev_;
        num++;
    }

    return num;
}

/**
 * Constructor
 */
NaviEngine::NaviEngine() :
        good_(false)
{
}

/**
 * Destructor
 *
 * Deletes nodes in the menu stack
 */
NaviEngine::~NaviEngine()
{
    while (not menuStack.empty())
    {
        delete menuStack.top().menuModel;
        menuStack.pop();
    }
}

/**
 * Check if the last function call was successful
 *
 * @return A boolean indicating if the last function call was successful or not
 */
bool NaviEngine::good() const
{
    return good_;
}

/**
 * Open a menu
 *
 * @param node The menu node to open
 * @param narrable If true, narrate functions are called
 * @return true on success, otherwise false
 */
bool NaviEngine::openMenu(AnyNode* node, bool narrable)
{
    if (node == 0)
        return false;

    MenuState before;

    MenuState menu;
    menu.menuModel = node;
    menu.state.currentNode = node;
    menu.state.currentChoice = node->firstChild();
    menuStack.push(menu);

    if (narrable)
    {
        if (not node->play_before_onOpen_.empty())
        {
            narrate(node->play_before_onOpen_.c_str());
        }

        good_ = node->onOpen(*this);
        narrateShortPause();
        narrateChange(before, menuStack.top());
    }

    return good_;
}

/**
 * Close a menu
 *
 * @return true on success, otherwsie false
 */
bool NaviEngine::closeMenu()
{
    if (menuStack.size() > 1)
    {
        MenuState menu = menuStack.top();
        delete menu.menuModel;
        menu.menuModel = NULL;
        menuStack.pop();

        return true; // This means the menu was closed
    }

    MenuState& menu = menuStack.top();
    menu.state.currentNode = menu.menuModel; // Fix the root menu state if someone borked it.
    menu.state.currentChoice = menu.state.currentNode->firstChild();

    return false; // No menu closed
}

/**
 * Invokes onNarrate for the current node
 *
 * If onNarrate returns false NaviEngine will render the node
 * with the help of it's virtual narrate functions
 */
void NaviEngine::narrateNode()
{
    MenuState& menu = menuStack.top();
    if (not menu.state.currentNode->onNarrate())
    {
        narrate(menu.state.currentNode->name_.c_str());
        narrate(menu.state.currentNode->info_.c_str());
        narrateShortPause();
        narrateNode(menu.state.currentChoice);
    }
}

/**
 * Invoke onNarrate for a node
 *
 * If onNarrate returns false NaviEngine will render the node
 * with the help of it's virtual narrate functions
 *
 * @param choice A pointer the to choice to narrate
 */
void NaviEngine::narrateNode(AnyNode* node)
{
    if (node == 0)
        return;

    if (not node->onNarrate())
    {
        std::string name = node->name_;
        if (name != "")
        {
            narrate(currentSibling(node));
            narrate(name.c_str());
            narrateLongPause();
        }
    }
}

/**
 * Invoke onRender for a node
 *
 * @param node A pointer the the node to render
 * @return The result from the onRender invoke
 */
bool NaviEngine::renderNode(AnyNode* node)
{
    if (node == NULL)
        return false;

    bool selfRendered = node->onRender();
    return not selfRendered;
}

/**
 * Go to the root (top) node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::top()
{
    MenuState menu = menuStack.top();

    // If already on top level, open the menu
    if (menu.state.currentNode == menu.menuModel)
    {
        narrate(menuStack.top().state.currentNode->play_before_onOpen_.c_str());
        narrateShortPause();
        menuStack.top().state.currentNode->onOpen(*this);
    }

    // If not on top level, go to top level
    while (menuStack.size() > 1 || menu.state.currentNode != menu.menuModel)
    {
        narrateStop();
        up();
        menu = menuStack.top();
    }
    return true;
}

/**
 * Check if state has changed
 *
 * @param before The MenuState before
 * @return true is state has changed, otherwise false
 */
bool NaviEngine::stateHasChanged(const MenuState& before)
{
    MenuState& now = menuStack.top();

    if (now.state.currentNode != before.state.currentNode)
    {
        return true;
    }
    return false;
}

/**
 * Open the current node by invoking onOpen on a state change
 *
 * @param before The MenuState before
 * @return the result from onOpen if the state has changed, otherwise false
 */
bool NaviEngine::openOnChange(const MenuState& before)
{
    MenuState& now = menuStack.top();
    if (now.state.currentNode == NULL)
        closeMenu();

    now = menuStack.top();
    { // Check if the node has changed

        if (now.state.currentNode != before.state.currentNode)
        {
            narrate(now.state.currentNode->play_before_onOpen_.c_str());
            narrateShortPause();
            good_ = now.state.currentNode->onOpen(*this);
            narrateChange(before, now);
            return good_;
        }
    }
    return false;
}

/**
 * Go to the parent node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::up()
{
    bool success = false;
    MenuState before = menuStack.top();
    success = menuStack.top().state.currentNode->up(*this);

    if (stateHasChanged(before))
        return openOnChange(before);
    return openOnChange(before);
}

/**
 * Open the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::select()
{
    bool success = false;
    MenuState before = menuStack.top();
    success = menuStack.top().state.currentNode->select(*this);

    if (stateHasChanged(before))
        return openOnChange(before);
    return openOnChange(before);
}

/**
 * Open the child referenced by uri
 *
 * @param uri The uri of the child
 * @return true on success, otherwise false
 */
bool NaviEngine::selectNodeByUri(std::string uri)
{
    bool success = false;
    MenuState before = menuStack.top();
    AnyNode* currentNode = menuStack.top().state.currentNode;

    if (currentNode->isVirtual())
    {
        success = currentNode->selectByUri(*this, uri);
    }
    else
    {
        AnyNode* currentChild = currentNode->firstChild();
        if (currentChild != NULL)
        {
            do
            {
                if (uri == currentChild->uri_)
                {
                    menuStack.top().state.currentChoice = currentChild;
                    success = currentNode->select(*this);
                    break;
                }
                currentChild = currentChild->next_;
            } while (currentChild != currentNode->firstChild() && currentChild != NULL);
        }
    }

    if (stateHasChanged(before))
        return openOnChange(before);
    return success;
}

/**
 * Go to the next child and set it as the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::next()
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;
    if (menu.state.currentNode->next(*this))
    {
        narrateChange(before, menu);
        return true;
    }
    return false;
}

/**
 * Go to the previous child and set it as the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::prev()
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;
    if (menu.state.currentNode->prev(*this))
    {
        narrateChange(before, menu);
        return true;
    }
    return false;
}

/**
 * Open the context menu for the current node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::openContextMenu()
{
    MenuState& menu = menuStack.top();
    return menu.state.currentNode->menu(*this);
}

/**
 * Let the current node process the command
 *
 * @param command The enumerated command the node shall process
 * @data data A pointer to a optional data object
 * @return The result of the process operation
 */
bool NaviEngine::process(int command, void* data)
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;

    bool processedCommand = true;

    if (not menu.state.currentNode->process(*this, command, data))
    { // This is a short of time hack.
        processedCommand = false;
    }

    { // Check if the node has changed during process
        MenuState& menu = menuStack.top();

        if (menu.state.currentNode != before.state.currentNode)
        {
            if (menu.state.currentNode == NULL)
            {
                closeMenu();
            }

            MenuState& menu = menuStack.top();
            narrate(menu.state.currentNode->play_before_onOpen_.c_str());
            narrateShortPause();
            good_ = menu.state.currentNode->onOpen(*this);
            // Consider a successful node change to mean that the command was processed.
            if (good_)
                processedCommand = true;
        }
    }

    MenuState& after = menuStack.top();
    narrateChange(before, after);

    return processedCommand;
}

/**
 * Get the number of children for a node
 *
 * @param node A pointer to the node for which to get the number of children
 * @return A positive value if the node has children, otherwise 0
 */
int NaviEngine::numberOfChildren(AnyNode* node)
{
    if (node == NULL || node->firstChild() == NULL)
    {
        return 0;
    }

    const AnyNode* tmp = node->firstChild();
    int num = 0;
    do
    {
        tmp = tmp->next_;
        num++;
    } while (tmp != node->firstChild() && tmp != NULL);

    return num;
}

/**
 * Get the current node
 *
 * @return A pointer to the current node
 */
AnyNode* NaviEngine::getCurrentNode()
{
    return menuStack.top().state.currentNode;
}

/**
 * Set the current node
 *
 * @param node A pointer to the node which shell become the current node
 */
void NaviEngine::setCurrentNode(AnyNode* node)
{
    menuStack.top().state.currentNode = node;
}

/**
 * Get the current choice
 *
 * @return A pointer to the current choice
 */
AnyNode* NaviEngine::getCurrentChoice()
{
    return menuStack.top().state.currentChoice;
}

/**
 * Set the current choice
 *
 * @param node A pointer to the node which shall become the current choice
 */
void NaviEngine::setCurrentChoice(AnyNode* node)
{
    menuStack.top().state.currentChoice = node;
}
<commit_msg>Fix unclear use of openOnChange<commit_after>/*
 * Copyright (C) 2012 Kolibre
 *
 * This file is part of kolibre-naviengine.
 *
 * Kolibre-naviengine is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Kolibre-naviengine is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with kolibre-naviengine. If not, see <http://www.gnu.org/licenses/>.
 */

#include "NaviEngine.h"

using namespace naviengine;

int currentSibling(const AnyNode* node)
{
    if (node->parent_->firstChild() == NULL)
    {
        return 0;
    }

    const AnyNode* tmp = node;
    int num = 1;
    while (tmp != node->parent_->firstChild() && tmp != NULL)
    {
        tmp = tmp->prev_;
        num++;
    }

    return num;
}

/**
 * Constructor
 */
NaviEngine::NaviEngine() :
        good_(false)
{
}

/**
 * Destructor
 *
 * Deletes nodes in the menu stack
 */
NaviEngine::~NaviEngine()
{
    while (not menuStack.empty())
    {
        delete menuStack.top().menuModel;
        menuStack.pop();
    }
}

/**
 * Check if the last function call was successful
 *
 * @return A boolean indicating if the last function call was successful or not
 */
bool NaviEngine::good() const
{
    return good_;
}

/**
 * Open a menu
 *
 * @param node The menu node to open
 * @param narrable If true, narrate functions are called
 * @return true on success, otherwise false
 */
bool NaviEngine::openMenu(AnyNode* node, bool narrable)
{
    if (node == 0)
        return false;

    MenuState before;

    MenuState menu;
    menu.menuModel = node;
    menu.state.currentNode = node;
    menu.state.currentChoice = node->firstChild();
    menuStack.push(menu);

    if (narrable)
    {
        if (not node->play_before_onOpen_.empty())
        {
            narrate(node->play_before_onOpen_.c_str());
        }

        good_ = node->onOpen(*this);
        narrateShortPause();
        narrateChange(before, menuStack.top());
    }

    return good_;
}

/**
 * Close a menu
 *
 * @return true on success, otherwsie false
 */
bool NaviEngine::closeMenu()
{
    if (menuStack.size() > 1)
    {
        MenuState menu = menuStack.top();
        delete menu.menuModel;
        menu.menuModel = NULL;
        menuStack.pop();

        return true; // This means the menu was closed
    }

    MenuState& menu = menuStack.top();
    menu.state.currentNode = menu.menuModel; // Fix the root menu state if someone borked it.
    menu.state.currentChoice = menu.state.currentNode->firstChild();

    return false; // No menu closed
}

/**
 * Invokes onNarrate for the current node
 *
 * If onNarrate returns false NaviEngine will render the node
 * with the help of it's virtual narrate functions
 */
void NaviEngine::narrateNode()
{
    MenuState& menu = menuStack.top();
    if (not menu.state.currentNode->onNarrate())
    {
        narrate(menu.state.currentNode->name_.c_str());
        narrate(menu.state.currentNode->info_.c_str());
        narrateShortPause();
        narrateNode(menu.state.currentChoice);
    }
}

/**
 * Invoke onNarrate for a node
 *
 * If onNarrate returns false NaviEngine will render the node
 * with the help of it's virtual narrate functions
 *
 * @param choice A pointer the to choice to narrate
 */
void NaviEngine::narrateNode(AnyNode* node)
{
    if (node == 0)
        return;

    if (not node->onNarrate())
    {
        std::string name = node->name_;
        if (name != "")
        {
            narrate(currentSibling(node));
            narrate(name.c_str());
            narrateLongPause();
        }
    }
}

/**
 * Invoke onRender for a node
 *
 * @param node A pointer the the node to render
 * @return The result from the onRender invoke
 */
bool NaviEngine::renderNode(AnyNode* node)
{
    if (node == NULL)
        return false;

    bool selfRendered = node->onRender();
    return not selfRendered;
}

/**
 * Go to the root (top) node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::top()
{
    MenuState menu = menuStack.top();

    // If already on top level, open the menu
    if (menu.state.currentNode == menu.menuModel)
    {
        narrate(menuStack.top().state.currentNode->play_before_onOpen_.c_str());
        narrateShortPause();
        menuStack.top().state.currentNode->onOpen(*this);
    }

    // If not on top level, go to top level
    while (menuStack.size() > 1 || menu.state.currentNode != menu.menuModel)
    {
        narrateStop();
        up();
        menu = menuStack.top();
    }
    return true;
}

/**
 * Check if state has changed
 *
 * @param before The MenuState before
 * @return true is state has changed, otherwise false
 */
bool NaviEngine::stateHasChanged(const MenuState& before)
{
    MenuState& now = menuStack.top();

    if (now.state.currentNode != before.state.currentNode)
    {
        return true;
    }
    return false;
}

/**
 * Open the current node by invoking onOpen on a state change
 *
 * @param before The MenuState before
 * @return the result from onOpen if the state has changed, otherwise false
 */
bool NaviEngine::openOnChange(const MenuState& before)
{
    MenuState& now = menuStack.top();
    if (now.state.currentNode == NULL)
        closeMenu();

    if (stateHasChanged(before))
    {
        now = menuStack.top();
        narrate(now.state.currentNode->play_before_onOpen_.c_str());
        narrateShortPause();
        good_ = now.state.currentNode->onOpen(*this);
        narrateChange(before, now);
        return good_;
    }
    return false;
}

/**
 * Go to the parent node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::up()
{
    bool success = false;
    MenuState before = menuStack.top();
    success = menuStack.top().state.currentNode->up(*this);

    return openOnChange(before);
}

/**
 * Open the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::select()
{
    bool success = false;
    MenuState before = menuStack.top();
    success = menuStack.top().state.currentNode->select(*this);

    return openOnChange(before);
}

/**
 * Open the child referenced by uri
 *
 * @param uri The uri of the child
 * @return true on success, otherwise false
 */
bool NaviEngine::selectNodeByUri(std::string uri)
{
    bool success = false;
    MenuState before = menuStack.top();
    AnyNode* currentNode = menuStack.top().state.currentNode;

    if (currentNode->isVirtual())
    {
        success = currentNode->selectByUri(*this, uri);
    }
    else
    {
        AnyNode* currentChild = currentNode->firstChild();
        if (currentChild != NULL)
        {
            do
            {
                if (uri == currentChild->uri_)
                {
                    menuStack.top().state.currentChoice = currentChild;
                    success = currentNode->select(*this);
                    break;
                }
                currentChild = currentChild->next_;
            } while (currentChild != currentNode->firstChild() && currentChild != NULL);
        }
    }

    if (stateHasChanged(before))
        return openOnChange(before);
    return success;
}

/**
 * Go to the next child and set it as the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::next()
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;
    if (menu.state.currentNode->next(*this))
    {
        narrateChange(before, menu);
        return true;
    }
    return false;
}

/**
 * Go to the previous child and set it as the currently selected child
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::prev()
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;
    if (menu.state.currentNode->prev(*this))
    {
        narrateChange(before, menu);
        return true;
    }
    return false;
}

/**
 * Open the context menu for the current node
 *
 * @return true on success, otherwise false
 */
bool NaviEngine::openContextMenu()
{
    MenuState& menu = menuStack.top();
    return menu.state.currentNode->menu(*this);
}

/**
 * Let the current node process the command
 *
 * @param command The enumerated command the node shall process
 * @data data A pointer to a optional data object
 * @return The result of the process operation
 */
bool NaviEngine::process(int command, void* data)
{
    MenuState& menu = menuStack.top();
    MenuState before = menu;

    bool processedCommand = true;

    if (not menu.state.currentNode->process(*this, command, data))
    { // This is a short of time hack.
        processedCommand = false;
    }

    { // Check if the node has changed during process
        MenuState& menu = menuStack.top();

        if (menu.state.currentNode != before.state.currentNode)
        {
            if (menu.state.currentNode == NULL)
            {
                closeMenu();
            }

            MenuState& menu = menuStack.top();
            narrate(menu.state.currentNode->play_before_onOpen_.c_str());
            narrateShortPause();
            good_ = menu.state.currentNode->onOpen(*this);
            // Consider a successful node change to mean that the command was processed.
            if (good_)
                processedCommand = true;
        }
    }

    MenuState& after = menuStack.top();
    narrateChange(before, after);

    return processedCommand;
}

/**
 * Get the number of children for a node
 *
 * @param node A pointer to the node for which to get the number of children
 * @return A positive value if the node has children, otherwise 0
 */
int NaviEngine::numberOfChildren(AnyNode* node)
{
    if (node == NULL || node->firstChild() == NULL)
    {
        return 0;
    }

    const AnyNode* tmp = node->firstChild();
    int num = 0;
    do
    {
        tmp = tmp->next_;
        num++;
    } while (tmp != node->firstChild() && tmp != NULL);

    return num;
}

/**
 * Get the current node
 *
 * @return A pointer to the current node
 */
AnyNode* NaviEngine::getCurrentNode()
{
    return menuStack.top().state.currentNode;
}

/**
 * Set the current node
 *
 * @param node A pointer to the node which shell become the current node
 */
void NaviEngine::setCurrentNode(AnyNode* node)
{
    menuStack.top().state.currentNode = node;
}

/**
 * Get the current choice
 *
 * @return A pointer to the current choice
 */
AnyNode* NaviEngine::getCurrentChoice()
{
    return menuStack.top().state.currentChoice;
}

/**
 * Set the current choice
 *
 * @param node A pointer to the node which shall become the current choice
 */
void NaviEngine::setCurrentChoice(AnyNode* node)
{
    menuStack.top().state.currentChoice = node;
}
<|endoftext|>


<commit_before>/**
 * @file Cosa/DS18B20.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Driver for the DS18B20 Programmable Resolution 1-Write
 * Digital Thermometer.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/DS18B20.h"

bool
DS18B20::convert_request()
{
  if (!_pin->reset()) return (0);
  _pin->write(OneWire::SKIP_ROM);
  _pin->write(CONVERT_T);
  return (1);
}

bool
DS18B20::read_scratchpad()
{
  if (!_pin->reset()) return (0);
  _pin->write(OneWire::SKIP_ROM);
  _pin->write(READ_SCRATCHPAD);
  _pin->begin();
  for (uint8_t i = 0; i < SCRATCHPAD_MAX; i++) {
    _scratchpad[i] = _pin->read();
  }
  return (_pin->end() == 0);
}

void
DS18B20::print_scratchpad(IOStream& stream)
{
  for (uint8_t i = 0; i < SCRATCHPAD_MAX; i++) {
    stream.printf_P(PSTR("scratchpad[%d] = %hd\n"), i, _scratchpad[i]);
  }
}

int16_t
DS18B20::get_temperature()
{
  int16_t temp = (_scratchpad[1] << 8) | _scratchpad[0];
  return (temp);
}

void
DS18B20::get(temperature_t& res)
{
  int16_t temp = ((int16_t*) _scratchpad)[0];
  int16_t numerator = temp >> 4;
  if (temp < 0) temp = -temp;
  uint16_t denominator = 0;
  uint16_t fraction = 625;
  for (uint8_t i = 0; i < 4; i++) {
    if (temp & 1) denominator += fraction;
    fraction <<= 1;
    temp >>= 1;
  }
  if (denominator < 1000 && denominator > 500) denominator = 1000;
  res.numerator = numerator;
  res.denominator = denominator;
}

<commit_msg>Improved sample access in DS18B20 sample in scratchpad memory.<commit_after>/**
 * @file Cosa/DS18B20.cpp
 * @version 1.0
 *
 * @section License
 * Copyright (C) 2012, Mikael Patel
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA  02111-1307  USA
 *
 * @section Description
 * Driver for the DS18B20 Programmable Resolution 1-Write
 * Digital Thermometer.
 *
 * This file is part of the Arduino Che Cosa project.
 */

#include "Cosa/DS18B20.h"

bool
DS18B20::convert_request()
{
  if (!_pin->reset()) return (0);
  _pin->write(OneWire::SKIP_ROM);
  _pin->write(CONVERT_T);
  return (1);
}

bool
DS18B20::read_scratchpad()
{
  if (!_pin->reset()) return (0);
  _pin->write(OneWire::SKIP_ROM);
  _pin->write(READ_SCRATCHPAD);
  _pin->begin();
  for (uint8_t i = 0; i < SCRATCHPAD_MAX; i++) {
    _scratchpad[i] = _pin->read();
  }
  return (_pin->end() == 0);
}

void
DS18B20::print_scratchpad(IOStream& stream)
{
  for (uint8_t i = 0; i < SCRATCHPAD_MAX; i++) {
    stream.printf_P(PSTR("scratchpad[%d] = %hd\n"), i, _scratchpad[i]);
  }
}

int16_t
DS18B20::get_temperature()
{
  return (((int16_t*) _scratchpad)[0]);
}

void
DS18B20::get(temperature_t& res)
{
  int16_t temp = ((int16_t*) _scratchpad)[0];
  int16_t numerator = temp >> 4;
  if (temp < 0) temp = -temp;
  uint16_t denominator = 0;
  uint16_t fraction = 625;
  for (uint8_t i = 0; i < 4; i++) {
    if (temp & 1) denominator += fraction;
    fraction <<= 1;
    temp >>= 1;
  }
  if (denominator < 1000 && denominator > 500) denominator = 1000;
  res.numerator = numerator;
  res.denominator = denominator;
}

<|endoftext|>


<commit_before>#ifndef ANY_HPP
# define ANY_HPP
# pragma once

#include <cassert>

#include <cstdint>

#include <stdexcept>

#include <typeinfo>

#include <type_traits>

#include <utility>

namespace generic
{

class any
{
  using typeid_t = ::std::uintptr_t;

  template <typename T>
  static typeid_t type_id()
  {
    return typeid_t(&type_id<T>);
  }

public:
  any() = default;

  any(any const& other) :
    content(other.content ? other.content->clone() : nullptr)
  {
  }

  any(any&& other) noexcept { *this = ::std::move(other); }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<any, typename ::std::decay<ValueType>::type>::value
    >::type
  >
  any(ValueType&& value) :
    content(new holder<typename ::std::decay<ValueType>::type>(
      ::std::forward<ValueType>(value)))
  {
  }

  ~any() { delete content; }

public: // modifiers
  void clear() noexcept { swap(any()); }

  void swap(any& other) noexcept { ::std::swap(content, other.content); }

  void swap(any&& other) noexcept { ::std::swap(content, other.content); }

  any& operator=(any const& rhs) { return *this = any(rhs); }

  any& operator=(any&& rhs) noexcept
  {
    content = rhs.content;
    rhs.content = nullptr;

    return *this;
  }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<any, typename ::std::decay<ValueType>::type>{}
    >::type
  >
  any& operator=(ValueType&& rhs)
  {
    return *this = any(::std::forward<ValueType>(rhs));
  }

public: // queries

  explicit operator bool() const noexcept { return content; }

  typeid_t type() const noexcept
  {
    return content ? content->type() : type_id<void>();
  }

private: // types

  struct placeholder
  {
    placeholder() = default;

    virtual ~placeholder() = default;

    virtual placeholder* clone() const = 0;

    virtual typeid_t type() const = 0;
  };

  template <typename ValueType, typename = void>
  struct holder : public placeholder
  {
  public: // constructor
    template <class T> holder(T&& value) :
      held(::std::forward<T>(value))
    {
    }

    holder& operator=(holder const&) = delete;

    placeholder* clone() const final { throw ::std::logic_error(""); }

  public: // queries
    typeid_t type() const noexcept final
    {
      return type_id<ValueType>();
    }

  public:
    ValueType held;
  };

  template <typename ValueType>
  struct holder<
    ValueType,
    typename ::std::enable_if<
      ::std::is_copy_constructible<ValueType>::value
    >::type
  > : public placeholder
  {
  public: // constructor
    template <class T>
    holder(T&& value) :
      held(::std::forward<T>(value))
    {
    }

    placeholder* clone() const final { return new holder<ValueType>(held); }

  public: // queries
    typeid_t type() const noexcept final
    {
      return type_id<ValueType>();
    }

  public:
    ValueType held;
  };

private: // representation

  template<typename ValueType>
  friend ValueType* any_cast(any*) noexcept;

  template<typename ValueType>
  friend ValueType* unsafe_any_cast(any*) noexcept;

  placeholder* content{};
};

template<typename ValueType>
inline ValueType* unsafe_any_cast(any* const operand) noexcept
{
  return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}

template<typename ValueType>
inline ValueType const* unsafe_any_cast(any const* const operand) noexcept
{
  return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType* any_cast(any* const operand) noexcept
{
  return operand && (operand->type() ==
    any::type_id<typename ::std::decay<ValueType>::type>()) ?
    &static_cast<any::holder<ValueType>*>(operand->content)->held :
    nullptr;
}

template<typename ValueType>
inline ValueType const* any_cast(any const* const operand) noexcept
{
  return any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType any_cast(any& operand)
{
  using nonref = typename ::std::remove_reference<ValueType>::type;

#ifndef NDEBUG
  auto const result(any_cast<nonref>(&operand));

  if (!result)
  {
    throw ::std::bad_cast();
  }
  // else do nothing

  return *result;
#else
  return *unsafe_any_cast<nonref>(&operand);
#endif // NDEBUG
}

template<typename ValueType>
inline ValueType any_cast(any const& operand)
{
  using nonref = typename ::std::remove_reference<ValueType>::type;

  return any_cast<nonref const&>(const_cast<any&>(operand));
}

}

#endif // ANY_HPP
<commit_msg>some fixes<commit_after>#ifndef ANY_HPP
# define ANY_HPP
# pragma once

#include <cassert>

#include <cstdint>

#include <stdexcept>

#include <typeinfo>

#include <type_traits>

#include <utility>

namespace generic
{

class any
{
  using typeid_t = ::std::uintptr_t;

  template <typename T>
  constexpr static typeid_t type_id()
  {
    return typeid_t(type_id<T>);
  }

public:
  any() = default;

  any(any const& other) :
    content(other.content ? other.content->clone() : nullptr)
  {
  }

  any(any&& other) noexcept { *this = ::std::move(other); }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<any, typename ::std::decay<ValueType>::type>::value
    >::type
  >
  any(ValueType&& value) :
    content(new holder<typename ::std::decay<ValueType>::type>(
      ::std::forward<ValueType>(value)))
  {
  }

  ~any() { delete content; }

public: // modifiers
  void clear() noexcept { swap(any()); }

  void swap(any& other) noexcept { ::std::swap(content, other.content); }

  void swap(any&& other) noexcept { ::std::swap(content, other.content); }

  any& operator=(any const& rhs) { return *this = any(rhs); }

  any& operator=(any&& rhs) noexcept
  {
    content = rhs.content;
    rhs.content = nullptr;

    return *this;
  }

  template<typename ValueType,
    typename = typename ::std::enable_if<
      !::std::is_same<any, typename ::std::decay<ValueType>::type>{}
    >::type
  >
  any& operator=(ValueType&& rhs)
  {
    return *this = any(::std::forward<ValueType>(rhs));
  }

public: // queries

  explicit operator bool() const noexcept { return content; }

  typeid_t type() const noexcept
  {
    return content ? content->type() : type_id<void>();
  }

private: // types

  struct placeholder
  {
    placeholder() = default;

    virtual ~placeholder() = default;

    virtual placeholder* clone() const = 0;

    virtual typeid_t type() const = 0;
  };

  template <typename ValueType, typename = void>
  struct holder : public placeholder
  {
  public: // constructor
    template <class T> holder(T&& value) :
      held(::std::forward<T>(value))
    {
    }

    holder& operator=(holder const&) = delete;

    placeholder* clone() const final { throw ::std::logic_error(""); }

  public: // queries
    typeid_t type() const noexcept final
    {
      return type_id<ValueType>();
    }

  public:
    ValueType held;
  };

  template <typename ValueType>
  struct holder<
    ValueType,
    typename ::std::enable_if<
      ::std::is_copy_constructible<ValueType>::value
    >::type
  > : public placeholder
  {
  public: // constructor
    template <class T>
    holder(T&& value) :
      held(::std::forward<T>(value))
    {
    }

    placeholder* clone() const final { return new holder<ValueType>(held); }

  public: // queries
    typeid_t type() const noexcept final
    {
      return type_id<ValueType>();
    }

  public:
    ValueType held;
  };

private: // representation

  template<typename ValueType>
  friend ValueType* any_cast(any*) noexcept;

  template<typename ValueType>
  friend ValueType* unsafe_any_cast(any*) noexcept;

  placeholder* content{};
};

template<typename ValueType>
inline ValueType* unsafe_any_cast(any* const operand) noexcept
{
  return &static_cast<any::holder<ValueType>*>(operand->content)->held;
}

template<typename ValueType>
inline ValueType const* unsafe_any_cast(any const* const operand) noexcept
{
  return unsafe_any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType* any_cast(any* const operand) noexcept
{
  return operand && (operand->type() ==
    any::type_id<typename ::std::decay<ValueType>::type>()) ?
    &static_cast<any::holder<ValueType>*>(operand->content)->held :
    nullptr;
}

template<typename ValueType>
inline ValueType const* any_cast(any const* const operand) noexcept
{
  return any_cast<ValueType>(const_cast<any*>(operand));
}

template<typename ValueType>
inline ValueType any_cast(any& operand)
{
  using nonref = typename ::std::remove_reference<ValueType>::type;

#ifndef NDEBUG
  auto const result(any_cast<nonref>(&operand));

  if (!result)
  {
    throw ::std::bad_cast();
  }
  // else do nothing

  return *result;
#else
  return *unsafe_any_cast<nonref>(&operand);
#endif // NDEBUG
}

template<typename ValueType>
inline ValueType any_cast(any const& operand)
{
  using nonref = typename ::std::remove_reference<ValueType>::type;

  return any_cast<nonref const&>(const_cast<any&>(operand));
}

}

#endif // ANY_HPP
<|endoftext|>


<commit_before>/************************************************************************/
/*                                                                      */
/*       Copyright 2009 by Ullrich Koethe and Hans Meine                */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#define PY_ARRAY_UNIQUE_SYMBOL vigranumpycore_PyArray_API
#define NO_IMPORT_ARRAY

#include <vigra/numpy_array.hxx>
#include <vigra/numpy_array_converters.hxx>
#include <boost/python.hpp>
#include <boost/python/to_python_converter.hpp>

namespace python = boost::python;

namespace vigra {

#define VIGRA_NUMPY_TYPECHECKER(type) \
    if(python::object((python::detail::new_reference)PyArray_TypeObjectFromType(type)).ptr() == obj) \
        return obj;

#define VIGRA_NUMPY_TYPECONVERTER(type) \
    if(python::object((python::detail::new_reference)PyArray_TypeObjectFromType(type)).ptr() == obj) \
        typeID = type;

struct NumpyTypenumConverter
{
    NumpyTypenumConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<NPY_TYPES>());
        python::to_python_converter<NPY_TYPES, NumpyTypenumConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        // FIXME: there should be a more elegant way to program this...
        if(obj == 0)
            return 0;
        if(obj->ob_type == &PyArrayDescr_Type)
            return obj;
        if(!PyType_Check(obj))
            return 0;
        VIGRA_NUMPY_TYPECHECKER(NPY_BOOL)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT8)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT8)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT16)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT16)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_FLOAT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_FLOAT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_LONGDOUBLE)
        VIGRA_NUMPY_TYPECHECKER(NPY_CFLOAT)
        VIGRA_NUMPY_TYPECHECKER(NPY_CDOUBLE)
        VIGRA_NUMPY_TYPECHECKER(NPY_CLONGDOUBLE)
        return 0;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<NumpyAnyArray>* ) data)->storage.bytes;

        // FIXME: there should be a more elegant way to program this...
        int typeID = -1;
        if(obj->ob_type == &PyArrayDescr_Type)
            typeID = (NPY_TYPES)((PyArray_Descr*)obj)->type_num;
        VIGRA_NUMPY_TYPECONVERTER(NPY_BOOL)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT8)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT8)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT16)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT16)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_FLOAT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_FLOAT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_LONGDOUBLE)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CFLOAT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CDOUBLE)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CLONGDOUBLE)

        new (storage) NPY_TYPES((NPY_TYPES)typeID);

        data->convertible = storage;
    }

    // to Python
    static PyObject* convert(NPY_TYPES typeID)
    {
        return PyArray_TypeObjectFromType(typeID);
    }
};

#undef VIGRA_NUMPY_TYPECHECKER
#undef VIGRA_NUMPY_TYPECONVERTER

struct NumpyAnyArrayConverter
{
    NumpyAnyArrayConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<NumpyAnyArray>());
        python::to_python_converter<NumpyAnyArray, NumpyAnyArrayConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        return obj && (obj == Py_None || PyArray_Check(obj))
                 ? obj
                 : 0;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<NumpyAnyArray>* ) data)->storage.bytes;

        if(obj == Py_None)
            obj = 0;

        new (storage) NumpyAnyArray(obj);

        data->convertible = storage;
    }

    static PyObject* convert(NumpyAnyArray const& a)
    {
        return returnNumpyArray(a);
    }
};

namespace detail {

template <int N, class T>
struct MultiArrayShapeConverterTraits
{
    typedef TinyVector<T, N> ShapeType;

    static void construct(void* const storage, PyObject * obj)
    {
        ShapeType * shape = new (storage) ShapeType();
        for(int i=0; i<PySequence_Length(obj); ++i)
            (*shape)[i] = python::extract<T>(PySequence_ITEM(obj, i));
    }
};

template <class T>
struct MultiArrayShapeConverterTraits<0, T>
{
    typedef ArrayVector<T> ShapeType;

    static void construct(void* const storage, PyObject * obj)
    {
        int len = (obj == Py_None)
                           ? 0
                           : PySequence_Length(obj);
        ShapeType * shape = new (storage) ShapeType(len);
        for(int i=0; i<len; ++i)
            (*shape)[i] = python::extract<T>(PySequence_ITEM(obj, i));
    }
};

} // namespace detail

template <int M, class T>
struct MultiArrayShapeConverter
{

    typedef typename detail::MultiArrayShapeConverterTraits<M, T>::ShapeType ShapeType;

    MultiArrayShapeConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<ShapeType>());
        python::to_python_converter<ShapeType, MultiArrayShapeConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        if(obj == 0)
            return 0;
        if(M == 0 && obj == Py_None)
            return obj;
        if(!PySequence_Check(obj) || (M != 0 && PySequence_Length(obj) != M))
            return 0;
        for(int i=0; i<PySequence_Length(obj); ++i)
            if(!PyNumber_Check(PySequence_ITEM(obj, i)))
                return 0;
        return obj;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<ShapeType>* ) data)->storage.bytes;

        detail::MultiArrayShapeConverterTraits<M, T>::construct(storage, obj);
        data->convertible = storage;
    }

    // to Python
    static PyObject* convert(ShapeType const& shape)
    {
        return shapeToPythonTuple(shape).release();
    }
};

python_ptr point2DToPythonTuple(Point2D const & point)
{
    python_ptr tuple(PyTuple_New(2), python_ptr::keep_count);
    pythonToCppException(tuple);
    PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), 0 ,pythonFromData(point.x).release());
    PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), 1 ,pythonFromData(point.y).release());
    return tuple;
}

struct Point2DConverter
{
    Point2DConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<Point2D>());
        python::to_python_converter<Point2D, Point2DConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        if(obj == 0 || !PySequence_Check(obj) || (PySequence_Length(obj) !=2))
            return 0;
        if(!PyNumber_Check(PySequence_Fast_GET_ITEM(obj,0)))
            return 0;
        if(!PyNumber_Check(PySequence_Fast_GET_ITEM(obj,0)))
            return 0;
        return obj;
    }

    //from python
    static void construct(PyObject* obj, python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<Point2D>*) data)->storage.bytes;
        new (storage) Point2D(python::extract<int>(PySequence_Fast_GET_ITEM(obj,0)),
                              python::extract<int>(PySequence_Fast_GET_ITEM(obj,1)));
        data->convertible = storage;
    }

    //to python
    static PyObject* convert(Point2D const& p)
    {
        return point2DToPythonTuple(p).release();
    }

};

void registerNumpyPoint2DConverter()
{
    Point2DConverter();
}

template <class T>
void registerNumpyShapeConvertersOneType()
{
    MultiArrayShapeConverter<0, T>();
    MultiArrayShapeConverter<1, T>();
    MultiArrayShapeConverter<2, T>();
    MultiArrayShapeConverter<3, T>();
    MultiArrayShapeConverter<4, T>();
    MultiArrayShapeConverter<5, T>();
}

void registerNumpyShapeConvertersAllTypes()
{
    registerNumpyShapeConvertersOneType<MultiArrayIndex>();
    registerNumpyShapeConvertersOneType<float>();
    registerNumpyShapeConvertersOneType<double>();
    if(typeid(npy_intp) != typeid(MultiArrayIndex))
        MultiArrayShapeConverter<0, npy_intp>();
}

#if 0 // FIXME: reimplement to replace the Python versions for consistence?
PyObject *
constructNumpyArrayFromShape(python::object type, ArrayVector<npy_intp> const & shape,
                       unsigned int spatialDimensions, unsigned int channels,
                       NPY_TYPES typeCode, std::string order, bool init)
{
    PyObject * obj = type.ptr();
    vigra_precondition(obj && PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, &PyArray_Type),
           "constructNumpyArray(type, ...): first argument was not an array type.");
    return detail::constructNumpyArrayImpl((PyTypeObject *)obj, shape, spatialDimensions, channels, typeCode, order, init).release();
}

PyObject *
constructNumpyArrayFromArray(python::object type, NumpyAnyArray array,
                       unsigned int spatialDimensions, unsigned int channels,
                       NPY_TYPES typeCode, std::string order, bool init)
{
    PyObject * obj = type.ptr();
    vigra_precondition(obj && PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, &PyArray_Type),
           "constructNumpyArray(type, ...): first argument was not an array type.");
    PyObject * res = detail::constructNumpyArrayImpl((PyTypeObject *)obj, array.shape(), spatialDimensions, channels,
                                                     typeCode, order, false, array.strideOrdering()).release();
    if(init)
    {
        NumpyAnyArray lhs(res);
        lhs = array;
    }
    return res;
}
#endif

PyObject *
constructArrayFromAxistags(python::object type, ArrayVector<npy_intp> const & shape,
                           NPY_TYPES typeCode, AxisTags const & axistags, bool init)
{
    PyAxisTags pyaxistags(python_ptr(python::object(axistags).ptr()));

    ArrayVector<npy_intp> norm_shape(shape);
    if(pyaxistags.size() > 0)
    {
        ArrayVector<npy_intp> permutation(pyaxistags.permutationToNormalOrder());
        applyPermutation(permutation.begin(), permutation.end(), shape.begin(), norm_shape.begin());
    }

    TaggedShape tagged_shape(norm_shape, pyaxistags);
    // FIXME: check that type is an array class?
    return constructArray(tagged_shape, typeCode, init, python_ptr(type.ptr()));
}

void registerNumpyArrayConverters()
{
    NumpyTypenumConverter();
    registerNumpyShapeConvertersAllTypes();
    registerNumpyPoint2DConverter();
    NumpyAnyArrayConverter();

    python::docstring_options doc_options(true, true, false);

    doc_options.disable_all();
    python::def("constructArrayFromAxistags", &constructArrayFromAxistags);
    // python::def("constructNumpyArray", &constructNumpyArrayFromArray);
}

} // namespace vigra

<commit_msg>added #include Python.h<commit_after>/************************************************************************/
/*                                                                      */
/*       Copyright 2009 by Ullrich Koethe and Hans Meine                */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    The VIGRA Website is                                              */
/*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#define PY_ARRAY_UNIQUE_SYMBOL vigranumpycore_PyArray_API
#define NO_IMPORT_ARRAY

#include <Python.h>
#include <vigra/numpy_array.hxx>
#include <vigra/numpy_array_converters.hxx>
#include <boost/python.hpp>
#include <boost/python/to_python_converter.hpp>

namespace python = boost::python;

namespace vigra {

#define VIGRA_NUMPY_TYPECHECKER(type) \
    if(python::object((python::detail::new_reference)PyArray_TypeObjectFromType(type)).ptr() == obj) \
        return obj;

#define VIGRA_NUMPY_TYPECONVERTER(type) \
    if(python::object((python::detail::new_reference)PyArray_TypeObjectFromType(type)).ptr() == obj) \
        typeID = type;

struct NumpyTypenumConverter
{
    NumpyTypenumConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<NPY_TYPES>());
        python::to_python_converter<NPY_TYPES, NumpyTypenumConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        // FIXME: there should be a more elegant way to program this...
        if(obj == 0)
            return 0;
        if(obj->ob_type == &PyArrayDescr_Type)
            return obj;
        if(!PyType_Check(obj))
            return 0;
        VIGRA_NUMPY_TYPECHECKER(NPY_BOOL)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT8)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT8)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT16)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT16)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT)
        VIGRA_NUMPY_TYPECHECKER(NPY_INT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_UINT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_FLOAT32)
        VIGRA_NUMPY_TYPECHECKER(NPY_FLOAT64)
        VIGRA_NUMPY_TYPECHECKER(NPY_LONGDOUBLE)
        VIGRA_NUMPY_TYPECHECKER(NPY_CFLOAT)
        VIGRA_NUMPY_TYPECHECKER(NPY_CDOUBLE)
        VIGRA_NUMPY_TYPECHECKER(NPY_CLONGDOUBLE)
        return 0;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<NumpyAnyArray>* ) data)->storage.bytes;

        // FIXME: there should be a more elegant way to program this...
        int typeID = -1;
        if(obj->ob_type == &PyArrayDescr_Type)
            typeID = (NPY_TYPES)((PyArray_Descr*)obj)->type_num;
        VIGRA_NUMPY_TYPECONVERTER(NPY_BOOL)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT8)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT8)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT16)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT16)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_INT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_UINT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_FLOAT32)
        VIGRA_NUMPY_TYPECONVERTER(NPY_FLOAT64)
        VIGRA_NUMPY_TYPECONVERTER(NPY_LONGDOUBLE)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CFLOAT)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CDOUBLE)
        VIGRA_NUMPY_TYPECONVERTER(NPY_CLONGDOUBLE)

        new (storage) NPY_TYPES((NPY_TYPES)typeID);

        data->convertible = storage;
    }

    // to Python
    static PyObject* convert(NPY_TYPES typeID)
    {
        return PyArray_TypeObjectFromType(typeID);
    }
};

#undef VIGRA_NUMPY_TYPECHECKER
#undef VIGRA_NUMPY_TYPECONVERTER

struct NumpyAnyArrayConverter
{
    NumpyAnyArrayConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<NumpyAnyArray>());
        python::to_python_converter<NumpyAnyArray, NumpyAnyArrayConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        return obj && (obj == Py_None || PyArray_Check(obj))
                 ? obj
                 : 0;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<NumpyAnyArray>* ) data)->storage.bytes;

        if(obj == Py_None)
            obj = 0;

        new (storage) NumpyAnyArray(obj);

        data->convertible = storage;
    }

    static PyObject* convert(NumpyAnyArray const& a)
    {
        return returnNumpyArray(a);
    }
};

namespace detail {

template <int N, class T>
struct MultiArrayShapeConverterTraits
{
    typedef TinyVector<T, N> ShapeType;

    static void construct(void* const storage, PyObject * obj)
    {
        ShapeType * shape = new (storage) ShapeType();
        for(int i=0; i<PySequence_Length(obj); ++i)
            (*shape)[i] = python::extract<T>(PySequence_ITEM(obj, i));
    }
};

template <class T>
struct MultiArrayShapeConverterTraits<0, T>
{
    typedef ArrayVector<T> ShapeType;

    static void construct(void* const storage, PyObject * obj)
    {
        int len = (obj == Py_None)
                           ? 0
                           : PySequence_Length(obj);
        ShapeType * shape = new (storage) ShapeType(len);
        for(int i=0; i<len; ++i)
            (*shape)[i] = python::extract<T>(PySequence_ITEM(obj, i));
    }
};

} // namespace detail

template <int M, class T>
struct MultiArrayShapeConverter
{

    typedef typename detail::MultiArrayShapeConverterTraits<M, T>::ShapeType ShapeType;

    MultiArrayShapeConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<ShapeType>());
        python::to_python_converter<ShapeType, MultiArrayShapeConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        if(obj == 0)
            return 0;
        if(M == 0 && obj == Py_None)
            return obj;
        if(!PySequence_Check(obj) || (M != 0 && PySequence_Length(obj) != M))
            return 0;
        for(int i=0; i<PySequence_Length(obj); ++i)
            if(!PyNumber_Check(PySequence_ITEM(obj, i)))
                return 0;
        return obj;
    }

    // from Python
    static void construct(PyObject* obj,
        python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<ShapeType>* ) data)->storage.bytes;

        detail::MultiArrayShapeConverterTraits<M, T>::construct(storage, obj);
        data->convertible = storage;
    }

    // to Python
    static PyObject* convert(ShapeType const& shape)
    {
        return shapeToPythonTuple(shape).release();
    }
};

python_ptr point2DToPythonTuple(Point2D const & point)
{
    python_ptr tuple(PyTuple_New(2), python_ptr::keep_count);
    pythonToCppException(tuple);
    PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), 0 ,pythonFromData(point.x).release());
    PyTuple_SET_ITEM((PyTupleObject *)tuple.get(), 1 ,pythonFromData(point.y).release());
    return tuple;
}

struct Point2DConverter
{
    Point2DConverter()
    {
        python::converter::registry::insert(&convertible, &construct,
                                            python::type_id<Point2D>());
        python::to_python_converter<Point2D, Point2DConverter>();
    }

    static void* convertible(PyObject* obj)
    {
        if(obj == 0 || !PySequence_Check(obj) || (PySequence_Length(obj) !=2))
            return 0;
        if(!PyNumber_Check(PySequence_Fast_GET_ITEM(obj,0)))
            return 0;
        if(!PyNumber_Check(PySequence_Fast_GET_ITEM(obj,0)))
            return 0;
        return obj;
    }

    //from python
    static void construct(PyObject* obj, python::converter::rvalue_from_python_stage1_data* data)
    {
        void* const storage =
            ((python::converter::rvalue_from_python_storage<Point2D>*) data)->storage.bytes;
        new (storage) Point2D(python::extract<int>(PySequence_Fast_GET_ITEM(obj,0)),
                              python::extract<int>(PySequence_Fast_GET_ITEM(obj,1)));
        data->convertible = storage;
    }

    //to python
    static PyObject* convert(Point2D const& p)
    {
        return point2DToPythonTuple(p).release();
    }

};

void registerNumpyPoint2DConverter()
{
    Point2DConverter();
}

template <class T>
void registerNumpyShapeConvertersOneType()
{
    MultiArrayShapeConverter<0, T>();
    MultiArrayShapeConverter<1, T>();
    MultiArrayShapeConverter<2, T>();
    MultiArrayShapeConverter<3, T>();
    MultiArrayShapeConverter<4, T>();
    MultiArrayShapeConverter<5, T>();
}

void registerNumpyShapeConvertersAllTypes()
{
    registerNumpyShapeConvertersOneType<MultiArrayIndex>();
    registerNumpyShapeConvertersOneType<float>();
    registerNumpyShapeConvertersOneType<double>();
    if(typeid(npy_intp) != typeid(MultiArrayIndex))
        MultiArrayShapeConverter<0, npy_intp>();
}

#if 0 // FIXME: reimplement to replace the Python versions for consistence?
PyObject *
constructNumpyArrayFromShape(python::object type, ArrayVector<npy_intp> const & shape,
                       unsigned int spatialDimensions, unsigned int channels,
                       NPY_TYPES typeCode, std::string order, bool init)
{
    PyObject * obj = type.ptr();
    vigra_precondition(obj && PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, &PyArray_Type),
           "constructNumpyArray(type, ...): first argument was not an array type.");
    return detail::constructNumpyArrayImpl((PyTypeObject *)obj, shape, spatialDimensions, channels, typeCode, order, init).release();
}

PyObject *
constructNumpyArrayFromArray(python::object type, NumpyAnyArray array,
                       unsigned int spatialDimensions, unsigned int channels,
                       NPY_TYPES typeCode, std::string order, bool init)
{
    PyObject * obj = type.ptr();
    vigra_precondition(obj && PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, &PyArray_Type),
           "constructNumpyArray(type, ...): first argument was not an array type.");
    PyObject * res = detail::constructNumpyArrayImpl((PyTypeObject *)obj, array.shape(), spatialDimensions, channels,
                                                     typeCode, order, false, array.strideOrdering()).release();
    if(init)
    {
        NumpyAnyArray lhs(res);
        lhs = array;
    }
    return res;
}
#endif

PyObject *
constructArrayFromAxistags(python::object type, ArrayVector<npy_intp> const & shape,
                           NPY_TYPES typeCode, AxisTags const & axistags, bool init)
{
    PyAxisTags pyaxistags(python_ptr(python::object(axistags).ptr()));

    ArrayVector<npy_intp> norm_shape(shape);
    if(pyaxistags.size() > 0)
    {
        ArrayVector<npy_intp> permutation(pyaxistags.permutationToNormalOrder());
        applyPermutation(permutation.begin(), permutation.end(), shape.begin(), norm_shape.begin());
    }

    TaggedShape tagged_shape(norm_shape, pyaxistags);
    // FIXME: check that type is an array class?
    return constructArray(tagged_shape, typeCode, init, python_ptr(type.ptr()));
}

void registerNumpyArrayConverters()
{
    NumpyTypenumConverter();
    registerNumpyShapeConvertersAllTypes();
    registerNumpyPoint2DConverter();
    NumpyAnyArrayConverter();

    python::docstring_options doc_options(true, true, false);

    doc_options.disable_all();
    python::def("constructArrayFromAxistags", &constructArrayFromAxistags);
    // python::def("constructNumpyArray", &constructNumpyArrayFromArray);
}

} // namespace vigra

<|endoftext|>


<commit_before>//=================================================================================================
//                    Copyright (C) 2017 Olivier Mallet - All Rights Reserved
//=================================================================================================

#ifndef POPULATION_HPP
#define POPULATION_HPP

namespace galgo {

//=================================================================================================

template <typename T, int...N>
class Population
{
   static_assert(std::is_same<float,T>::value || std::is_same<double,T>::value, "variable type can only be float or double, please amend.");

public:
   // nullary constructor
   Population() {}
   // constructor
   Population(const GeneticAlgorithm<T,N...>& ga);
   // create a population of chromosomes
   void creation();
   // evolve population, get next generation
   void evolution();

   // access element in current population at position pos
   const CHR<T,N...>& operator()(int pos) const;
   // access element in mating population at position pos
   const CHR<T,N...>& operator[](int pos) const;
   // return iterator to current population beginning
   typename std::vector<CHR<T,N...>>::iterator begin();
   // return const iterator to current population beginning
   typename std::vector<CHR<T,N...>>::const_iterator cbegin() const;
   // return iterator to current population ending
   typename std::vector<CHR<T,N...>>::iterator end();
   // return const iterator to current population ending
   typename std::vector<CHR<T,N...>>::const_iterator cend() const;
   // select element at position pos in current population and copy it into mating population
   void select(int pos);
   // set all fitness to positive values
   void adjustFitness();
   // compute fitness sum of current population
   T getSumFitness() const;
   // get worst objective function total result from current population
   T getWorstTotal() const;
   // return population size
   int popsize() const;
   // return mating population size
   int matsize() const;
   // return tournament size
   int tntsize() const;
   // return numero of generation
   int nogen() const;
   // return number of generations
   int nbgen() const;
   // return selection pressure
   T SP() const;

private:
   std::vector<CHR<T,N...>> curpop;               // current population
   std::vector<CHR<T,N...>> matpop;               // mating population
   std::vector<CHR<T,N...>> newpop;               // new population

   const GeneticAlgorithm<T,N...>* ptr = nullptr; // pointer to genetic algorithm
   int nbrcrov;                                   // number of cross-over
   int matidx;                                    // mating population index

   // elitism => saving best chromosomes in new population
   void elitism();
   // create new population from recombination of the old one
   void recombination();
   // complete new population randomly
   void completion();
   // update population (adapting, sorting)
   void updating();
};

/*-------------------------------------------------------------------------------------------------*/

// constructor
template <typename T, int...N>
Population<T,N...>::Population(const GeneticAlgorithm<T,N...>& ga)
{
   ptr = &ga;
   nbrcrov = floor(ga.covrate * (ga.popsize - ga.elitpop));
   // adjusting nbrcrov (must be an even number)
   if (nbrcrov % 2 != 0) nbrcrov -= 1;
   // for convenience, we add elitpop to nbrcrov
   nbrcrov += ga.elitpop;
   // allocating memory
   curpop.resize(ga.popsize);
   matpop.resize(ga.matsize);
}

/*-------------------------------------------------------------------------------------------------*/

// create a population of chromosomes
template <typename T, int...N>
void Population<T,N...>::creation()
{
   int start = 0;
   // initializing first chromosome
   if (!ptr->initialSet.empty()) {
      curpop[0] = std::make_shared<Chromosome<T,N...>>(*ptr);
      curpop[0]->initialize();
      curpop[0]->evaluate();
      start++;
   }
   // getting the rest
   #ifdef _OPENMP
   #pragma omp parallel for num_threads(MAX_THREADS)
   #endif
   for (int i = start; i < ptr->popsize; ++i) {
      curpop[i] = std::make_shared<Chromosome<T,N...>>(*ptr);
      curpop[i]->create();
      curpop[i]->evaluate();
   }
   // updating population
   this->updating();
}

/*-------------------------------------------------------------------------------------------------*/

// population evolution (selection, recombination, completion, mutation), get next generation
template <typename T, int...N>
void Population<T,N...>::evolution()
{
   // initializing mating population index
   matidx = 0;
   // selecting mating population
   ptr->Selection(*this);
   // applying elitism if required
   this->elitism();
   // crossing-over mating population
   this->recombination();
   // completing new population
   this->completion();
   // moving new population into current population for next generation
   curpop = std::move(newpop);
   // updating population
   this->updating();
}

/*-------------------------------------------------------------------------------------------------*/

// elitism => saving best chromosomes in new population, making a copy of each elit chromosome
template <typename T, int...N>
void Population<T,N...>::elitism()
{
   // (re)allocating new population
   newpop.resize(ptr->popsize);

   if (ptr->elitpop > 0) {
      // copying elit chromosomes into new population
      std::transform(curpop.cbegin(), curpop.cend(), newpop.begin(), [](const CHR<T,N...>& chr)->CHR<T,N...>{return std::make_shared<Chromosome<T,N...>>(*chr);});
   }
}

/*-------------------------------------------------------------------------------------------------*/

// create new population from recombination of the old one
template <typename T, int...N>
void Population<T,N...>::recombination()
{
   // creating a new population by cross-over
   #ifdef _OPENMP
   #pragma omp parallel for num_threads(MAX_THREADS)
   #endif
   for (int i = ptr->elitpop; i < nbrcrov; i = i + 2) {
      // initializing 2 new chromosome
      newpop[i] = std::make_shared<Chromosome<T,N...>>(*ptr);
      newpop[i+1] = std::make_shared<Chromosome<T,N...>>(*ptr);
      // crossing-over mating population to create 2 new chromosomes
      ptr->CrossOver(*this, newpop[i], newpop[i+1]);
      // mutating new chromosomes
      ptr->Mutation(newpop[i]);
      ptr->Mutation(newpop[i+1]);
      // evaluating new chromosomes
      newpop[i]->evaluate();
      newpop[i+1]->evaluate();
   }
}

/*-------------------------------------------------------------------------------------------------*/

// complete new population
template <typename T, int...N>
void Population<T,N...>::completion()
{
   #ifdef _OPENMP
   #pragma omp parallel for num_threads(MAX_THREADS)
   #endif
   for (int i = nbrcrov; i < ptr->popsize; ++i) {
      // selecting chromosome randomly from mating population
      newpop[i] = std::make_shared<Chromosome<T,N...>>(*matpop[uniform<int>(0, ptr->matsize)]);
      // mutating chromosome
      ptr->Mutation(newpop[i]);
      // evaluating chromosome
      newpop[i]->evaluate();
   }
}

/*-------------------------------------------------------------------------------------------------*/

// update population (adapting, sorting)
template <typename T, int...N>
void Population<T,N...>::updating()
{
   // adapting population to constraints
   if (ptr->Constraint != nullptr) {
      ptr->Adaptation(*this);
   }
   // sorting chromosomes from best to worst fitness
   std::sort(curpop.begin(),curpop.end(),[](const CHR<T,N...>& chr1,const CHR<T,N...>& chr2)->bool{return chr1->fitness > chr2->fitness;});
}

/*-------------------------------------------------------------------------------------------------*/

// access element in current population at position pos
template <typename T, int...N>
const CHR<T,N...>& Population<T,N...>::operator()(int pos) const
{
   #ifndef NDEBUG
   if (pos > ptr->popsize - 1) {
      throw std::invalid_argument("Error: in galgo::Population<T>::operator()(int), exceeding current population memory.");
   }
   #endif

   return curpop[pos];
}

/*-------------------------------------------------------------------------------------------------*/

// access element in mating population at position pos
template <typename T, int...N>
const CHR<T,N...>& Population<T,N...>::operator[](int pos) const
{
   #ifndef NDEBUG
   if (pos > ptr->matsize - 1) {
      throw std::invalid_argument("Error: in galgo::Population<T>::operator[](int), exceeding mating population memory.");
   }
   #endif

   return matpop[pos];
}

/*-------------------------------------------------------------------------------------------------*/

// return iterator to current population beginning
template <typename T, int...N>
inline typename std::vector<CHR<T,N...>>::iterator Population<T,N...>::begin()
{
   return curpop.begin();
}

/*-------------------------------------------------------------------------------------------------*/

// return const iterator to current population beginning
template <typename T, int...N>
inline typename std::vector<CHR<T,N...>>::const_iterator Population<T,N...>::cbegin() const
{
   return curpop.cbegin();
}

/*-------------------------------------------------------------------------------------------------*/

// return iterator to current population ending
template <typename T, int...N>
inline typename std::vector<CHR<T,N...>>::iterator Population<T,N...>::end()
{
   return curpop.end();
}

/*-------------------------------------------------------------------------------------------------*/

// return const iterator to current population ending
template <typename T, int...N>
inline typename std::vector<CHR<T,N...>>::const_iterator Population<T,N...>::cend() const
{
   return curpop.cend();
}

/*-------------------------------------------------------------------------------------------------*/

// select element at position pos in current population and copy it into mating population
template <typename T, int...N>
inline void Population<T,N...>::select(int pos)
{
   #ifndef NDEBUG
   if (pos > ptr->popsize - 1) {
      throw std::out_of_range("Error: in galgo::Population<T>::select(int), exceeding current population memory.");
   }
   if (matidx == ptr->matsize) {
      throw std::out_of_range("Error: in galgo::Population<T>::select(int), exceeding mating population memory.");
   }
   #endif

   matpop[matidx] = curpop[pos];
   matidx++;
}

/*-------------------------------------------------------------------------------------------------*/

// set all fitness to positive values (used in RWS and SUS selection methods)
template <typename T, int...N>
void Population<T,N...>::adjustFitness()
{
   // getting worst population fitness
   T worstFitness = curpop.back()->fitness;

   if (worstFitness < 0) {
      // getting best fitness
      T bestFitness = curpop.front()->fitness;
      // case where all fitness are equal and negative
      if (worstFitness == bestFitness) {
         std::for_each(curpop.begin(), curpop.end(), [](CHR<T,N...>& chr)->void{chr->fitness *= -1;});
       } else {
         std::for_each(curpop.begin(), curpop.end(), [worstFitness](CHR<T,N...>& chr)->void{chr->fitness -= worstFitness;});
      }
   }
}

/*-------------------------------------------------------------------------------------------------*/

// compute population fitness sum (used in TRS, RWS and SUS selection methods)
template <typename T, int...N>
inline T Population<T,N...>::getSumFitness() const
{
   return std::accumulate(curpop.cbegin(), curpop.cend(), 0.0, [](T sum, const CHR<T,N...>& chr)->T{return sum + T(chr->fitness);});
}

/*-------------------------------------------------------------------------------------------------*/

// get worst objective function total result from current population (used in constraint(s) adaptation)
template <typename T, int...N>
inline T Population<T,N...>::getWorstTotal() const
{
   auto it = std::min_element(curpop.begin(), curpop.end(), [](const CHR<T,N...>& chr1, const CHR<T,N...>& chr2)->bool{return chr1->getTotal() < chr2->getTotal();});

   return (*it)->getTotal();
}

/*-------------------------------------------------------------------------------------------------*/

// return population size
template <typename T, int...N>
inline int Population<T,N...>::popsize() const
{
   return ptr->popsize;
}

/*-------------------------------------------------------------------------------------------------*/

// return mating population size
template <typename T, int...N>
inline int Population<T,N...>::matsize() const
{
   return ptr->matsize;
}

/*-------------------------------------------------------------------------------------------------*/

// return tournament size
template <typename T, int...N>
inline int Population<T,N...>::tntsize() const
{
   return ptr->tntsize;
}

/*-------------------------------------------------------------------------------------------------*/

// return numero of generation
template <typename T, int...N>
inline int Population<T,N...>::nogen() const
{
   return ptr->nogen;
}

/*-------------------------------------------------------------------------------------------------*/

// return number of generations
template <typename T, int...N>
inline int Population<T,N...>::nbgen() const
{
   return ptr->nbgen;
}

/*-------------------------------------------------------------------------------------------------*/

// return selection pressure
template <typename T, int...N>
inline T Population<T,N...>::SP() const
{
   return ptr->SP;
}

//=================================================================================================

}

#endif

<commit_msg>Delete Population.hpp<commit_after><|endoftext|>


<commit_before>//--------------------------------------------------------------- SudokuGrid.cpp

#include "SudokuGrid.h"
#include "SetOperations.h"

#include <numeric>
#include <stdexcept>
#include <string>

using namespace std;

namespace {
const string subhorz(13, '-');
const string subhorz2(13, ' ');
const string horz = "+" + subhorz + "+" + subhorz + "+" + subhorz + "+";
const string horz2 = "|" + subhorz2 + "|" + subhorz2 + "|" + subhorz2 + "|";
const string vert(11, '|');
} // namespace

const SudokuGrid::set_t SudokuGrid::EMPTY;
const SudokuGrid::set_t SudokuGrid::U{
   makeRange<SudokuGrid::value_t>(1, SudokuGrid::ORDER2 + 1)};

ostream &operator<<(ostream &os, const SudokuGrid &sdkg)
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if ((col != 0) && (col % SudokuGrid::ORDER == 0)) {
            os << "|";
         }
         if (!sdkg.cellIsSolved(row, col)) {
            os << " . ";
         }
         else {
            os << " " << sdkg._cell[row][col] << " ";
         }
      }
      os << endl;
      if ((row != SudokuGrid::ORDER2 - 1) &&
          (row % SudokuGrid::ORDER == (SudokuGrid::ORDER - 1))) {
         // @TODO Remove magic number
         os << string(29, '-') << endl;
      }
   }
   os << endl;

   return os;
}

std::istream &operator>>(std::istream &is, SudokuGrid &sdkg)
{
   int value{0};

   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         is >> value;
         sdkg.add(value, row, col);
      }
   }
   sdkg.calculateAllCellCandidates();
   return is;
}

void writeCandidates(std::ostream &os, const SudokuGrid &sdkg)
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0 && row % SudokuGrid::ORDER == 0 &&
             row < SudokuGrid::ORDER2 - 1) {
            os << horz;
            if (row == 0) {
               os << " ID = " << &sdkg << " " << sdkg.getID() << " "
                  << (sdkg.isSolvable() ? "" : " not solvable");
            }
            os << endl << horz2 << endl;
         }
         if (col == 0)
            os << "| ";
         SudokuGrid::set_t candidates = sdkg.getCellCandidates(row, col);
         for (SudokuGrid::value_t v = 1; v <= SudokuGrid::ORDER; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               candidates == SudokuGrid::EMPTY ? os << ' ' : os << '.';
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl;
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0)
            os << "| ";
         int pos{-1};
         SudokuGrid::set_t candidates{sdkg.getCellCandidates(row, col)};
         for (SudokuGrid::value_t v = SudokuGrid::ORDER + 1;
              v <= 2 * SudokuGrid::ORDER; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               if (candidates == SudokuGrid::EMPTY) {
                  ++pos;
                  (pos == 1) ? os << sdkg._cell[row][col] : os << ' ';
               }
               else {
                  os << '.';
               }
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl;
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0)
            os << "| ";
         SudokuGrid::set_t candidates{sdkg.getCellCandidates(row, col)};
         for (SudokuGrid::value_t v = 2 * SudokuGrid::ORDER + 1;
              v < 3 * SudokuGrid::ORDER + 1; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               candidates == SudokuGrid::EMPTY ? os << ' ' : os << '.';
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl << horz2 << endl;
   }
   os << horz << endl;
}

void writeLatex(std::ostream &os, const SudokuGrid &sdkg)
{
   os << "\n\\begin{sudoku}\n";
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (!sdkg.cellIsSolved(row, col)) {
            os << "| ";
         }
         else {
            os << "|" << sdkg._cell[row][col];
         }
      }
      os << "|.\n";
   }
   os << "\\end{sudoku}\n\n";
}

SudokuGrid::SudokuGrid()
   : _id{}
   , _numberOfCellsSolved{0}
   , _isSolvable{true}
   , _cell{{}}
   , _columnSet{{}}
   , _rowSet{{}}
   , _blockSet{{}}
   , _candidates{{}}
   , pRow{}
   , pColumn{}
   , pBlock{}
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int column = 0; column < SudokuGrid::ORDER2; ++column) {
         _candidates[row][column] = U;
      }
   }
   _columnSet.fill(U);
   _rowSet.fill(U);
   for (int row = 0; row < SudokuGrid::ORDER; ++row) {
      for (int column = 0; column < SudokuGrid::ORDER; ++column) {
         _blockSet[row][column] = U;
      }
   }
   mapPointerArraysToCandidates();
}

SudokuGrid::SudokuGrid(const SudokuGrid &sdkg)
   : _id{sdkg._id}
   , _numberOfCellsSolved{sdkg._numberOfCellsSolved}
   , _isSolvable{sdkg._isSolvable}
   , _cell{{}}
   , _columnSet{{}}
   , _rowSet{{}}
   , _blockSet{{}}
   , _candidates{{}}
   , pRow{}
   , pColumn{}
   , pBlock{}
{
   _cell = sdkg._cell;
   _columnSet = sdkg._columnSet;
   _rowSet = sdkg._rowSet;
   _blockSet = sdkg._blockSet;
   _candidates = sdkg._candidates;
   mapPointerArraysToCandidates();
   // writeCandidates(cout, sdkg);
   // cout << "COPY" << endl;
   // writeCandidates(cout, *this);
}

SudokuGrid &SudokuGrid::operator=(const SudokuGrid &sdkg)
{
   if (this != &sdkg) {
      _id = sdkg._id;
      _numberOfCellsSolved = sdkg._numberOfCellsSolved;
      _isSolvable = sdkg._isSolvable;
      _cell = sdkg._cell;
      _columnSet = sdkg._columnSet;
      _rowSet = sdkg._rowSet;
      _blockSet = sdkg._blockSet;
      _candidates = sdkg._candidates;
      mapPointerArraysToCandidates();
   }
   return *this;
}

bool SudokuGrid::removeCandidates(const set_t &rem, int row, int column)
{
   set_t candidates{_candidates[row][column]};
   _candidates[row][column] = _candidates[row][column] - rem;
   return candidates != _candidates[row][column];
}

void SudokuGrid::add(const value_t value, int row, int column)
{
   if (isSolvable()) {
      if (isAnElementOf(value, SudokuGrid::U)) {
         // cout << "-- Add: " << Value << " in [" << Row << "][" << Column <<
         // "]" << endl;
         if (isAnElementOf(value, _columnSet[column]) &&
             isAnElementOf(value, _rowSet[row]) &&
             isAnElementOf(value, _blockSet[row / SudokuGrid::ORDER]
                                           [column / SudokuGrid::ORDER])) {
            _columnSet[column].erase(value);
            _rowSet[row].erase(value);
            _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER]
               .erase(value);
            _candidates[row][column] = SudokuGrid::EMPTY;
            _cell[row][column] = value;
            ++_numberOfCellsSolved;
         }
         else {
            // cout << "ADD ERROR" << endl;
            // writeCandidates(cout, *this);
            // getchar();
            throw std::logic_error(
               "-- [" + to_string(row) + "][" + to_string(column) +
               "] Sudoku element: " + to_string(value) + " not in groups");
         }
      }
      else {
         if (value != 0) {
            throw std::logic_error("-- Sudoku element: " + to_string(value) +
                                   " must be in the range "
                                   "[1," +
                                   to_string(SudokuGrid::ORDER2) + "]");
         }
         _cell[row][column] = 0;
      }
      calculateAllCellCandidates();
   }
   else {
      cout << "ADD to not solvable sudoku grid " << getID() << endl;
   }
}

void SudokuGrid::unsafeAdd(const value_t value, int row, int column)
{
   _columnSet[column].erase(value);
   _rowSet[row].erase(value);
   _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER].erase(value);
   _candidates[row][column] = SudokuGrid::EMPTY;
   _cell[row][column] = value;
   if (value != 0) {
      ++_numberOfCellsSolved;
   }
   calculateAllCellCandidates();
}

//------------------------------------------------------------------------------

void SudokuGrid::calculateAllCellCandidates()
{
   for (int row = 0; row < SudokuGrid::ORDER2 && _isSolvable; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2 && _isSolvable; ++col) {
         if (!cellIsSolved(row, col)) {
            _candidates[row][col] = calculateCellCandidates(row, col);
            if (_candidates[row][col].empty()) {
               _isSolvable = false;
            }
         }
      }
   }
}

SudokuGrid::set_t SudokuGrid::calculateCellCandidates(int row, int column) const
{
   return _columnSet[column] * _rowSet[row] *
          _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER];
}

void SudokuGrid::mapPointerArraysToCandidates()
{
   for (int groupIndex = 0; groupIndex < SudokuGrid::ORDER2; ++groupIndex) {
      for (int index = 0; index < SudokuGrid::ORDER2; ++index) {
         pRow[groupIndex][index] = &_candidates[groupIndex][index];
         pColumn[groupIndex][index] = &_candidates[index][groupIndex];
      }
   }
   for (int blockIndex = 0; blockIndex < SudokuGrid::ORDER2; ++blockIndex) {
      int index = 0;
      int starti = SudokuGrid::ORDER * (blockIndex / SudokuGrid::ORDER);
      int startj = SudokuGrid::ORDER * (blockIndex % SudokuGrid::ORDER);

      for (int i = starti; i < starti + SudokuGrid::ORDER; ++i) {
         for (int j = startj; j < startj + SudokuGrid::ORDER; ++j) {
            pBlock[blockIndex][index++] = &_candidates[i][j];
         }
      }
   }
}

//----------------------------------------------------------- eof SudokuGrid.cpp
<commit_msg>Improved layout<commit_after>#include "SudokuGrid.h"
#include "SetOperations.h"

#include <numeric>
#include <stdexcept>
#include <string>

using namespace std;

namespace {
const string subhorz(13, '-');
const string subhorz2(13, ' ');
const string horz = "+" + subhorz + "+" + subhorz + "+" + subhorz + "+";
const string horz2 = "|" + subhorz2 + "|" + subhorz2 + "|" + subhorz2 + "|";
const string vert(11, '|');
} // namespace

const SudokuGrid::set_t SudokuGrid::EMPTY;
const SudokuGrid::set_t SudokuGrid::U{
   makeRange<SudokuGrid::value_t>(1, SudokuGrid::ORDER2 + 1)};

ostream &operator<<(ostream &os, const SudokuGrid &sdkg)
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if ((col != 0) && (col % SudokuGrid::ORDER == 0)) {
            os << "|";
         }
         if (!sdkg.cellIsSolved(row, col)) {
            os << " . ";
         }
         else {
            os << " " << sdkg._cell[row][col] << " ";
         }
      }
      os << endl;
      if ((row != SudokuGrid::ORDER2 - 1) &&
          (row % SudokuGrid::ORDER == (SudokuGrid::ORDER - 1))) {
         // @TODO Remove magic number
         os << string(29, '-') << endl;
      }
   }
   os << endl;

   return os;
}

std::istream &operator>>(std::istream &is, SudokuGrid &sdkg)
{
   int value{0};

   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         is >> value;
         sdkg.add(value, row, col);
      }
   }
   sdkg.calculateAllCellCandidates();
   return is;
}

void writeCandidates(std::ostream &os, const SudokuGrid &sdkg)
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0 && row % SudokuGrid::ORDER == 0 &&
             row < SudokuGrid::ORDER2 - 1) {
            os << horz;
            if (row == 0) {
               os << " ID = " << &sdkg << " " << sdkg.getID() << " "
                  << (sdkg.isSolvable() ? "" : " not solvable");
            }
            os << endl << horz2 << endl;
         }
         if (col == 0) {
            os << "| ";
         }
         SudokuGrid::set_t candidates = sdkg.getCellCandidates(row, col);
         for (SudokuGrid::value_t v = 1; v <= SudokuGrid::ORDER; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               candidates == SudokuGrid::EMPTY ? os << ' ' : os << '.';
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl;
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0) {
            os << "| ";
         }
         int pos{-1};
         SudokuGrid::set_t candidates{sdkg.getCellCandidates(row, col)};
         for (SudokuGrid::value_t v = SudokuGrid::ORDER + 1;
              v <= 2 * SudokuGrid::ORDER; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               if (candidates == SudokuGrid::EMPTY) {
                  ++pos;
                  (pos == 1) ? os << sdkg._cell[row][col] : os << ' ';
               }
               else {
                  os << '.';
               }
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl;
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (col == 0) {
            os << "| ";
         }
         SudokuGrid::set_t candidates{sdkg.getCellCandidates(row, col)};
         for (SudokuGrid::value_t v = 2 * SudokuGrid::ORDER + 1;
              v < 3 * SudokuGrid::ORDER + 1; ++v) {
            if (isAnElementOf(v, candidates)) {
               os << v;
            }
            else {
               candidates == SudokuGrid::EMPTY ? os << ' ' : os << '.';
            }
         }
         if ((col != 0) && (col % SudokuGrid::ORDER == 2)) {
            os << " | ";
         }
         else {
            os << " ";
         }
      }
      os << endl << horz2 << endl;
   }
   os << horz << endl;
}

void writeLatex(std::ostream &os, const SudokuGrid &sdkg)
{
   os << "\n\\begin{sudoku}\n";
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2; ++col) {
         if (!sdkg.cellIsSolved(row, col)) {
            os << "| ";
         }
         else {
            os << "|" << sdkg._cell[row][col];
         }
      }
      os << "|.\n";
   }
   os << "\\end{sudoku}\n\n";
}

SudokuGrid::SudokuGrid()
   : _id{}
   , _numberOfCellsSolved{0}
   , _isSolvable{true}
   , _cell{{}}
   , _columnSet{{}}
   , _rowSet{{}}
   , _blockSet{{}}
   , _candidates{{}}
   , pRow{}
   , pColumn{}
   , pBlock{}
{
   for (int row = 0; row < SudokuGrid::ORDER2; ++row) {
      for (int column = 0; column < SudokuGrid::ORDER2; ++column) {
         _candidates[row][column] = U;
      }
   }
   _columnSet.fill(U);
   _rowSet.fill(U);
   for (int row = 0; row < SudokuGrid::ORDER; ++row) {
      for (int column = 0; column < SudokuGrid::ORDER; ++column) {
         _blockSet[row][column] = U;
      }
   }
   mapPointerArraysToCandidates();
}

SudokuGrid::SudokuGrid(const SudokuGrid &sdkg)
   : _id{sdkg._id}
   , _numberOfCellsSolved{sdkg._numberOfCellsSolved}
   , _isSolvable{sdkg._isSolvable}
   , _cell{{}}
   , _columnSet{{}}
   , _rowSet{{}}
   , _blockSet{{}}
   , _candidates{{}}
   , pRow{}
   , pColumn{}
   , pBlock{}
{
   _cell = sdkg._cell;
   _columnSet = sdkg._columnSet;
   _rowSet = sdkg._rowSet;
   _blockSet = sdkg._blockSet;
   _candidates = sdkg._candidates;
   mapPointerArraysToCandidates();
   // writeCandidates(cout, sdkg);
   // cout << "COPY" << endl;
   // writeCandidates(cout, *this);
}

SudokuGrid &SudokuGrid::operator=(const SudokuGrid &sdkg)
{
   if (this != &sdkg) {
      _id = sdkg._id;
      _numberOfCellsSolved = sdkg._numberOfCellsSolved;
      _isSolvable = sdkg._isSolvable;
      _cell = sdkg._cell;
      _columnSet = sdkg._columnSet;
      _rowSet = sdkg._rowSet;
      _blockSet = sdkg._blockSet;
      _candidates = sdkg._candidates;
      mapPointerArraysToCandidates();
   }
   return *this;
}

bool SudokuGrid::removeCandidates(const set_t &rem, int row, int column)
{
   set_t candidates{_candidates[row][column]};
   _candidates[row][column] = _candidates[row][column] - rem;
   return candidates != _candidates[row][column];
}

void SudokuGrid::add(const value_t value, int row, int column)
{
   if (isSolvable()) {
      if (isAnElementOf(value, SudokuGrid::U)) {
         // cout << "-- Add: " << Value << " in [" << Row << "][" << Column <<
         // "]" << endl;
         if (isAnElementOf(value, _columnSet[column]) &&
             isAnElementOf(value, _rowSet[row]) &&
             isAnElementOf(value, _blockSet[row / SudokuGrid::ORDER]
                                           [column / SudokuGrid::ORDER])) {
            _columnSet[column].erase(value);
            _rowSet[row].erase(value);
            _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER]
               .erase(value);
            _candidates[row][column] = SudokuGrid::EMPTY;
            _cell[row][column] = value;
            ++_numberOfCellsSolved;
         }
         else {
            // cout << "ADD ERROR" << endl;
            // writeCandidates(cout, *this);
            // getchar();
            throw std::logic_error(
               "-- [" + to_string(row) + "][" + to_string(column) +
               "] Sudoku element: " + to_string(value) + " not in groups");
         }
      }
      else {
         if (value != 0) {
            throw std::logic_error("-- Sudoku element: " + to_string(value) +
                                   " must be in the range "
                                   "[1," +
                                   to_string(SudokuGrid::ORDER2) + "]");
         }
         _cell[row][column] = 0;
      }
      calculateAllCellCandidates();
   }
   else {
      cout << "ADD to not solvable sudoku grid " << getID() << endl;
   }
}

void SudokuGrid::unsafeAdd(const value_t value, int row, int column)
{
   _columnSet[column].erase(value);
   _rowSet[row].erase(value);
   _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER].erase(value);
   _candidates[row][column] = SudokuGrid::EMPTY;
   _cell[row][column] = value;
   if (value != 0) {
      ++_numberOfCellsSolved;
   }
   calculateAllCellCandidates();
}

//------------------------------------------------------------------------------

void SudokuGrid::calculateAllCellCandidates()
{
   for (int row = 0; row < SudokuGrid::ORDER2 && _isSolvable; ++row) {
      for (int col = 0; col < SudokuGrid::ORDER2 && _isSolvable; ++col) {
         if (!cellIsSolved(row, col)) {
            _candidates[row][col] = calculateCellCandidates(row, col);
            if (_candidates[row][col].empty()) {
               _isSolvable = false;
            }
         }
      }
   }
}

SudokuGrid::set_t SudokuGrid::calculateCellCandidates(int row, int column) const
{
   return _columnSet[column] * _rowSet[row] *
          _blockSet[row / SudokuGrid::ORDER][column / SudokuGrid::ORDER];
}

void SudokuGrid::mapPointerArraysToCandidates()
{
   for (int groupIndex = 0; groupIndex < SudokuGrid::ORDER2; ++groupIndex) {
      for (int index = 0; index < SudokuGrid::ORDER2; ++index) {
         pRow[groupIndex][index] = &_candidates[groupIndex][index];
         pColumn[groupIndex][index] = &_candidates[index][groupIndex];
      }
   }
   for (int blockIndex = 0; blockIndex < SudokuGrid::ORDER2; ++blockIndex) {
      int index = 0;
      int starti = SudokuGrid::ORDER * (blockIndex / SudokuGrid::ORDER);
      int startj = SudokuGrid::ORDER * (blockIndex % SudokuGrid::ORDER);

      for (int i = starti; i < starti + SudokuGrid::ORDER; ++i) {
         for (int j = startj; j < startj + SudokuGrid::ORDER; ++j) {
            pBlock[blockIndex][index++] = &_candidates[i][j];
         }
      }
   }
}
<|endoftext|>