<commit_before>#include <iostream>
#include <time.h>
#include "vpp/algorithms/Line_tracker_4_sfm/Hough_Extruder/hough_extruder.hh"

#include <chrono>
//1

using namespace  std;
using namespace Eigen;
using namespace cv;
using namespace vpp;
using namespace std::chrono;

int main(int argc, char *argv[])
{
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    //image3d<vuchar3> img3;
    //feature_matching_video
    //mode_capture_photo
    Capture_Image(feature_matching_video,Theta_max::SMALL, Sclare_rho::HALF,
                  Type_video_hough::ALL_POINTS,
                  Type_output::ORIGINAL_VIDEO,
                  Type_Lines::ONLY_POLAR,
                  Frequence::ALL_FRAME,
                  With_Kalman_Filter::NO,
                  With_Transparency::YES,
                  _rayon_exclusion_theta = 15,
                  _rayon_exclusion_rho = 12,
                  _slot_hough = 1,
                  _link_of_video = "videos/work1.avi",
                  _detector_th = 10,
                  _keypoint_spacing = 10,
                  _detector_period = 1,
                  _acc_threshold = 100,
                  _m_first_lines = 5,
                  _max_trajectory_length = 5,
                  _nombre_max_frame_without_update =5);/**/
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<seconds>( t2 - t1 ).count();
    cout << "la duree " << duration << endl ;
    return 0;
}
<commit_msg>Update hough_extruder.cc<commit_after>#include <iostream>
#include <time.h>
#include "vpp/algorithms/Line_tracker_4_sfm/Hough_Extruder/hough_extruder.hh"

#include <chrono>
//1

using namespace  std;
using namespace Eigen;
using namespace cv;
using namespace vpp;
using namespace std::chrono;

int main(int argc, char *argv[])
{
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    Fast_DHT_Matching(feature_matching,Theta_max::SMALL, Sclare_rho::SAME,
                  Type_video_hough::ALL_POINTS,
                  Type_output::ORIGINAL_VIDEO,
                  Type_Lines::ONLY_POLAR,
                  Frequence::ALL_FRAME,
                  With_Kalman_Filter::NO,
                  With_Transparency::YES,
                  With_Entries::YES,
                  _rayon_exclusion_theta = 15,
                  _rayon_exclusion_rho = 12,
                  _slot_hough = 1,
                  _link_of_video_image = "videos/corridor2.mp4",
                  _acc_threshold = 100,
                  _m_first_lines = 5,
                  _max_trajectory_length = 5,
                  _nombre_max_frame_without_update =5);/**/
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    auto duration = duration_cast<nanoseconds>( t2 - t1 ).count();
    cout << "la duree " << duration << endl ;
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2009 Odbayar Nyamtseren <odbayar.n@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <windows.h>
#include <immdev.h>
#include <string.h>
#include <tchar.h>
#include "common.h"
#include "input_context.h"
#include "comp_string.h"
#include "composer.h"

namespace /* anonymous */
{
    void initContext(InputContext* imc)
    {
        INPUTCONTEXT* imcPtr = imc->ptr();

        if (!(imcPtr->fdwInit & INIT_CONVERSION))
        {
            imcPtr->fdwConversion = IME_CMODE_NATIVE;
            imcPtr->fdwInit |= INIT_CONVERSION;
        }

        if (!(imcPtr->fdwInit & INIT_LOGFONT))
        {
            NONCLIENTMETRICS ncMetrics;
            ncMetrics.cbSize = sizeof(NONCLIENTMETRICS);
            SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
                    sizeof(NONCLIENTMETRICS), &ncMetrics, 0);
            imcPtr->lfFont.W = ncMetrics.lfMessageFont;
            imcPtr->fdwInit |= INIT_LOGFONT;
        }

        if (!(imcPtr->fdwInit & INIT_COMPFORM))
        {
            imcPtr->cfCompForm.dwStyle = CFS_POINT;
            imcPtr->cfCompForm.ptCurrentPos.x = 0;
            imcPtr->cfCompForm.ptCurrentPos.y = 0;
            if (IsWindow(imcPtr->hWnd))
                GetClientRect(imcPtr->hWnd, &imcPtr->cfCompForm.rcArea);
            else
                memset(&imcPtr->cfCompForm.rcArea, 0, sizeof(RECT));
            imcPtr->fdwInit |= INIT_COMPFORM;
        }
    }
} // anonymous namespace

bool isWinLogonProcess;

extern "C"
BOOL WINAPI ImeInquire(LPIMEINFO imeInfo,
                       LPTSTR uiWndClass,
                       DWORD systemInfo)
{
    if (!imeInfo)
        return FALSE;

    imeInfo->dwPrivateDataSize = sizeof(ImcPrivate);
    imeInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_KBD_CHAR_FIRST |
                           IME_PROP_IGNORE_UPKEYS | IME_PROP_AT_CARET;
    imeInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_SOFTKBD;
    imeInfo->fdwSentenceCaps = 0;
    imeInfo->fdwUICaps = UI_CAP_SOFTKBD;
    imeInfo->fdwSCSCaps = 0;
    imeInfo->fdwSelectCaps = 0;

    _tcscpy(uiWndClass, uiClassName);

    isWinLogonProcess = systemInfo & IME_SYSINFO_WINLOGON;

    return TRUE;
}

extern "C"
DWORD WINAPI ImeConversionList(HIMC hImc,
                               LPCTSTR src,
                               LPCANDIDATELIST dest,
                               DWORD bufLen,
                               UINT flag)
{
    return 0; // We won't implement this API
}

extern "C"
BOOL WINAPI ImeConfigure(HKL kl, HWND wnd, DWORD mode, LPVOID data)
{
    // TODO

    return FALSE;
}

extern "C"
BOOL WINAPI ImeDestroy(UINT reserved)
{
    if (reserved != 0)
        return FALSE;
    return TRUE;
}

extern "C"
LRESULT WINAPI ImeEscape(HIMC hImc, UINT escape, LPVOID data)
{
    switch (escape)
    {
    case IME_ESC_QUERY_SUPPORT:
        if (data)
        {
            switch (*(UINT*)data)
            {
            case IME_ESC_QUERY_SUPPORT:
            //case IME_ESC_GETHELPFILENAME:
                return TRUE;
            }
        }
        return FALSE;
    case IME_ESC_GETHELPFILENAME:
        //{
        //    LPTSTR path = (LPTSTR)data;
        //    if (path && GetWindowsDirectory(path, MAX_PATH))
        //    {
        //        if (_tcscat_s(path, MAX_PATH, _T("\\Help\\buuz.chm")) == 0)
        //            return TRUE;
        //    }
        //}
        return FALSE;
    default:
        return FALSE;
    }
}

extern "C"
BOOL WINAPI ImeProcessKey(HIMC hImc,
                          UINT virtKey,
                          LPARAM lParam,
                          CONST LPBYTE keyState)
{
    InputContext imc(hImc);

    if (!imc.lock())
        return FALSE;

    WORD scanCode = HIWORD(lParam);
    WCHAR charCode;
    if (ToUnicode(virtKey, scanCode, keyState, &charCode, 1, 0) == 0)
        charCode = 0;
    return composer->processKey(&imc, virtKey, scanCode, charCode, keyState);
}

extern "C"
UINT WINAPI ImeToAsciiEx(UINT virtKey,
                         UINT scanCode,
                         CONST LPBYTE keyState,
                         LPTRANSMSGLIST transMsgList,
                         UINT state,
                         HIMC hImc)
{
    InputContext imc(hImc);

    if (!imc.lock())
        return 0;

    ImcPrivate* imcPrv = imc.prv();

    imcPrv->numMsgs = 0;
    imcPrv->msgList = transMsgList;
    composer->toAsciiEx(&imc, LOWORD(virtKey), scanCode, HIWORD(virtKey), keyState);
    imcPrv->msgList = NULL;

    return imcPrv->numMsgs;
}

extern "C"
BOOL WINAPI NotifyIME(HIMC hImc, DWORD action, DWORD index, DWORD value)
{
    InputContext imc(hImc);
    CompString cs(&imc);
    BOOL retValue = FALSE;

    if (!imc.lock())
        return retValue;

    switch (action)
    {
    case NI_CONTEXTUPDATED:
        switch (value)
        {
        case IMC_SETOPENSTATUS:
            {
                if (!imc.ptr()->fOpen && cs.lock() && cs.compStr.size() != 0)
                    composer->cancelComp(&imc, &cs);
                retValue = TRUE;
            }
            break;
        case IMC_SETCONVERSIONMODE:
        case IMC_SETSENTENCEMODE:
            break;
        case IMC_SETCANDIDATEPOS:
        case IMC_SETCOMPOSITIONFONT:
        case IMC_SETCOMPOSITIONWINDOW:
            retValue = FALSE;
            break;
        }
        break;

    case NI_COMPOSITIONSTR:
        if (cs.lock())
        {
            switch (index)
            {
            case CPS_COMPLETE:
                composer->finishComp(&imc, &cs);
                retValue = TRUE;
                break;
            case CPS_CONVERT:
                break;
            case CPS_REVERT:
                break;
            case CPS_CANCEL:
                composer->cancelComp(&imc, &cs);
                retValue = TRUE;
                break;
            }
        }
        break;

    // We don't support candidate list.
    case NI_OPENCANDIDATE:
    case NI_CLOSECANDIDATE:
    case NI_SELECTCANDIDATESTR:
    case NI_CHANGECANDIDATELIST:
    case NI_SETCANDIDATE_PAGESTART:
    case NI_SETCANDIDATE_PAGESIZE:
        retValue = FALSE;
        break;
    }

    return retValue;
}

extern "C"
BOOL WINAPI ImeSelect(HIMC hImc, BOOL select)
{
    InputContext imc(hImc);

    if (!imc.lock())
        return FALSE;

    INPUTCONTEXT* imcPtr = imc.ptr();
    ImcPrivate* imcPrv = imc.prv();

    if (select)
    {
        CompString cs(&imc);
        if (!cs.create())
            return FALSE;

        imcPtr->fOpen = TRUE;

        initContext(&imc);
    }
    else
    {
        imcPtr->fOpen = FALSE;
    }

    return TRUE;
}

extern "C"
BOOL WINAPI ImeSetActiveContext(HIMC hImc, BOOL activate)
{
    InputContext imc(hImc);
    CompString cs(&imc);

    if (!(imc.lock() && cs.lock()))
        return FALSE;

    if (activate)
        initContext(&imc);
    else
        if (cs.compStr.size() != 0)
            composer->finishComp(&imc, &cs);

    return TRUE;
}

extern "C"
BOOL WINAPI ImeSetCompositionString(HIMC hImc,
                                    DWORD index,
                                    LPVOID comp,
                                    DWORD compLen,
                                    LPVOID read,
                                    DWORD readLen)
{
    return FALSE;
}

//
// We won't support dictionary, so everything below this line is unimportant.
//

extern "C"
BOOL WINAPI ImeRegisterWord(LPCTSTR reading, DWORD style, LPCTSTR string)
{
    return FALSE;
}

extern "C"
BOOL WINAPI ImeUnregisterWord(LPCTSTR reading, DWORD style, LPCTSTR string)
{
    return FALSE;
}

extern "C"
UINT WINAPI ImeGetRegisterWordStyle(UINT item, LPSTYLEBUF styleBuf)
{
    return FALSE;
}

extern "C"
UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC enumProc,
        LPCTSTR reading, DWORD style, LPCTSTR string, LPVOID data)
{
    return FALSE;
}
<commit_msg>Even more cosmetic changes.<commit_after>/*
 * Copyright 2009 Odbayar Nyamtseren <odbayar.n@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <windows.h>
#include <immdev.h>
#include <string.h>
#include <tchar.h>
#include "common.h"
#include "input_context.h"
#include "comp_string.h"
#include "composer.h"

bool isWinLogonProcess;

namespace /* unnamed */ {

    void initContext(InputContext* imc) {
        INPUTCONTEXT* imcPtr = imc->ptr();

        if (!(imcPtr->fdwInit & INIT_CONVERSION)) {
            imcPtr->fdwConversion = IME_CMODE_NATIVE;
            imcPtr->fdwInit |= INIT_CONVERSION;
        }

        if (!(imcPtr->fdwInit & INIT_LOGFONT)) {
            NONCLIENTMETRICS ncMetrics;
            ncMetrics.cbSize = sizeof(NONCLIENTMETRICS);
            SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
                    sizeof(NONCLIENTMETRICS), &ncMetrics, 0);
            imcPtr->lfFont.W = ncMetrics.lfMessageFont;
            imcPtr->fdwInit |= INIT_LOGFONT;
        }

        if (!(imcPtr->fdwInit & INIT_COMPFORM)) {
            imcPtr->cfCompForm.dwStyle = CFS_POINT;
            imcPtr->cfCompForm.ptCurrentPos.x = 0;
            imcPtr->cfCompForm.ptCurrentPos.y = 0;
            if (IsWindow(imcPtr->hWnd))
                GetClientRect(imcPtr->hWnd, &imcPtr->cfCompForm.rcArea);
            else
                memset(&imcPtr->cfCompForm.rcArea, 0, sizeof(RECT));
            imcPtr->fdwInit |= INIT_COMPFORM;
        }
    }

} // unnamed namespace

extern "C" {

    BOOL WINAPI ImeInquire(LPIMEINFO imeInfo,
                           LPTSTR uiWndClass,
                           DWORD systemInfo)
    {
        if (!imeInfo)
            return FALSE;

        imeInfo->dwPrivateDataSize = sizeof(ImcPrivate);
        imeInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_KBD_CHAR_FIRST |
                               IME_PROP_IGNORE_UPKEYS | IME_PROP_AT_CARET;
        imeInfo->fdwConversionCaps = IME_CMODE_NATIVE | IME_CMODE_SOFTKBD;
        imeInfo->fdwSentenceCaps = 0;
        imeInfo->fdwUICaps = UI_CAP_SOFTKBD;
        imeInfo->fdwSCSCaps = 0;
        imeInfo->fdwSelectCaps = 0;

        _tcscpy(uiWndClass, uiClassName);

        isWinLogonProcess = systemInfo & IME_SYSINFO_WINLOGON;

        return TRUE;
    }

    DWORD WINAPI ImeConversionList(HIMC hImc,
                                   LPCTSTR src,
                                   LPCANDIDATELIST dest,
                                   DWORD bufLen,
                                   UINT flag)
    {
        return 0; // We won't implement this API
    }

    BOOL WINAPI ImeConfigure(HKL kl, HWND wnd, DWORD mode, LPVOID data) {
        // TODO

        return FALSE;
    }

    BOOL WINAPI ImeDestroy(UINT reserved) {
        if (reserved != 0)
            return FALSE;
        return TRUE;
    }

    LRESULT WINAPI ImeEscape(HIMC hImc, UINT escape, LPVOID data) {
        switch (escape) {
        case IME_ESC_QUERY_SUPPORT:
            if (data) {
                switch (*(UINT*)data) {
                case IME_ESC_QUERY_SUPPORT:
                //case IME_ESC_GETHELPFILENAME:
                    return TRUE;
                }
            }
            return FALSE;
        case IME_ESC_GETHELPFILENAME:
            //{
            //    LPTSTR path = (LPTSTR)data;
            //    if (path && GetWindowsDirectory(path, MAX_PATH))
            //    {
            //        if (_tcscat_s(path, MAX_PATH, _T("\\Help\\buuz.chm")) == 0)
            //            return TRUE;
            //    }
            //}
            return FALSE;
        default:
            return FALSE;
        }
    }

    BOOL WINAPI ImeProcessKey(HIMC hImc,
                              UINT virtKey,
                              LPARAM lParam,
                              CONST LPBYTE keyState)
    {
        InputContext imc(hImc);

        if (!imc.lock())
            return FALSE;

        WORD scanCode = HIWORD(lParam);
        WCHAR charCode;
        if (ToUnicode(virtKey, scanCode, keyState, &charCode, 1, 0) == 0)
            charCode = 0;
        return composer->processKey(&imc, virtKey, scanCode, charCode, keyState);
    }

    UINT WINAPI ImeToAsciiEx(UINT virtKey,
                             UINT scanCode,
                             CONST LPBYTE keyState,
                             LPTRANSMSGLIST transMsgList,
                             UINT state,
                             HIMC hImc)
    {
        InputContext imc(hImc);

        if (!imc.lock())
            return 0;

        ImcPrivate* imcPrv = imc.prv();

        imcPrv->numMsgs = 0;
        imcPrv->msgList = transMsgList;
        composer->toAsciiEx(&imc, LOWORD(virtKey), scanCode, HIWORD(virtKey), keyState);
        imcPrv->msgList = NULL;

        return imcPrv->numMsgs;
    }

    BOOL WINAPI NotifyIME(HIMC hImc, DWORD action, DWORD index, DWORD value) {
        InputContext imc(hImc);
        CompString cs(&imc);
        BOOL retValue = FALSE;

        if (!imc.lock())
            return retValue;

        switch (action) {
        case NI_CONTEXTUPDATED:
            switch (value) {
            case IMC_SETOPENSTATUS:
                {
                    if (!imc.ptr()->fOpen && cs.lock() && cs.compStr.size() != 0)
                        composer->cancelComp(&imc, &cs);
                    retValue = TRUE;
                }
                break;
            case IMC_SETCONVERSIONMODE:
            case IMC_SETSENTENCEMODE:
                break;
            case IMC_SETCANDIDATEPOS:
            case IMC_SETCOMPOSITIONFONT:
            case IMC_SETCOMPOSITIONWINDOW:
                retValue = FALSE;
                break;
            }
            break;

        case NI_COMPOSITIONSTR:
            if (cs.lock()) {
                switch (index) {
                case CPS_COMPLETE:
                    composer->finishComp(&imc, &cs);
                    retValue = TRUE;
                    break;
                case CPS_CONVERT:
                    break;
                case CPS_REVERT:
                    break;
                case CPS_CANCEL:
                    composer->cancelComp(&imc, &cs);
                    retValue = TRUE;
                    break;
                }
            }
            break;

        // We don't support candidate list.
        case NI_OPENCANDIDATE:
        case NI_CLOSECANDIDATE:
        case NI_SELECTCANDIDATESTR:
        case NI_CHANGECANDIDATELIST:
        case NI_SETCANDIDATE_PAGESTART:
        case NI_SETCANDIDATE_PAGESIZE:
            retValue = FALSE;
            break;
        }

        return retValue;
    }

    BOOL WINAPI ImeSelect(HIMC hImc, BOOL select) {
        InputContext imc(hImc);

        if (!imc.lock())
            return FALSE;

        INPUTCONTEXT* imcPtr = imc.ptr();
        ImcPrivate* imcPrv = imc.prv();

        if (select) {
            CompString cs(&imc);
            if (!cs.create())
                return FALSE;

            imcPtr->fOpen = TRUE;

            initContext(&imc);
        } else {
            imcPtr->fOpen = FALSE;
        }

        return TRUE;
    }

    BOOL WINAPI ImeSetActiveContext(HIMC hImc, BOOL activate) {
        InputContext imc(hImc);
        CompString cs(&imc);

        if (!(imc.lock() && cs.lock()))
            return FALSE;

        if (activate) {
            initContext(&imc);
        } else {
            if (cs.compStr.size() != 0)
                composer->finishComp(&imc, &cs);
        }

        return TRUE;
    }

    BOOL WINAPI ImeSetCompositionString(HIMC hImc,
                                        DWORD index,
                                        LPVOID comp,
                                        DWORD compLen,
                                        LPVOID read,
                                        DWORD readLen)
    {
        return FALSE;
    }

    //
    // We won't support dictionary, so everything below this line is unimportant.
    //

    BOOL WINAPI ImeRegisterWord(LPCTSTR reading, DWORD style, LPCTSTR string) {
        return FALSE;
    }

    BOOL WINAPI ImeUnregisterWord(LPCTSTR reading, DWORD style, LPCTSTR string) {
        return FALSE;
    }

    UINT WINAPI ImeGetRegisterWordStyle(UINT item, LPSTYLEBUF styleBuf) {
        return FALSE;
    }

    UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROC enumProc,
                                    LPCTSTR reading,
                                    DWORD style,
                                    LPCTSTR string,
                                    LPVOID data)
    {
        return FALSE;
    }

} // extern "C"
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
// $Log: cmd_quest.cc,v $
// Revision 1.1  1999/09/12 17:24:04  sneezy
// Initial revision
//
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"

bool TBeing::hasQuestBit(int) const
{
  return false;
}

void TBeing::setQuestBit(int)
{
}

void TBeing::remQuestBit(int)
{
}

bool TPerson::hasQuestBit(int value) const
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of hasQuestBit(%d)", value);
    return FALSE;
  }

  return (toggles[value]);
}

void TPerson::setQuestBit(int value)
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of setQuestBit(%d)", value);
    return;
  }

  toggles[value] |= 0x1;
}

void TPerson::remQuestBit(int value)
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of remQuestBit(%d)", value);
    return;
  }

  toggles[value] &= ~(0x1);
}

void TBeing::doMortalQuest(const char *tArg)
{
  /********************************************
   Quest information is no longer housed here.
   use: lib/mobdata/responses/help/tog_number
   to add help to a response quest.
   ********************************************/
  sendTo("Your current quest status:\n\r");

  if (GetMaxLevel() > MAX_MORT) {
    char buf[256];
    const char * t2 = one_argument(tArg, buf);
    char   questPath[256];
    string tStString("");

    // check "immorts" for "quest real 3"
    if (is_abbrev(buf, "real")) {
      int questNumber = atoi(t2);
      if (questNumber < 0 || questNumber >= MAX_TOG_INDEX) {
        sendTo("Invalid quest value.\n\r");
        return;
      }

      sprintf(questPath, "mobdata/responses/help/%d", questNumber);
      if (file_to_string(questPath, tStString, true))
        desc->page_string(tStString.c_str(), 0);
      else
        sendTo("No such quest helpfile seems to exist.\n\r");

      return;
    }
  }

  int questNumber = atoi(tArg);
  unsigned int totFound = 0;
  int questRes = -1;
  char   questPath[256];
  string tStString("");

  if (questNumber <= 0)
    questNumber = 1;

  for (int questIndex = (MAX_TOG_INDEX - 1); questIndex > -1; questIndex--) {
    if (hasQuestBit(questIndex)) {
      sprintf(questPath, "mobdata/responses/help/%d", questIndex);
      FILE *fp = fopen(questPath, "r");
      if (fp) {
        totFound++;
        fclose(fp);
        if (questNumber == (int) totFound)
          questRes = questIndex;
      }
    }
  }

  sendTo("You have %d total current quest goals.\n\r", totFound);
  if (questRes != -1) {
    sendTo("You don't seem to have a quest goal #%d\n\r", questNumber);
    return;
  }

  sprintf(questPath, "mobdata/responses/help/%d", questRes);
  if (file_to_string(questPath, tStString, true))
    desc->page_string(tStString.c_str(), 0);
  // else condition not needed, it should be valid based on above logic
}

<commit_msg>Fixed typo that was preventing execution.<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
// $Log: cmd_quest.cc,v $
// Revision 1.2  1999/09/27 14:12:24  lapsos
// Fixed typo that was preventing execution.
//
// Revision 1.1  1999/09/12 17:24:04  sneezy
// Initial revision
//
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"

bool TBeing::hasQuestBit(int) const
{
  return false;
}

void TBeing::setQuestBit(int)
{
}

void TBeing::remQuestBit(int)
{
}

bool TPerson::hasQuestBit(int value) const
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of hasQuestBit(%d)", value);
    return FALSE;
  }

  return (toggles[value]);
}

void TPerson::setQuestBit(int value)
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of setQuestBit(%d)", value);
    return;
  }

  toggles[value] |= 0x1;
}

void TPerson::remQuestBit(int value)
{
  if (value < 0 || value >= MAX_TOG_INDEX) {
    vlogf(6, "Bad check of remQuestBit(%d)", value);
    return;
  }

  toggles[value] &= ~(0x1);
}

void TBeing::doMortalQuest(const char *tArg)
{
  /********************************************
   Quest information is no longer housed here.
   use: lib/mobdata/responses/help/tog_number
   to add help to a response quest.
   ********************************************/
  sendTo("Your current quest status:\n\r");

  if (GetMaxLevel() > MAX_MORT) {
    char buf[256];
    const char * t2 = one_argument(tArg, buf);
    char   questPath[256];
    string tStString("");

    // check "immorts" for "quest real 3"
    if (is_abbrev(buf, "real")) {
      int questNumber = atoi(t2);
      if (questNumber < 0 || questNumber >= MAX_TOG_INDEX) {
        sendTo("Invalid quest value.\n\r");
        return;
      }

      sprintf(questPath, "mobdata/responses/help/%d", questNumber);
      if (file_to_string(questPath, tStString, true))
        desc->page_string(tStString.c_str(), 0);
      else
        sendTo("No such quest helpfile seems to exist.\n\r");

      return;
    }
  }

  int questNumber = atoi(tArg);
  unsigned int totFound = 0;
  int questRes = -1;
  char   questPath[256];
  string tStString("");

  if (questNumber <= 0)
    questNumber = 1;

  for (int questIndex = (MAX_TOG_INDEX - 1); questIndex > -1; questIndex--) {
    if (hasQuestBit(questIndex)) {
      sprintf(questPath, "mobdata/responses/help/%d", questIndex);
      FILE *fp = fopen(questPath, "r");
      if (fp) {
        totFound++;
        fclose(fp);
        if (questNumber == (int) totFound)
          questRes = questIndex;
      }
    }
  }

  sendTo("You have %d total current quest goals.\n\r", totFound);
  if (questRes == -1) {
    sendTo("You don't seem to have a quest goal #%d\n\r", questNumber);
    return;
  }

  sprintf(questPath, "mobdata/responses/help/%d", questRes);
  if (file_to_string(questPath, tStString, true))
    desc->page_string(tStString.c_str(), 0);
  // else condition not needed, it should be valid based on above logic
}

<|endoftext|>


<commit_before><commit_msg>`gpgpu_test::create_gpgpu_test_scene`: edited debug output.<commit_after><|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(ptr),
      b(b) {
    if (ptr) {
      ptr->incShared();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(nullptr), b(false) {
    if (o.b && biconnected_copy()) {
      replace(o.load());
      b = true;
    } else {
      replace(o.get());
      b = false;
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      Shared(o.get(), false) {
    //
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    if (o.b && biconnected_copy()) {
      replace(o.load());
      b = true;
    } else {
      replace(o.get());
      b = false;
    }
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return load() != nullptr;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer as const.
   */
  const T* read() const {
    return get();
  }

  /**
   * Deep copy.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Replace. Sets the raw pointer to a new value and returns the previous
   * value.
   */
  T* replace(T* ptr) {
    if (ptr) {
      ptr->incShared();
    }
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    b = false;
    return old;
  }

  /**
   * Release. Sets the raw pointer to null and returns the previous value.
   */
  T* release() {
    auto old = ptr.exchange(nullptr);
    if (old) {
      old->decShared();
    }
    b = false;
    return old;
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

private:
  /**
   * Load the raw pointer as-is. Does not trigger copy-on-write.
   */
  T* load() const {
    return ptr.load();
  }

  /**
   * Store the raw pointer as-is. Does not update reference counts.
   */
  void store(T* o) {
    ptr.store(o);
  }

  /**
   * Raw pointer.
   */
  Atomic<T*> ptr;

  /**
   * Is this a bridge?
   */
  bool b;
};

template<class T>
struct is_value<Shared<T>> {
  static const bool value = false;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* v = load();
  if (b) {
    b = false;
    if (v->numShared() > 1) {  // no need to copy for last reference
      /* the copy is of a biconnected component here, used the optimized
       * BiconnectedCopier for this */
      v = static_cast<T*>(BiconnectedCopier(v).visit(static_cast<Any*>(v)));
      replace(v);
    }
  }
  return v;
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  /* find bridges */
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);

  Any* u = load();
  if (b) {
    return Shared<T>(static_cast<T*>(u), true);
  } else {
    /* the copy is *not* of a biconnected component here, used the
     * general-purpose Copier for this */
    return Shared<T>(static_cast<T*>(Copier().visit(u)), false);
  }
}
<commit_msg>Debugging copy on write.<commit_after>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(ptr),
      b(b) {
    if (ptr) {
      ptr->incShared();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(nullptr), b(false) {
    if (o.b) {
      if (biconnected_copy()) {
        replace(o.load());
        b = true;
      } else {
        replace(o.get());
        b = false;
      }
    } else {
      replace(o.load());
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      Shared(o.get(), false) {
    //
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return load() != nullptr;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer as const.
   */
  const T* read() const {
    return get();
  }

  /**
   * Deep copy.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Replace. Sets the raw pointer to a new value and returns the previous
   * value.
   */
  T* replace(T* ptr) {
    if (ptr) {
      ptr->incShared();
    }
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    b = false;
    return old;
  }

  /**
   * Release. Sets the raw pointer to null and returns the previous value.
   */
  T* release() {
    auto old = ptr.exchange(nullptr);
    if (old) {
      old->decShared();
    }
    b = false;
    return old;
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

private:
  /**
   * Load the raw pointer as-is. Does not trigger copy-on-write.
   */
  T* load() const {
    return ptr.load();
  }

  /**
   * Store the raw pointer as-is. Does not update reference counts.
   */
  void store(T* o) {
    ptr.store(o);
  }

  /**
   * Raw pointer.
   */
  Atomic<T*> ptr;

  /**
   * Is this a bridge?
   */
  bool b;
};

template<class T>
struct is_value<Shared<T>> {
  static const bool value = false;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* v = load();
  if (b) {
    b = false;
    if (v->numShared() > 1) {  // no need to copy for last reference
      /* the copy is of a biconnected component here, used the optimized
       * BiconnectedCopier for this */
      v = static_cast<T*>(BiconnectedCopier(v).visit(static_cast<Any*>(v)));
      replace(v);
    }
  }
  return v;
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  /* find bridges */
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);

  Any* u = load();
  if (b) {
    return Shared<T>(static_cast<T*>(u), true);
  } else {
    /* the copy is *not* of a biconnected component here, used the
     * general-purpose Copier for this */
    return Shared<T>(static_cast<T*>(Copier().visit(u)), false);
  }
}
<|endoftext|>


<commit_before>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class BiconnectedCollector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
  friend class Destroyer;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  template<class U = T, std::enable_if_t<std::is_default_constructible<U>::value,int> = 0>
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args, std::enable_if_t<std::is_constructible<T,Args...>::value,int> = 0>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(pack(ptr)),
      a(ptr->isAcyclic_()),
      b(b) {
    if (ptr) {
      ptr->incShared_();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(o.ptr), a(o.a), b(o.b) {
    if (ptr) {
      if (biconnected_copy()) {
        if (b) {
          unpack(ptr)->incShared_();
        } else {
          // deferred until Copier or BiconnectedCopier visits and updates
        }
      } else {
        if (b) {
          store(o.get());  // copy next biconnected component
          b = false;
        }
        unpack(ptr)->incShared_();
      }
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      ptr(pack(o.get())),
      a(o.a),
      b(false) {
    if (ptr) {
      unpack(ptr)->incShared_();
    }
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) : ptr(o.ptr), a(o.a), b(o.b) {
    o.store(nullptr);
    o.a = false;
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) : ptr(o.ptr), a(o.a), b(o.b) {
    o.store(nullptr);
    o.a = false;
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    replace(o);
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o);
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    replace(std::move(o));
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    replace(std::move(o));
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<!std::is_base_of<T,U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<!std::is_base_of<T,U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return ptr != 0;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer without copy-on-use.
   */
  T* load() const {
    return unpack(ptr);
  }

  /**
   * Bridge finding. Finds bridges in the reachable graph. Must be followed by
   * copy() for correct behavior.
   */
  void bridge();

  /**
   * Bridge finding.
   */
  void bridge() const {
    return const_cast<Shared<T>*>(this)->bridge();
  }

  /**
   * Deep copy. Copies the subgraph up to the nearest reachable bridges, the
   * remainder deferred until needed. If bridge() has been called previously,
   * this constitutes a lazy copy, otherwise an eager copy. It is correct
   * either way.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Replace.
   */
  template<class U>
  void replace(const Shared<U>& o) {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    /* when duplicating a pointer, may need to trigger a biconnected copy */
    auto ptr1 = o.get();
    if (ptr1) {
      ptr1->incShared_();
    }

    this->ptr = pack(ptr1);
    this->a = o.a;
    this->b = false;  // if it was a bridge, now copied

    if (ptr) {
      if (ptr == ptr1) {
        ptr->decSharedReachable_();
      } else if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }
  }

  /**
   * Replace.
   */
  template<class U>
  void replace(Shared<U>&& o) {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = o.ptr;
    this->a = o.a;
    this->b = o.b;

    if (ptr) {
      if (ptr == unpack(this->ptr)) {
        ptr->decSharedReachable_();
      } else if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }

    o.ptr = 0;
    o.a = false;
    o.b = false;
  }

  /**
   * Release the referent.
   */
  void release() {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = 0;
    this->a = false;
    this->b = false;

    if (ptr) {
      if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }
  }

  /**
   * Release the referent, during collection of a biconnected component.
   */
  void releaseBiconnected() {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = 0;
    this->a = false;
    this->b = false;

    if (ptr) {
      if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decSharedBiconnected_();
      }
    }
  }

  /**
   * Dereference.
   */
  T& operator*() {
    return *get();
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() {
    return get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) const {
    return const_cast<Shared<T>*>(this)->operator()(std::forward<Args>(args)...);
  }

private:
  /**
   * Store the raw pointer without reference count updates.
   */
  void store(T* ptr) {
    this->ptr = pack(ptr);
  }

  /**
   * Unpack a raw pointer after loading.
   */
  static T* unpack(int64_t ptr) {
    return reinterpret_cast<T*>(ptr);
  }

  /**
   * Pack a raw pointer before storing.
   */
  static int64_t pack(T* ptr) {
    return reinterpret_cast<int64_t>(ptr);
  }

  /**
   * Raw pointer.
   */
  int64_t ptr:(8*sizeof(int64_t) - 2);

  /**
   * Is this an acyclic edge?
   */
  bool a:1;

  /**
   * Is this a bridge edge?
   */
  bool b:1;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};

template<class T>
struct unwrap_pointer<Shared<T>> {
  using type = T;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* o = unpack(ptr);
  if (b) {
    if (!o->isUniqueHead_()) {  // last reference optimization
      /* copy biconnected component */
      assert(!biconnected_copy());
      biconnected_copy(true);
      assert(biconnected_copy());
      o = static_cast<T*>(BiconnectedCopier(o).visit(static_cast<Any*>(o)));
      biconnected_copy(true);
      assert(!biconnected_copy());

      /* replace pointer */
      o->incShared_();
      auto old = unpack(ptr);
      ptr = pack(o);
      old->decSharedBridge_();
    }
    b = false;  // no longer a bridge
  }
  return o;
}

template<class T>
void libbirch::Shared<T>::bridge() {
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  T* o = unpack(ptr);
  if (!b) {
    /* the copy is *not* of a biconnected component here, use the
     * general-purpose Copier for this */
    assert(!biconnected_copy());
    biconnected_copy(true);
    assert(biconnected_copy());
    o = static_cast<T*>(Copier().visit(static_cast<Any*>(o)));
    biconnected_copy(true);
    assert(!biconnected_copy());
  }
  return Shared<T>(o, b);
}
<commit_msg>Further tweaks to SFINAE.<commit_after>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class BiconnectedCollector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
  friend class Destroyer;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(pack(ptr)),
      a(ptr->isAcyclic_()),
      b(b) {
    if (ptr) {
      ptr->incShared_();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(o.ptr), a(o.a), b(o.b) {
    if (ptr) {
      if (biconnected_copy()) {
        if (b) {
          unpack(ptr)->incShared_();
        } else {
          // deferred until Copier or BiconnectedCopier visits and updates
        }
      } else {
        if (b) {
          store(o.get());  // copy next biconnected component
          b = false;
        }
        unpack(ptr)->incShared_();
      }
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      ptr(pack(o.get())),
      a(o.a),
      b(false) {
    if (ptr) {
      unpack(ptr)->incShared_();
    }
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) : ptr(o.ptr), a(o.a), b(o.b) {
    o.store(nullptr);
    o.a = false;
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) : ptr(o.ptr), a(o.a), b(o.b) {
    o.store(nullptr);
    o.a = false;
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    replace(o);
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o);
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    replace(std::move(o));
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    replace(std::move(o));
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<!std::is_base_of<T,U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<!std::is_base_of<T,U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return ptr != 0;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer without copy-on-use.
   */
  T* load() const {
    return unpack(ptr);
  }

  /**
   * Bridge finding. Finds bridges in the reachable graph. Must be followed by
   * copy() for correct behavior.
   */
  void bridge();

  /**
   * Bridge finding.
   */
  void bridge() const {
    return const_cast<Shared<T>*>(this)->bridge();
  }

  /**
   * Deep copy. Copies the subgraph up to the nearest reachable bridges, the
   * remainder deferred until needed. If bridge() has been called previously,
   * this constitutes a lazy copy, otherwise an eager copy. It is correct
   * either way.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Replace.
   */
  template<class U>
  void replace(const Shared<U>& o) {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    /* when duplicating a pointer, may need to trigger a biconnected copy */
    auto ptr1 = o.get();
    if (ptr1) {
      ptr1->incShared_();
    }

    this->ptr = pack(ptr1);
    this->a = o.a;
    this->b = false;  // if it was a bridge, now copied

    if (ptr) {
      if (ptr == ptr1) {
        ptr->decSharedReachable_();
      } else if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }
  }

  /**
   * Replace.
   */
  template<class U>
  void replace(Shared<U>&& o) {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = o.ptr;
    this->a = o.a;
    this->b = o.b;

    if (ptr) {
      if (ptr == unpack(this->ptr)) {
        ptr->decSharedReachable_();
      } else if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }

    o.ptr = 0;
    o.a = false;
    o.b = false;
  }

  /**
   * Release the referent.
   */
  void release() {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = 0;
    this->a = false;
    this->b = false;

    if (ptr) {
      if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decShared_();
      }
    }
  }

  /**
   * Release the referent, during collection of a biconnected component.
   */
  void releaseBiconnected() {
    auto ptr = unpack(this->ptr);
    auto a = this->a;
    auto b = this->b;

    this->ptr = 0;
    this->a = false;
    this->b = false;

    if (ptr) {
      if (a) {
        ptr->decSharedAcyclic_();
      } else if (b) {
        ptr->decSharedBridge_();
      } else {
        ptr->decSharedBiconnected_();
      }
    }
  }

  /**
   * Dereference.
   */
  T& operator*() {
    return *get();
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() {
    return get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) const {
    return const_cast<Shared<T>*>(this)->operator()(std::forward<Args>(args)...);
  }

private:
  /**
   * Store the raw pointer without reference count updates.
   */
  void store(T* ptr) {
    this->ptr = pack(ptr);
  }

  /**
   * Unpack a raw pointer after loading.
   */
  static T* unpack(int64_t ptr) {
    return reinterpret_cast<T*>(ptr);
  }

  /**
   * Pack a raw pointer before storing.
   */
  static int64_t pack(T* ptr) {
    return reinterpret_cast<int64_t>(ptr);
  }

  /**
   * Raw pointer.
   */
  int64_t ptr:(8*sizeof(int64_t) - 2);

  /**
   * Is this an acyclic edge?
   */
  bool a:1;

  /**
   * Is this a bridge edge?
   */
  bool b:1;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};

template<class T>
struct unwrap_pointer<Shared<T>> {
  using type = T;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* o = unpack(ptr);
  if (b) {
    if (!o->isUniqueHead_()) {  // last reference optimization
      /* copy biconnected component */
      assert(!biconnected_copy());
      biconnected_copy(true);
      assert(biconnected_copy());
      o = static_cast<T*>(BiconnectedCopier(o).visit(static_cast<Any*>(o)));
      biconnected_copy(true);
      assert(!biconnected_copy());

      /* replace pointer */
      o->incShared_();
      auto old = unpack(ptr);
      ptr = pack(o);
      old->decSharedBridge_();
    }
    b = false;  // no longer a bridge
  }
  return o;
}

template<class T>
void libbirch::Shared<T>::bridge() {
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  T* o = unpack(ptr);
  if (!b) {
    /* the copy is *not* of a biconnected component here, use the
     * general-purpose Copier for this */
    assert(!biconnected_copy());
    biconnected_copy(true);
    assert(biconnected_copy());
    o = static_cast<T*>(Copier().visit(static_cast<Any*>(o)));
    biconnected_copy(true);
    assert(!biconnected_copy());
  }
  return Shared<T>(o, b);
}
<|endoftext|>


<commit_before>#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "symscope.h"

//
// Removes nested block statements.  We don't want basic blocks to
// span across multiple block statements or we run into trouble where
// a variable is used outside of its scope during copy propagation.
//
void compressUnnecessaryScopes(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (BlockStmt* block = dynamic_cast<BlockStmt*>(ast)) {
      if (block->loopInfo ||
          block->blockTag == BLOCK_COBEGIN ||
          block->blockTag == BLOCK_BEGIN)
        continue;
      if (block->list) {
        for_alist(Expr, stmt, block->body)
          block->insertBefore(stmt->remove());
        block->remove();
      }
    }
  }
}

//
// Applies local copy propagation ultra conservatively in the presence
// of pass by reference assuming that any argument to a call may be
// pass by reference.
//
// In the presence of threads, made even more conservative; compiler
// temps only.
//
typedef ChainHashMap<Symbol*,PointerHashFns,Symbol*> AvailableMap;

static void
copyAvailable(AvailableMap& available, CallExpr* call) {
  if (call->primitive) {
    if (!strcmp(call->primitive->name, "fscanf"))
      return;
    for_actuals(actual, call) {
      if (SymExpr* sym = dynamic_cast<SymExpr*>(actual))
        if (Symbol* copy = available.get(sym->var))
          sym->var = copy;
      if (CallExpr* call = dynamic_cast<CallExpr*>(actual))
        if (call->isPrimitive(PRIMITIVE_CAST))
          if (SymExpr* sym = dynamic_cast<SymExpr*>(call->get(2)))
            if (Symbol* copy = available.get(sym->var))
              sym->var = copy;
    }
  } else {
    for_formals_actuals(formal, actual, call) {
      if (formal->intent != INTENT_BLANK)
        continue;
      if (SymExpr* sym = dynamic_cast<SymExpr*>(actual))
        if (Symbol* copy = available.get(sym->var))
          sym->var = copy;
      if (CallExpr* call = dynamic_cast<CallExpr*>(actual))
        if (call->isPrimitive(PRIMITIVE_CAST))
          if (SymExpr* sym = dynamic_cast<SymExpr*>(call->get(2)))
            if (Symbol* copy = available.get(sym->var))
              sym->var = copy;
    }
  }
}

static void
removeAvailable(AvailableMap& available, CallExpr* call) {
  Vec<Symbol*> keys;
  available.get_keys(keys);
  Vec<BaseAST*> asts;
  collect_asts(&asts, call);
  forv_Vec(BaseAST, ast, asts) {
    if (SymExpr* sym = dynamic_cast<SymExpr*>(ast)) {
      forv_Vec(Symbol, key, keys) {
        if (key == sym->var || available.get(key) == sym->var)
          available.del(key);
      }
    }
  }
}

void localCopyPropagation(BasicBlock* bb) {
  AvailableMap available;
  forv_Vec(Expr, expr, bb->exprs) {
    // Replace rhs that match available
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* rhs = dynamic_cast<SymExpr*>(call->get(2)))
          if (Symbol* copy = available.get(rhs->var))
            rhs->var = copy;
        if (CallExpr* rhs = dynamic_cast<CallExpr*>(call->get(2)))
          copyAvailable(available, rhs);
      } else {
        copyAvailable(available, call);
      }
    }

    // Remove pairs of invalidated copies
    // This would be alot easier if we didn't have to worry about pass
    // by reference!
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(call->get(1))) {
          Vec<Symbol*> keys;
          available.get_keys(keys);
          forv_Vec(Symbol, key, keys) {
            if (key == lhs->var || available.get(key) == lhs->var)
              available.del(key);
          }
        }
        if (CallExpr* rhs = dynamic_cast<CallExpr*>(call->get(2)))
          removeAvailable(available, rhs);
      } else {
        removeAvailable(available, call);
      }
    }

    // Insert pairs of available copies
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(call->get(1))) {
          if (SymExpr* rhs = dynamic_cast<SymExpr*>(call->get(2))) {
            if (lhs->var == rhs->var)
              continue;
            if (!lhs->var->isCompilerTemp) // only compiler temps
              continue;
            if (lhs->var->isReference || rhs->var->isReference)
              continue;
            available.put(lhs->var, rhs->var);
          }
        }
      }
    }
  }
}

void localCopyPropagation(FnSymbol* fn) {
  buildBasicBlocks(fn);
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    localCopyPropagation(bb);
  }
}

//
// Removes local variables that are only targets for moves, but are
// never used anywhere.
//
void deadVariableElimination(FnSymbol* fn) {
  bool change = true;
  while (change) {
    Vec<BaseAST*> asts;
    collect_asts(&asts, fn);
    compute_sym_uses(fn);
    change = false;
    forv_Vec(BaseAST, ast, asts) {
      if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
        if (def->sym->astType != SYMBOL_VAR || def->parentSymbol != fn)
          continue; // only variables, no fields of nested types
        if (def->sym->uses.n == 0 && def->sym->defs.n <= 1) {
          forv_Vec(SymExpr, se, def->sym->defs) {
            CallExpr* call = dynamic_cast<CallExpr*>(se->parentExpr);
            Expr* rhs = call->get(2);
            if (rhs->astType == EXPR_SYM)
              call->remove();
            else
              call->replace(rhs->remove());
          }
          def->remove();
          change = true;
        }
      }
    }
  }
}

//
// Removes expression statements that have no effect.
//
void deadExpressionElimination(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (SymExpr* expr = dynamic_cast<SymExpr*>(ast)) {
      if (expr->parentExpr && expr == expr->getStmtExpr())
        expr->remove();
    } else if (CallExpr* expr = dynamic_cast<CallExpr*>(ast)) {
      if (expr->isPrimitive(PRIMITIVE_CAST) ||
          expr->isPrimitive(PRIMITIVE_GET_MEMBER))
        if (expr->parentExpr && expr == expr->getStmtExpr())
          expr->remove();
      if (expr->isPrimitive(PRIMITIVE_MOVE))
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(expr->get(1)))
          if (SymExpr* rhs = dynamic_cast<SymExpr*>(expr->get(2)))
            if (lhs->var == rhs->var)
              expr->remove();
    }
  }
}

//
// Removes gotos where the label immediately follows the goto
//
void removeUnnecessaryGotos(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (GotoStmt* gotoStmt = dynamic_cast<GotoStmt*>(ast))
      if (DefExpr* def = dynamic_cast<DefExpr*>(gotoStmt->next))
        if (def->sym == gotoStmt->label)
          gotoStmt->remove();
  }
}

//
// Remove unused labels
//
void removeUnusedLabels(FnSymbol* fn) {
  Vec<BaseAST*> labels;
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (GotoStmt* gotoStmt = dynamic_cast<GotoStmt*>(ast))
      labels.set_add(gotoStmt->label);
  }
  forv_Vec(BaseAST, ast, asts) {
    if (DefExpr* def = dynamic_cast<DefExpr*>(ast))
      if (LabelSymbol* label = dynamic_cast<LabelSymbol*>(def->sym))
        if (!labels.set_in(label))
          def->remove();
  }
}

void copyPropagation(void) {
  if (unoptimized)
    return;
  Vec<FnSymbol*> fns;
  collect_functions(&fns);
  forv_Vec(FnSymbol, fn, fns) {
    compressUnnecessaryScopes(fn);
    removeUnnecessaryGotos(fn);
    removeUnusedLabels(fn);
    localCopyPropagation(fn);
    deadVariableElimination(fn);
    deadExpressionElimination(fn);
  }
}
<commit_msg>Improved the effectiveness of dead variable elimination to eliminate variables that are defined multiple times but each time with moves. Previously, variables would not be removed if they had more than one definition.<commit_after>#include "astutil.h"
#include "bb.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "symscope.h"

//
// Removes nested block statements.  We don't want basic blocks to
// span across multiple block statements or we run into trouble where
// a variable is used outside of its scope during copy propagation.
//
void compressUnnecessaryScopes(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (BlockStmt* block = dynamic_cast<BlockStmt*>(ast)) {
      if (block->loopInfo ||
          block->blockTag == BLOCK_COBEGIN ||
          block->blockTag == BLOCK_BEGIN)
        continue;
      if (block->list) {
        for_alist(Expr, stmt, block->body)
          block->insertBefore(stmt->remove());
        block->remove();
      }
    }
  }
}

//
// Applies local copy propagation ultra conservatively in the presence
// of pass by reference assuming that any argument to a call may be
// pass by reference.
//
// In the presence of threads, made even more conservative; compiler
// temps only.
//
typedef ChainHashMap<Symbol*,PointerHashFns,Symbol*> AvailableMap;

static void
copyAvailable(AvailableMap& available, CallExpr* call) {
  if (call->primitive) {
    if (!strcmp(call->primitive->name, "fscanf"))
      return;
    for_actuals(actual, call) {
      if (SymExpr* sym = dynamic_cast<SymExpr*>(actual))
        if (Symbol* copy = available.get(sym->var))
          sym->var = copy;
      if (CallExpr* call = dynamic_cast<CallExpr*>(actual))
        if (call->isPrimitive(PRIMITIVE_CAST))
          if (SymExpr* sym = dynamic_cast<SymExpr*>(call->get(2)))
            if (Symbol* copy = available.get(sym->var))
              sym->var = copy;
    }
  } else {
    for_formals_actuals(formal, actual, call) {
      if (formal->intent != INTENT_BLANK)
        continue;
      if (SymExpr* sym = dynamic_cast<SymExpr*>(actual))
        if (Symbol* copy = available.get(sym->var))
          sym->var = copy;
      if (CallExpr* call = dynamic_cast<CallExpr*>(actual))
        if (call->isPrimitive(PRIMITIVE_CAST))
          if (SymExpr* sym = dynamic_cast<SymExpr*>(call->get(2)))
            if (Symbol* copy = available.get(sym->var))
              sym->var = copy;
    }
  }
}

static void
removeAvailable(AvailableMap& available, CallExpr* call) {
  Vec<Symbol*> keys;
  available.get_keys(keys);
  Vec<BaseAST*> asts;
  collect_asts(&asts, call);
  forv_Vec(BaseAST, ast, asts) {
    if (SymExpr* sym = dynamic_cast<SymExpr*>(ast)) {
      forv_Vec(Symbol, key, keys) {
        if (key == sym->var || available.get(key) == sym->var)
          available.del(key);
      }
    }
  }
}

void localCopyPropagation(BasicBlock* bb) {
  AvailableMap available;
  forv_Vec(Expr, expr, bb->exprs) {
    // Replace rhs that match available
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* rhs = dynamic_cast<SymExpr*>(call->get(2)))
          if (Symbol* copy = available.get(rhs->var))
            rhs->var = copy;
        if (CallExpr* rhs = dynamic_cast<CallExpr*>(call->get(2)))
          copyAvailable(available, rhs);
      } else {
        copyAvailable(available, call);
      }
    }

    // Remove pairs of invalidated copies
    // This would be alot easier if we didn't have to worry about pass
    // by reference!
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(call->get(1))) {
          Vec<Symbol*> keys;
          available.get_keys(keys);
          forv_Vec(Symbol, key, keys) {
            if (key == lhs->var || available.get(key) == lhs->var)
              available.del(key);
          }
        }
        if (CallExpr* rhs = dynamic_cast<CallExpr*>(call->get(2)))
          removeAvailable(available, rhs);
      } else {
        removeAvailable(available, call);
      }
    }

    // Insert pairs of available copies
    if (CallExpr* call = dynamic_cast<CallExpr*>(expr)) {
      if (call->isPrimitive(PRIMITIVE_MOVE)) {
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(call->get(1))) {
          if (SymExpr* rhs = dynamic_cast<SymExpr*>(call->get(2))) {
            if (lhs->var == rhs->var)
              continue;
            if (!lhs->var->isCompilerTemp) // only compiler temps
              continue;
            if (lhs->var->isReference || rhs->var->isReference)
              continue;
            available.put(lhs->var, rhs->var);
          }
        }
      }
    }
  }
}

void localCopyPropagation(FnSymbol* fn) {
  buildBasicBlocks(fn);
  forv_Vec(BasicBlock, bb, *fn->basicBlocks) {
    localCopyPropagation(bb);
  }
}

//
// Removes local variables that are only targets for moves, but are
// never used anywhere.
//
static bool isDeadVariable(DefExpr* def) {
  if (def->sym->uses.n > 0)
    return false;
  if (def->sym->defs.n <= 1)
    return true;
  forv_Vec(SymExpr, se, def->sym->defs) {
    if (CallExpr* call = dynamic_cast<CallExpr*>(se->parentExpr))
      if (call->isPrimitive(PRIMITIVE_MOVE))
        continue;
    return false;
  }
  return true; // only target of moves
}

void deadVariableElimination(FnSymbol* fn) {
  bool change = true;
  while (change) {
    Vec<BaseAST*> asts;
    collect_asts(&asts, fn);
    compute_sym_uses(fn);
    change = false;
    forv_Vec(BaseAST, ast, asts) {
      if (DefExpr* def = dynamic_cast<DefExpr*>(ast)) {
        if (def->sym->astType != SYMBOL_VAR || def->parentSymbol != fn)
          continue; // only variables, no fields of nested types
        if (isDeadVariable(def)) {
          forv_Vec(SymExpr, se, def->sym->defs) {
            CallExpr* call = dynamic_cast<CallExpr*>(se->parentExpr);
            Expr* rhs = call->get(2);
            if (rhs->astType == EXPR_SYM)
              call->remove();
            else
              call->replace(rhs->remove());
          }
          def->remove();
          change = true;
        }
      }
    }
  }
}

//
// Removes expression statements that have no effect.
//
void deadExpressionElimination(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (SymExpr* expr = dynamic_cast<SymExpr*>(ast)) {
      if (expr->parentExpr && expr == expr->getStmtExpr())
        expr->remove();
    } else if (CallExpr* expr = dynamic_cast<CallExpr*>(ast)) {
      if (expr->isPrimitive(PRIMITIVE_CAST) ||
          expr->isPrimitive(PRIMITIVE_GET_MEMBER))
        if (expr->parentExpr && expr == expr->getStmtExpr())
          expr->remove();
      if (expr->isPrimitive(PRIMITIVE_MOVE))
        if (SymExpr* lhs = dynamic_cast<SymExpr*>(expr->get(1)))
          if (SymExpr* rhs = dynamic_cast<SymExpr*>(expr->get(2)))
            if (lhs->var == rhs->var)
              expr->remove();
    }
  }
}

//
// Removes gotos where the label immediately follows the goto
//
void removeUnnecessaryGotos(FnSymbol* fn) {
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (GotoStmt* gotoStmt = dynamic_cast<GotoStmt*>(ast))
      if (DefExpr* def = dynamic_cast<DefExpr*>(gotoStmt->next))
        if (def->sym == gotoStmt->label)
          gotoStmt->remove();
  }
}

//
// Remove unused labels
//
void removeUnusedLabels(FnSymbol* fn) {
  Vec<BaseAST*> labels;
  Vec<BaseAST*> asts;
  collect_asts(&asts, fn);
  forv_Vec(BaseAST, ast, asts) {
    if (GotoStmt* gotoStmt = dynamic_cast<GotoStmt*>(ast))
      labels.set_add(gotoStmt->label);
  }
  forv_Vec(BaseAST, ast, asts) {
    if (DefExpr* def = dynamic_cast<DefExpr*>(ast))
      if (LabelSymbol* label = dynamic_cast<LabelSymbol*>(def->sym))
        if (!labels.set_in(label))
          def->remove();
  }
}

void copyPropagation(void) {
  if (unoptimized)
    return;
  Vec<FnSymbol*> fns;
  collect_functions(&fns);
  forv_Vec(FnSymbol, fn, fns) {
    compressUnnecessaryScopes(fn);
    removeUnnecessaryGotos(fn);
    removeUnusedLabels(fn);
    localCopyPropagation(fn);
    deadVariableElimination(fn);
    deadExpressionElimination(fn);
  }
}
<|endoftext|>


<commit_before>#pragma once

#include "RMDP.hpp"
#include "Transition.hpp"

#include <vector>
#include <memory>

using namespace std;

namespace craam{
namespace impl{

/**
Represents an MDP with implementability constraints.

Consists of an MDP and a set of observations.
*/
class MDPI{

public:
    /**
    Constructs the MDP with implementability constraints. This constructor makes it
    possible to share the MDP with other data structures.

    Important: when the underlying MDP changes externally, the object becomes invalid
    and may result in unpredictable behavior.

    \param mdp A non-robust base MDP model.
    \param state2observ Maps each state to the index of the corresponding observation.
                    A valid policy will take the same action in all states
                    with a single observation. The index is 0-based.
    \param initial A representation of the initial distribution. The rewards
                    in this transition are ignored (and should be 0).
    */
    MDPI(const shared_ptr<const RMDP>& mdp, const indvec& state2observ,
         const Transition& initial);

    /**
    Constructs the MDP with implementability constraints. The MDP model is
    copied (using the copy constructor) and stored internally.
    \param mdp A non-robust base MDP model. It cannot be shared to prevent
                direct modification.
    \param state2observ Maps each state to the index of the corresponding observation.
                    A valid policy will take the same action in all states
                    with a single observation. The index is 0-based.
    \param initial A representation of the initial distribution. The rewards
                    in this transition are ignored (and should be 0).
    */
    MDPI(const RMDP& mdp, const indvec& state2observ, const Transition& initial);

    size_t obs_count() const { return obscount; };
    size_t state_count() const {return mdp->state_count(); };
    long state2obs(long state){return state2observ[state];};
    size_t action_count(long obsid) {return action_counts[obsid];};

    /**
    Converts a policy defined in terms of observations to a policy defined in
    terms of states.
    \param obspol Policy that maps observations to actions to take
    \param statepol Optional state policy target
    */
    indvec obspol2statepol(const indvec& obspol) const;
    void obspol2statepol(const indvec& obspol, indvec& statepol) const;

    /** Internal MDP representation */
    shared_ptr<const RMDP> get_mdp() {return mdp;};

    /** Initial distribution of MDP */
    Transition get_initial() const {return initial;};

    /** Constructs a random observation policy */
    indvec random_policy(random_device::result_type seed = random_device{}());

    /**
    Computes a return of an observation policy.

    \param obspol Policy in terms of observations
    \param discount Discount factor
    \return Discounted return of the policy
    */
    prec_t total_return(const indvec& obspol, prec_t discount, prec_t precision=SOLPREC) const;

    // save and load description.
    /**
    Saves the MDPI to a set of 3 csv files, for transitions,
    observations, and the initial distribution

    \param output_mdp Transition probabilities and rewards
    \param output_state2obs Mapping states to observations
    \param output_initial Initial distribution
    */
    void to_csv(ostream& output_mdp, ostream& output_state2obs, ostream& output_initial,
                    bool headers = true) const;

    /**
    Saves the MDPI to a set of 3 csv files, for transitions, observations,
    and the initial distribution

    \param output_mdp File name for transition probabilities and rewards
    \param output_state2obs File name for mapping states to observations
    \param output_initial File name for initial distribution
    */
    void to_csv_file(const string& output_mdp, const string& output_state2obs,
                     const string& output_initial, bool headers = true) const;

    /**
    Loads an MDPI from a set of 3 csv files, for transitions, observations,
    and the initial distribution

    The MDP size is defined by the transitions file.

    \param input_mdp File name for transition probabilities and rewards
    \param input_state2obs File name for mapping states to observations
    \param input_initial File name for initial distribution
     */
    template<typename T = MDPI>
    static unique_ptr<T> from_csv(istream& input_mdp, istream& input_state2obs,
                                     istream& input_initial, bool headers = true);
    template<typename T = MDPI>
    static unique_ptr<T> from_csv_file(const string& input_mdp,
                                          const string& input_state2obs,
                                          const string& input_initial,
                                          bool headers = true);
protected:

    /** the underlying MDP */
    shared_ptr<const RMDP> mdp;
    /** maps index of a state to the index of the observation */
    indvec state2observ;
    /** initial distribution */
    Transition initial;
    /** number of observations */
    long obscount;
    /** number of actions for each observation */
    indvec action_counts;

    /**
     Checks whether the parameters are correct. Throws an exception if the parameters
     are wrong.
     */
    static void check_parameters(const RMDP& mdp, const indvec& state2observ, const Transition& initial);
};

/**
    An MDP with implementability constraints. The class contains solution
    methods that rely on robust MDP reformulation of the problem.
 */
class MDPI_R : public MDPI{

public:

    /**
    Calls the base constructor and also constructs the corresponding
    robust MDP
     */
    MDPI_R(const shared_ptr<const RMDP>& mdp, const indvec& state2observ,
            const Transition& initial);

    /**
    Calls the base constructor and also constructs the corresponding
    robust MDP.
    */
    MDPI_R(const RMDP& mdp, const indvec& state2observ, const Transition& initial);

    const RMDP& get_robust_mdp() const {
        /** Returns the internal robust MDP representation  */
        return robust_mdp;
    };

    /**
    Updates the weights on outcomes in the robust MDP based on the state
    weights provided.

    This method modifies the stored robust MDP.
     */
    void update_importance_weights(const numvec& weights);

    /**
    Uses a simple iterative algorithm to solve the MDPI.

    The algorithm starts with a policy composed of actions all 0, and
    then updates the distribution of robust outcomes (corresponding to MDP states),
    and computes the optimal solution for thus weighted RMDP.

    This method modifies the stored robust MDP.

    \param iterations Maximal number of iterations; terminates when the policy no longer changes
    \param discount Discount factor
    \param initobspol Initial observation policy (optional). When omitted or has length 0
        a policy that takes the first action is used.
    \returns Policy for observations (an index of each action for each observation)
    */
    indvec solve_reweighted(long iterations, prec_t discount, const indvec& initpol = indvec(0));

    static unique_ptr<MDPI_R> from_csv(istream& input_mdp, istream& input_state2obs,
                                     istream& input_initial, bool headers = true){

        return MDPI::from_csv<MDPI_R>(input_mdp,input_state2obs,input_initial, headers);
    };

    /** Loads the class from an set of CSV files. See also from_csv. */
    static unique_ptr<MDPI_R> from_csv_file(const string& input_mdp,
                                          const string& input_state2obs,
                                          const string& input_initial,
                                          bool headers = true){
        return MDPI::from_csv_file<MDPI_R>(input_mdp,input_state2obs,input_initial, headers);
    };

protected:
    /** Robust representation of the MDPI */
    RMDP robust_mdp;
    /** Maps the index of the mdp state to the index of the observation
    within the state corresponding to the observation (multiple states per observation) */
    indvec state2outcome;
    /** Constructs a robust version of the implementable MDP.*/
    void initialize_robustmdp();
};

}}
<commit_msg>doc update<commit_after>#pragma once

#include "RMDP.hpp"
#include "Transition.hpp"

#include <vector>
#include <memory>

using namespace std;

namespace craam{
namespace impl{

/**
Represents an MDP with implementability constraints.

Consists of an MDP and a set of observations.
*/
class MDPI{

public:
    /**
    Constructs the MDP with implementability constraints. This constructor makes it
    possible to share the MDP with other data structures.

    Important: when the underlying MDP changes externally, the object becomes invalid
    and may result in unpredictable behavior.

    \param mdp A non-robust base MDP model.
    \param state2observ Maps each state to the index of the corresponding observation.
                    A valid policy will take the same action in all states
                    with a single observation. The index is 0-based.
    \param initial A representation of the initial distribution. The rewards
                    in this transition are ignored (and should be 0).
    */
    MDPI(const shared_ptr<const RMDP>& mdp, const indvec& state2observ,
         const Transition& initial);

    /**
    Constructs the MDP with implementability constraints. The MDP model is
    copied (using the copy constructor) and stored internally.
    \param mdp A non-robust base MDP model. It cannot be shared to prevent
                direct modification.
    \param state2observ Maps each state to the index of the corresponding observation.
                    A valid policy will take the same action in all states
                    with a single observation. The index is 0-based.
    \param initial A representation of the initial distribution. The rewards
                    in this transition are ignored (and should be 0).
    */
    MDPI(const RMDP& mdp, const indvec& state2observ, const Transition& initial);

    size_t obs_count() const { return obscount; };
    size_t state_count() const {return mdp->state_count(); };
    long state2obs(long state){return state2observ[state];};
    size_t action_count(long obsid) {return action_counts[obsid];};

    /**
    Converts a policy defined in terms of observations to a policy defined in
    terms of states.
    \param obspol Policy that maps observations to actions to take
    \param statepol Optional state policy target
    */
    indvec obspol2statepol(const indvec& obspol) const;
    void obspol2statepol(const indvec& obspol, indvec& statepol) const;

    /** Internal MDP representation */
    shared_ptr<const RMDP> get_mdp() {return mdp;};

    /** Initial distribution of MDP */
    Transition get_initial() const {return initial;};

    /** Constructs a random observation policy */
    indvec random_policy(random_device::result_type seed = random_device{}());

    /**
    Computes a return of an observation policy.

    \param obspol Policy in terms of observations
    \param discount Discount factor
    \return Discounted return of the policy
    */
    prec_t total_return(const indvec& obspol, prec_t discount, prec_t precision=SOLPREC) const;

    // save and load description.
    /**
    Saves the MDPI to a set of 3 csv files, for transitions,
    observations, and the initial distribution

    \param output_mdp Transition probabilities and rewards
    \param output_state2obs Mapping states to observations
    \param output_initial Initial distribution
    */
    void to_csv(ostream& output_mdp, ostream& output_state2obs, ostream& output_initial,
                    bool headers = true) const;

    /**
    Saves the MDPI to a set of 3 csv files, for transitions, observations,
    and the initial distribution

    \param output_mdp File name for transition probabilities and rewards
    \param output_state2obs File name for mapping states to observations
    \param output_initial File name for initial distribution
    */
    void to_csv_file(const string& output_mdp, const string& output_state2obs,
                     const string& output_initial, bool headers = true) const;

    /**
    Loads an MDPI from a set of 3 csv files, for transitions, observations,
    and the initial distribution

    The MDP size is defined by the transitions file.

    \param input_mdp File name for transition probabilities and rewards
    \param input_state2obs File name for mapping states to observations
    \param input_initial File name for initial distribution
     */
    template<typename T = MDPI>
    static unique_ptr<T> from_csv(istream& input_mdp, istream& input_state2obs,
                                     istream& input_initial, bool headers = true);
    template<typename T = MDPI>
    static unique_ptr<T> from_csv_file(const string& input_mdp,
                                          const string& input_state2obs,
                                          const string& input_initial,
                                          bool headers = true);
protected:

    /** the underlying MDP */
    shared_ptr<const RMDP> mdp;
    /** maps index of a state to the index of the observation */
    indvec state2observ;
    /** initial distribution */
    Transition initial;
    /** number of observations */
    long obscount;
    /** number of actions for each observation */
    indvec action_counts;

    /**
     Checks whether the parameters are correct. Throws an exception if the parameters
     are wrong.
     */
    static void check_parameters(const RMDP& mdp, const indvec& state2observ, const Transition& initial);
};

/**
    An MDP with implementability constraints. The class contains solution
    methods that rely on robust MDP reformulation of the problem.
 */
class MDPI_R : public MDPI{

public:

    /**
    Calls the base constructor and also constructs the corresponding
    robust MDP
     */
    MDPI_R(const shared_ptr<const RMDP>& mdp, const indvec& state2observ,
            const Transition& initial);

    /**
    Calls the base constructor and also constructs the corresponding
    robust MDP.
    */
    MDPI_R(const RMDP& mdp, const indvec& state2observ, const Transition& initial);

    const RMDP& get_robust_mdp() const {
        /** Returns the internal robust MDP representation  */
        return robust_mdp;
    };

    /**
    Updates the weights on outcomes in the robust MDP based on the state
    weights provided.

    This method modifies the stored robust MDP.
     */
    void update_importance_weights(const numvec& weights);

    /**
    Uses a simple iterative algorithm to solve the MDPI.

    The algorithm starts with a policy composed of actions all 0, and
    then updates the distribution of robust outcomes (corresponding to MDP states),
    and computes the optimal solution for thus weighted RMDP.

    This method modifies the stored robust MDP.

    \param iterations Maximal number of iterations; terminates when the policy no longer changes
    \param discount Discount factor
    \param initobspol Initial observation policy (optional). When omitted or has length 0
        a policy that takes the first action (action 0) is used.
    \returns Policy for observations (an index of each action for each observation)
    */
    indvec solve_reweighted(long iterations, prec_t discount, const indvec& initpol = indvec(0));

    static unique_ptr<MDPI_R> from_csv(istream& input_mdp, istream& input_state2obs,
                                     istream& input_initial, bool headers = true){

        return MDPI::from_csv<MDPI_R>(input_mdp,input_state2obs,input_initial, headers);
    };

    /** Loads the class from an set of CSV files. See also from_csv. */
    static unique_ptr<MDPI_R> from_csv_file(const string& input_mdp,
                                          const string& input_state2obs,
                                          const string& input_initial,
                                          bool headers = true){
        return MDPI::from_csv_file<MDPI_R>(input_mdp,input_state2obs,input_initial, headers);
    };

protected:
    /** Robust representation of the MDPI */
    RMDP robust_mdp;
    /** Maps the index of the mdp state to the index of the observation
    within the state corresponding to the observation (multiple states per observation) */
    indvec state2outcome;
    /** Constructs a robust version of the implementable MDP.*/
    void initialize_robustmdp();
};

}}
<|endoftext|>