<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
#include "opencv2/photo.hpp"

#include "seamless_cloning.hpp"

using namespace std;
using namespace cv;

void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
{
    CV_INSTRUMENT_REGION();

    const Mat src  = _src.getMat();
    const Mat dest = _dst.getMat();
    const Mat mask = _mask.getMat();
    dest.copyTo(_blend);
    Mat blend = _blend.getMat();

    Mat gray;

    if(mask.channels() == 3)
        cvtColor(mask, gray, COLOR_BGR2GRAY );
    else
    {
        if (mask.empty())
            gray = Mat(src.rows, src.cols, CV_8UC1, Scalar(255));
        else
            mask.copyTo(gray);
    }

    Mat gray_inner = gray(Rect(1, 1, gray.cols - 2, gray.rows - 2));
    copyMakeBorder(gray_inner, gray, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(0));

    int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
    int h = gray.size().height;
    int w = gray.size().width;

    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            if(gray.at<uchar>(i,j) == 255)
            {
                miny = std::min(miny,i);
                maxy = std::max(maxy,i);
                minx = std::min(minx,j);
                maxx = std::max(maxx,j);
            }
        }
    }

    int lenx = maxx - minx + 1;
    int leny = maxy - miny + 1;

    int minxd = p.x - lenx/2;
    int minyd = p.y - leny/2;

    Rect roi_d(minxd,minyd,lenx,leny);
    Rect roi_s(minx,miny,lenx,leny);

    Mat destinationROI = dest(roi_d).clone();

    Mat sourceROI = Mat::zeros(leny, lenx, src.type());
    src(roi_s).copyTo(sourceROI,gray(roi_s));

    Mat maskROI = gray(roi_s);
    Mat recoveredROI = blend(roi_d);

    Cloning obj;
    obj.normalClone(destinationROI,sourceROI,maskROI,recoveredROI,flags);
}

void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float red, float green, float blue)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask  = _mask.getMat();
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();

    Mat gray, cs_mask;

    if(mask.channels() == 3)
        cvtColor(mask, gray, COLOR_BGR2GRAY );
    else
        mask.copyTo(gray);

    src.copyTo(cs_mask,gray);

    Cloning obj;
    obj.localColorChange(src,cs_mask,gray,blend,red,green,blue);
}

void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float alpha, float beta)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask  = _mask.getMat();
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();

    Mat gray, cs_mask;

    if(mask.channels() == 3)
        cvtColor(mask, gray, COLOR_BGR2GRAY );
    else
        mask.copyTo(gray);

    src.copyTo(cs_mask,gray);

    Cloning obj;
    obj.illuminationChange(src,cs_mask,gray,blend,alpha,beta);

}

void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
                           float low_threshold, float high_threshold, int kernel_size)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask  = _mask.getMat();
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();
    Mat gray, cs_mask;

    if(mask.channels() == 3)
        cvtColor(mask, gray, COLOR_BGR2GRAY );
    else
        mask.copyTo(gray);

    src.copyTo(cs_mask,gray);

    Cloning obj;
    obj.textureFlatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend);
}
<commit_msg>Update seamless_cloning.cpp<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"
#include "opencv2/photo.hpp"

#include "seamless_cloning.hpp"

using namespace std;
using namespace cv;

static Mat checkMask(InputArray _mask, Size size)
{
    Mat mask = _mask.getMat();
    Mat gray;
    if (mask.channels() == 3)
        cvtColor(mask, gray, COLOR_BGR2GRAY);
    else
    {
        if (mask.empty())
            gray = Mat(size.height, size.width, CV_8UC1, Scalar(255));
        else
            mask.copyTo(gray);
    }

    return gray;
}

void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
{
    CV_INSTRUMENT_REGION();

    const Mat src  = _src.getMat();
    const Mat dest = _dst.getMat();
    Mat mask = checkMask(_mask, src.size());
    dest.copyTo(_blend);
    Mat blend = _blend.getMat();

    Mat mask_inner = mask(Rect(1, 1, mask.cols - 2, mask.rows - 2));
    copyMakeBorder(mask_inner, mask, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(0));

    Rect roi_s = boundingRect(mask);
    Rect roi_d(p.x - roi_s.width / 2, p.y - roi_s.height / 2, roi_s.width, roi_s.height);

    Mat destinationROI = dest(roi_d).clone();

    Mat sourceROI = Mat::zeros(roi_s.height, roi_s.width, src.type());
    src(roi_s).copyTo(sourceROI,mask(roi_s));

    Mat maskROI = mask(roi_s);
    Mat recoveredROI = blend(roi_d);

    Cloning obj;
    obj.normalClone(destinationROI,sourceROI,maskROI,recoveredROI,flags);
}

void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float red, float green, float blue)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask = checkMask(_mask, src.size());
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();

    Mat cs_mask = Mat::zeros(src.size(), src.type());
    src.copyTo(cs_mask, mask);

    Cloning obj;
    obj.localColorChange(src, cs_mask, mask, blend, red, green, blue);
}

void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float alpha, float beta)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask = checkMask(_mask, src.size());
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();

    Mat cs_mask = Mat::zeros(src.size(), src.type());
    src.copyTo(cs_mask, mask);

    Cloning obj;
    obj.illuminationChange(src, cs_mask, mask, blend, alpha, beta);

}

void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
                           float low_threshold, float high_threshold, int kernel_size)
{
    CV_INSTRUMENT_REGION();

    Mat src  = _src.getMat();
    Mat mask = checkMask(_mask, src.size());
    _dst.create(src.size(), src.type());
    Mat blend = _dst.getMat();

    Mat cs_mask = Mat::zeros(src.size(), src.type());
    src.copyTo(cs_mask, mask);

    Cloning obj;
    obj.textureFlatten(src, cs_mask, mask, low_threshold, high_threshold, kernel_size, blend);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cnttab.hxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 09:04:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _CNTTAB_HXX
#define _CNTTAB_HXX

#ifndef _SVX_STDDLG_HXX //autogen
#include <svx/stddlg.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif

#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _SV_LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif

#include "tox.hxx"
#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#ifndef _TOXMGR_HXX
#include <toxmgr.hxx>
#endif
#ifndef _SVX_CHECKLBX_HXX //autogen wg. SvxCheckListBox
#include <svx/checklbx.hxx>
#endif
#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SVTREEBOX_HXX
#include <svtools/svtreebx.hxx>
#endif
#ifndef _SV_MENUBTN_HXX
#include <vcl/menubtn.hxx>
#endif
#ifndef _SVX_LANGBOX_HXX
#include <svx/langbox.hxx>
#endif
#define TOX_PAGE_SELECT 1
#define TOX_PAGE_ENTRY  2
#define TOX_PAGE_STYLES 3

struct CurTOXType
{
    TOXTypes    eType;
    USHORT      nIndex; //for TOX_USER only

    BOOL operator==(const CurTOXType aCmp)
       {
        return eType == aCmp.eType && nIndex == aCmp.nIndex;
       }
    USHORT GetFlatIndex() const;

};

class SwOLENames : public Resource
{
    ResStringArray      aNamesAry;
public:
    SwOLENames(const ResId& rResId) :
        Resource(rResId),
        aNamesAry(ResId(1)){FreeResource();}

    ResStringArray&     GetNames() { return aNamesAry;}

};

#endif
<commit_msg>INTEGRATION: CWS residcleanup (1.14.728); FILE MERGED 2007/03/04 17:03:03 pl 1.14.728.1: #i73635# ResId cleanup<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: cnttab.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-26 09:11:32 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _CNTTAB_HXX
#define _CNTTAB_HXX

#ifndef _SVX_STDDLG_HXX //autogen
#include <svx/stddlg.hxx>
#endif

#ifndef _BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _EDIT_HXX //autogen
#include <vcl/edit.hxx>
#endif

#ifndef _FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _FIELD_HXX //autogen
#include <vcl/field.hxx>
#endif
#ifndef _SV_LSTBOX_HXX //autogen
#include <vcl/lstbox.hxx>
#endif

#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif

#include "tox.hxx"
#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#ifndef _TOXMGR_HXX
#include <toxmgr.hxx>
#endif
#ifndef _SVX_CHECKLBX_HXX //autogen wg. SvxCheckListBox
#include <svx/checklbx.hxx>
#endif
#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SVTREEBOX_HXX
#include <svtools/svtreebx.hxx>
#endif
#ifndef _SV_MENUBTN_HXX
#include <vcl/menubtn.hxx>
#endif
#ifndef _SVX_LANGBOX_HXX
#include <svx/langbox.hxx>
#endif
#define TOX_PAGE_SELECT 1
#define TOX_PAGE_ENTRY  2
#define TOX_PAGE_STYLES 3

struct CurTOXType
{
    TOXTypes    eType;
    USHORT      nIndex; //for TOX_USER only

    BOOL operator==(const CurTOXType aCmp)
       {
        return eType == aCmp.eType && nIndex == aCmp.nIndex;
       }
    USHORT GetFlatIndex() const;

};

class SwOLENames : public Resource
{
    ResStringArray      aNamesAry;
public:
    SwOLENames(const ResId& rResId) :
        Resource(rResId),
        aNamesAry(ResId(1,*rResId.GetResMgr())){FreeResource();}

    ResStringArray&     GetNames() { return aNamesAry;}

};

#endif
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeTypePch.h"

namespace Js
{
    bool DynamicObjectPropertyEnumerator::GetEnumNonEnumerable() const
    {
        return !!(flags & EnumeratorFlags::EnumNonEnumerable);
    }
    bool DynamicObjectPropertyEnumerator::GetEnumSymbols() const
    {
        return !!(flags & EnumeratorFlags::EnumSymbols);
    }
    bool DynamicObjectPropertyEnumerator::GetSnapShotSemantics() const
    {
        return !!(flags & EnumeratorFlags::SnapShotSemantics);
    }

    bool DynamicObjectPropertyEnumerator::GetUseCache() const
    {
#if ENABLE_TTD
        if(this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode())
        {
            return false;
        }
#endif

        return ((flags & (EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::UseCache)) == (EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::UseCache));
    }

    void DynamicObjectPropertyEnumerator::Initialize(DynamicType * type, CachedData * data, Js::BigPropertyIndex initialPropertyCount)
    {
        this->initialType = type;
        this->cachedData = data;
        this->initialPropertyCount = initialPropertyCount;
    }

    bool DynamicObjectPropertyEnumerator::Initialize(DynamicObject * object, EnumeratorFlags flags, ScriptContext * requestContext, EnumeratorCache * enumeratorCache)
    {
        this->scriptContext = requestContext;
        this->object = object;
        this->flags = flags;

        if (!object)
        {
            this->cachedData = nullptr;
            return true;
        }

        this->objectIndex = Constants::NoBigSlot;
        this->enumeratedCount = 0;

        if (!GetUseCache())
        {
            if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object))
            {
                return false;
            }
            Initialize(object->GetDynamicType(), nullptr, GetSnapShotSemantics() ? this->object->GetPropertyCount() : Constants::NoBigSlot);
            return true;
        }

        DynamicType * type = object->GetDynamicType();

        CachedData * data;
        if (enumeratorCache && type == enumeratorCache->type)
        {
            data = (CachedData *)enumeratorCache->data;

            Assert(data != nullptr);
            Assert(data->scriptContext == this->scriptContext); // The cache data script context should be the same as request context

            if (data->enumNonEnumerable == GetEnumNonEnumerable())
            {
                Initialize(type, data, data->propertyCount);
                return true;
            }
        }

        data = (CachedData *)requestContext->GetThreadContext()->GetDynamicObjectEnumeratorCache(type);

        if (data != nullptr && data->scriptContext == this->scriptContext && data->enumNonEnumerable == GetEnumNonEnumerable() && data->enumSymbols == GetEnumSymbols())
        {
            Initialize(type, data, data->propertyCount);

            if (enumeratorCache)
            {
                enumeratorCache->type = type;
                enumeratorCache->data = data;
            }
            return true;
        }

        if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object))
        {
            return false;
        }

        // Reload the type after EnsureObjecteReady
        type = object->GetDynamicType();
        if (!type->PrepareForTypeSnapshotEnumeration())
        {
            Initialize(type, nullptr, object->GetPropertyCount());
            return true;
        }

        uint propertyCount = this->object->GetPropertyCountForEnum();
        data = RecyclerNewStructPlus(requestContext->GetRecycler(),
            propertyCount * sizeof(Field(PropertyString*)) + propertyCount * sizeof(BigPropertyIndex) + propertyCount * sizeof(PropertyAttributes), CachedData);
        data->scriptContext = requestContext;
        data->cachedCount = 0;
        data->propertyCount = propertyCount;
        data->strings = reinterpret_cast<Field(PropertyString*)*>(data + 1);
        data->indexes = unsafe_write_barrier_cast<BigPropertyIndex *>(data->strings + propertyCount);
        data->attributes = (PropertyAttributes*)(data->indexes + propertyCount);
        data->completed = false;
        data->enumNonEnumerable = GetEnumNonEnumerable();
        data->enumSymbols = GetEnumSymbols();
        requestContext->GetThreadContext()->AddDynamicObjectEnumeratorCache(type, data);
        Initialize(type, data, propertyCount);

        if (enumeratorCache)
        {
            enumeratorCache->type = type;
            enumeratorCache->data = data;
        }
        return true;
    }

    bool DynamicObjectPropertyEnumerator::IsNullEnumerator() const
    {
        return this->object == nullptr;
    }

    bool DynamicObjectPropertyEnumerator::CanUseJITFastPath() const
    {
#if ENABLE_TTD
        TTDAssert(this->cachedData == nullptr || !this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode(), "We should always have cachedData null if we are in record or replay mode");
#endif

        return !this->IsNullEnumerator() && !GetEnumNonEnumerable() && this->cachedData != nullptr;
    }

    void DynamicObjectPropertyEnumerator::Clear(EnumeratorFlags flags, ScriptContext * requestContext)
    {
        Initialize(nullptr, flags, requestContext, nullptr);
    }

    void DynamicObjectPropertyEnumerator::Reset()
    {
        Initialize(object, flags, scriptContext, nullptr);
    }

    DynamicType * DynamicObjectPropertyEnumerator::GetTypeToEnumerate() const
    {
        return
            GetSnapShotSemantics() &&
            initialType->GetIsLocked() &&
            CONFIG_FLAG(TypeSnapshotEnumeration)
            ? PointerValue(initialType)
            : object->GetDynamicType();
    }

    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNextWithCache(PropertyId& propertyId, PropertyAttributes* attributes)
    {
#if ENABLE_TTD
        AssertMsg(!this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode(), "We should always trap out to explicit enumeration in this case");
#endif

        Assert(enumeratedCount <= cachedData->cachedCount);
        JavascriptString* propertyStringName;
        PropertyAttributes propertyAttributes = PropertyNone;
        if (enumeratedCount < cachedData->cachedCount)
        {
            PropertyString * propertyString = cachedData->strings[enumeratedCount];
            propertyStringName = propertyString;
            propertyId = propertyString->GetPropertyId();

#if DBG
            PropertyId tempPropertyId;
            /* JavascriptString * tempPropertyString = */ this->MoveAndGetNextNoCache(tempPropertyId, attributes);

            Assert(tempPropertyId == propertyId);
            Assert(this->objectIndex == cachedData->indexes[enumeratedCount]);
#endif

            this->objectIndex = cachedData->indexes[enumeratedCount];
            propertyAttributes = cachedData->attributes[enumeratedCount];

            enumeratedCount++;
        }
        else if (!cachedData->completed)
        {
            propertyStringName = this->MoveAndGetNextNoCache(propertyId, &propertyAttributes);

            if (propertyStringName)
            {
                PropertyString* propertyString = JavascriptOperators::TryFromVar<PropertyString>(propertyStringName);
                if (propertyString != nullptr)
                {
                    Assert(enumeratedCount < this->initialPropertyCount);
                    cachedData->strings[enumeratedCount] = propertyString;
                    cachedData->indexes[enumeratedCount] = this->objectIndex;
                    cachedData->attributes[enumeratedCount] = propertyAttributes;
                    cachedData->cachedCount = ++enumeratedCount;
                }
            }
            else
            {
                cachedData->completed = true;
            }
        }
        else
        {
#if DBG
            PropertyId tempPropertyId;
            Assert(this->MoveAndGetNextNoCache(tempPropertyId, attributes) == nullptr);
#endif

            propertyStringName = nullptr;
        }

        if (attributes != nullptr)
        {
            *attributes = propertyAttributes;
        }

        return propertyStringName;
    }
    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNextNoCache(PropertyId& propertyId, PropertyAttributes * attributes)
    {
        JavascriptString* propertyString = nullptr;
        BigPropertyIndex newIndex = this->objectIndex;
        PropertyValueInfo info;
        RecyclableObject * startingObject = this->object;
        do
        {
            newIndex++;
            PropertyValueInfo::ClearCacheInfo(&info);
            if (!this->object->FindNextProperty(newIndex, &propertyString, &propertyId, attributes,
                GetTypeToEnumerate(), flags, this->scriptContext, &info)
                || (GetSnapShotSemantics() && PropertyIndexToPropertyEnumeration(newIndex) >= initialPropertyCount))
            {
                // No more properties
                newIndex--;
                propertyString = nullptr;
                PropertyValueInfo::ClearCacheInfo(&info);
                break;
            }
        } while (Js::IsInternalPropertyId(propertyId));

        if (info.GetPropertyRecordUsageCache() != nullptr && info.GetPropertyRecordUsageCache()->ShouldUseCache() && propertyString == info.GetProperty())
        {
            CacheOperators::CachePropertyRead(startingObject, this->object, false, propertyId, false, &info, scriptContext);
            if ((!(this->flags & EnumeratorFlags::EphemeralReference)) && info.IsStoreFieldCacheEnabled() && info.IsWritable() && ((info.GetFlags() & (InlineCacheGetterFlag | InlineCacheSetterFlag)) == 0))
            {
                PropertyValueInfo::SetCacheInfo(&info, info.GetPropertyRecordUsageCache()->GetStElemInlineCache(), info.AllowResizingPolymorphicInlineCache());
                CacheOperators::CachePropertyWrite(this->object, false, this->object->GetType(), propertyId, &info, scriptContext);
            }
        }
        this->objectIndex = newIndex;
        return propertyString;
    }

    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNext(PropertyId& propertyId, PropertyAttributes * attributes)
    {
        propertyId = Js::Constants::NoProperty;
        if (this->cachedData && this->initialType == this->object->GetDynamicType())
        {
            return MoveAndGetNextWithCache(propertyId, attributes);
        }
        if (this->object)
        {
            // Once enters NoCache path, ensure never switches to Cache path above.
            this->cachedData = nullptr;
            return MoveAndGetNextNoCache(propertyId, attributes);
        }
        return nullptr;
    }
}
<commit_msg>Objecte -> Object<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeTypePch.h"

namespace Js
{
    bool DynamicObjectPropertyEnumerator::GetEnumNonEnumerable() const
    {
        return !!(flags & EnumeratorFlags::EnumNonEnumerable);
    }
    bool DynamicObjectPropertyEnumerator::GetEnumSymbols() const
    {
        return !!(flags & EnumeratorFlags::EnumSymbols);
    }
    bool DynamicObjectPropertyEnumerator::GetSnapShotSemantics() const
    {
        return !!(flags & EnumeratorFlags::SnapShotSemantics);
    }

    bool DynamicObjectPropertyEnumerator::GetUseCache() const
    {
#if ENABLE_TTD
        if(this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode())
        {
            return false;
        }
#endif

        return ((flags & (EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::UseCache)) == (EnumeratorFlags::SnapShotSemantics | EnumeratorFlags::UseCache));
    }

    void DynamicObjectPropertyEnumerator::Initialize(DynamicType * type, CachedData * data, Js::BigPropertyIndex initialPropertyCount)
    {
        this->initialType = type;
        this->cachedData = data;
        this->initialPropertyCount = initialPropertyCount;
    }

    bool DynamicObjectPropertyEnumerator::Initialize(DynamicObject * object, EnumeratorFlags flags, ScriptContext * requestContext, EnumeratorCache * enumeratorCache)
    {
        this->scriptContext = requestContext;
        this->object = object;
        this->flags = flags;

        if (!object)
        {
            this->cachedData = nullptr;
            return true;
        }

        this->objectIndex = Constants::NoBigSlot;
        this->enumeratedCount = 0;

        if (!GetUseCache())
        {
            if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object))
            {
                return false;
            }
            Initialize(object->GetDynamicType(), nullptr, GetSnapShotSemantics() ? this->object->GetPropertyCount() : Constants::NoBigSlot);
            return true;
        }

        DynamicType * type = object->GetDynamicType();

        CachedData * data;
        if (enumeratorCache && type == enumeratorCache->type)
        {
            data = (CachedData *)enumeratorCache->data;

            Assert(data != nullptr);
            Assert(data->scriptContext == this->scriptContext); // The cache data script context should be the same as request context

            if (data->enumNonEnumerable == GetEnumNonEnumerable())
            {
                Initialize(type, data, data->propertyCount);
                return true;
            }
        }

        data = (CachedData *)requestContext->GetThreadContext()->GetDynamicObjectEnumeratorCache(type);

        if (data != nullptr && data->scriptContext == this->scriptContext && data->enumNonEnumerable == GetEnumNonEnumerable() && data->enumSymbols == GetEnumSymbols())
        {
            Initialize(type, data, data->propertyCount);

            if (enumeratorCache)
            {
                enumeratorCache->type = type;
                enumeratorCache->data = data;
            }
            return true;
        }

        if (!object->GetDynamicType()->GetTypeHandler()->EnsureObjectReady(object))
        {
            return false;
        }

        // Reload the type after EnsureObjectReady
        type = object->GetDynamicType();
        if (!type->PrepareForTypeSnapshotEnumeration())
        {
            Initialize(type, nullptr, object->GetPropertyCount());
            return true;
        }

        uint propertyCount = this->object->GetPropertyCountForEnum();
        data = RecyclerNewStructPlus(requestContext->GetRecycler(),
            propertyCount * sizeof(Field(PropertyString*)) + propertyCount * sizeof(BigPropertyIndex) + propertyCount * sizeof(PropertyAttributes), CachedData);
        data->scriptContext = requestContext;
        data->cachedCount = 0;
        data->propertyCount = propertyCount;
        data->strings = reinterpret_cast<Field(PropertyString*)*>(data + 1);
        data->indexes = unsafe_write_barrier_cast<BigPropertyIndex *>(data->strings + propertyCount);
        data->attributes = (PropertyAttributes*)(data->indexes + propertyCount);
        data->completed = false;
        data->enumNonEnumerable = GetEnumNonEnumerable();
        data->enumSymbols = GetEnumSymbols();
        requestContext->GetThreadContext()->AddDynamicObjectEnumeratorCache(type, data);
        Initialize(type, data, propertyCount);

        if (enumeratorCache)
        {
            enumeratorCache->type = type;
            enumeratorCache->data = data;
        }
        return true;
    }

    bool DynamicObjectPropertyEnumerator::IsNullEnumerator() const
    {
        return this->object == nullptr;
    }

    bool DynamicObjectPropertyEnumerator::CanUseJITFastPath() const
    {
#if ENABLE_TTD
        TTDAssert(this->cachedData == nullptr || !this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode(), "We should always have cachedData null if we are in record or replay mode");
#endif

        return !this->IsNullEnumerator() && !GetEnumNonEnumerable() && this->cachedData != nullptr;
    }

    void DynamicObjectPropertyEnumerator::Clear(EnumeratorFlags flags, ScriptContext * requestContext)
    {
        Initialize(nullptr, flags, requestContext, nullptr);
    }

    void DynamicObjectPropertyEnumerator::Reset()
    {
        Initialize(object, flags, scriptContext, nullptr);
    }

    DynamicType * DynamicObjectPropertyEnumerator::GetTypeToEnumerate() const
    {
        return
            GetSnapShotSemantics() &&
            initialType->GetIsLocked() &&
            CONFIG_FLAG(TypeSnapshotEnumeration)
            ? PointerValue(initialType)
            : object->GetDynamicType();
    }

    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNextWithCache(PropertyId& propertyId, PropertyAttributes* attributes)
    {
#if ENABLE_TTD
        AssertMsg(!this->scriptContext->GetThreadContext()->IsRuntimeInTTDMode(), "We should always trap out to explicit enumeration in this case");
#endif

        Assert(enumeratedCount <= cachedData->cachedCount);
        JavascriptString* propertyStringName;
        PropertyAttributes propertyAttributes = PropertyNone;
        if (enumeratedCount < cachedData->cachedCount)
        {
            PropertyString * propertyString = cachedData->strings[enumeratedCount];
            propertyStringName = propertyString;
            propertyId = propertyString->GetPropertyId();

#if DBG
            PropertyId tempPropertyId;
            /* JavascriptString * tempPropertyString = */ this->MoveAndGetNextNoCache(tempPropertyId, attributes);

            Assert(tempPropertyId == propertyId);
            Assert(this->objectIndex == cachedData->indexes[enumeratedCount]);
#endif

            this->objectIndex = cachedData->indexes[enumeratedCount];
            propertyAttributes = cachedData->attributes[enumeratedCount];

            enumeratedCount++;
        }
        else if (!cachedData->completed)
        {
            propertyStringName = this->MoveAndGetNextNoCache(propertyId, &propertyAttributes);

            if (propertyStringName)
            {
                PropertyString* propertyString = JavascriptOperators::TryFromVar<PropertyString>(propertyStringName);
                if (propertyString != nullptr)
                {
                    Assert(enumeratedCount < this->initialPropertyCount);
                    cachedData->strings[enumeratedCount] = propertyString;
                    cachedData->indexes[enumeratedCount] = this->objectIndex;
                    cachedData->attributes[enumeratedCount] = propertyAttributes;
                    cachedData->cachedCount = ++enumeratedCount;
                }
            }
            else
            {
                cachedData->completed = true;
            }
        }
        else
        {
#if DBG
            PropertyId tempPropertyId;
            Assert(this->MoveAndGetNextNoCache(tempPropertyId, attributes) == nullptr);
#endif

            propertyStringName = nullptr;
        }

        if (attributes != nullptr)
        {
            *attributes = propertyAttributes;
        }

        return propertyStringName;
    }
    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNextNoCache(PropertyId& propertyId, PropertyAttributes * attributes)
    {
        JavascriptString* propertyString = nullptr;
        BigPropertyIndex newIndex = this->objectIndex;
        PropertyValueInfo info;
        RecyclableObject * startingObject = this->object;
        do
        {
            newIndex++;
            PropertyValueInfo::ClearCacheInfo(&info);
            if (!this->object->FindNextProperty(newIndex, &propertyString, &propertyId, attributes,
                GetTypeToEnumerate(), flags, this->scriptContext, &info)
                || (GetSnapShotSemantics() && PropertyIndexToPropertyEnumeration(newIndex) >= initialPropertyCount))
            {
                // No more properties
                newIndex--;
                propertyString = nullptr;
                PropertyValueInfo::ClearCacheInfo(&info);
                break;
            }
        } while (Js::IsInternalPropertyId(propertyId));

        if (info.GetPropertyRecordUsageCache() != nullptr && info.GetPropertyRecordUsageCache()->ShouldUseCache() && propertyString == info.GetProperty())
        {
            CacheOperators::CachePropertyRead(startingObject, this->object, false, propertyId, false, &info, scriptContext);
            if ((!(this->flags & EnumeratorFlags::EphemeralReference)) && info.IsStoreFieldCacheEnabled() && info.IsWritable() && ((info.GetFlags() & (InlineCacheGetterFlag | InlineCacheSetterFlag)) == 0))
            {
                PropertyValueInfo::SetCacheInfo(&info, info.GetPropertyRecordUsageCache()->GetStElemInlineCache(), info.AllowResizingPolymorphicInlineCache());
                CacheOperators::CachePropertyWrite(this->object, false, this->object->GetType(), propertyId, &info, scriptContext);
            }
        }
        this->objectIndex = newIndex;
        return propertyString;
    }

    JavascriptString * DynamicObjectPropertyEnumerator::MoveAndGetNext(PropertyId& propertyId, PropertyAttributes * attributes)
    {
        propertyId = Js::Constants::NoProperty;
        if (this->cachedData && this->initialType == this->object->GetDynamicType())
        {
            return MoveAndGetNextWithCache(propertyId, attributes);
        }
        if (this->object)
        {
            // Once enters NoCache path, ensure never switches to Cache path above.
            this->cachedData = nullptr;
            return MoveAndGetNextNoCache(propertyId, attributes);
        }
        return nullptr;
    }
}
<|endoftext|>


<commit_before>//===--- AccessedStorageAnalysis.cpp  - Accessed Storage Analysis ---------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-sea"

#include "swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h"
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
#include "swift/SILOptimizer/Analysis/FunctionOrder.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"

using namespace swift;

// -----------------------------------------------------------------------------
// MARK: Accessing the results.
// -----------------------------------------------------------------------------

bool AccessedStorageResult::hasNoNestedConflict(
    const AccessedStorage &otherStorage) const {
  assert(otherStorage.isUniquelyIdentified());
  assert(!hasUnidentifiedAccess());

  return getStorageAccessInfo(otherStorage).hasNoNestedConflict();
}

bool AccessedStorageResult::mayConflictWith(
    SILAccessKind otherAccessKind, const AccessedStorage &otherStorage) const {
  if (hasUnidentifiedAccess()
      && accessKindMayConflict(otherAccessKind,
                               unidentifiedAccess.getValue())) {
    return true;
  }
  for (auto &storageAccess : storageAccessSet) {
    assert(storageAccess && "FunctionAccessedStorage mapped invalid storage.");

    if (!accessKindMayConflict(otherAccessKind, storageAccess.getAccessKind()))
      continue;

    if (!otherStorage.isDistinctFrom(storageAccess))
      return true;
  }
  return false;
}

StorageAccessInfo AccessedStorageResult::getStorageAccessInfo(
    const AccessedStorage &otherStorage) const {
  // Construct a fake StorageAccessInfo to do a hash lookup for the real
  // StorageAccessInfo. The DenseSet key is limited to the AccessedStorage base
  // class members.
  StorageAccessInfo storageKey(otherStorage, SILAccessKind::Read, false);
  auto iter = storageAccessSet.find(storageKey);
  assert(iter != storageAccessSet.end());
  return *iter;
}

// -----------------------------------------------------------------------------
// MARK: Constructing the results.
// -----------------------------------------------------------------------------

static bool updateAccessKind(SILAccessKind &LHS, SILAccessKind RHS) {
  bool changed = false;
  // Assume we don't track Init/Deinit.
  if (LHS == SILAccessKind::Read && RHS == SILAccessKind::Modify) {
    LHS = RHS;
    changed = true;
  }
  return changed;
}

static bool updateOptionalAccessKind(Optional<SILAccessKind> &LHS,
                                     Optional<SILAccessKind> RHS) {
  if (RHS == None)
    return false;

  if (LHS == None) {
    LHS = RHS;
    return true;
  }
  return updateAccessKind(LHS.getValue(), RHS.getValue());
}

bool StorageAccessInfo::mergeFrom(const StorageAccessInfo &RHS) {
  bool changed = false;
  SILAccessKind accessKind = getAccessKind();
  assert(accessKind == SILAccessKind::Read
         || accessKind == SILAccessKind::Modify && "uninitialized info");
  if (updateAccessKind(accessKind, RHS.getAccessKind())) {
    setAccessKind(accessKind);
    changed = true;
  }
  if (hasNoNestedConflict() && !RHS.hasNoNestedConflict()) {
    setNoNestedConflict(false);
    changed = true;
  }
  return changed;
}

bool AccessedStorageResult::updateUnidentifiedAccess(SILAccessKind accessKind) {
  if (unidentifiedAccess == None) {
    unidentifiedAccess = accessKind;
    return true;
  }
  return updateAccessKind(unidentifiedAccess.getValue(), accessKind);
}

// Merge the given AccessedStorageResult in `other` into this
// AccessedStorageResult. Use the given `transformStorage` to map `other`
// AccessedStorage into this context. If `other` is from a callee, argument
// substitution will be performed if possible. However, there's no guarantee
// that the merged access values will belong to this region.
//
// Return true if these results changed, requiring further propagation through
// the call graph.
bool AccessedStorageResult::mergeAccesses(
    const AccessedStorageResult &other,
    std::function<StorageAccessInfo(const StorageAccessInfo &)>
        transformStorage) {

  // The cost of BottomUpIPAnalysis can be quadratic for large recursive call
  // graphs. That cost is multiplied by the size of storageAccessSet. Slowdowns
  // can occur ~1000 elements. 200 is large enough to cover "normal" code,
  // while ensuring compile time isn't affected.
  if (storageAccessSet.size() > 200) {
    llvm::dbgs() << "BIG SET " << storageAccessSet.size() << "\n";
    setWorstEffects();
    return true;
  }
  // To save compile time, if this storage already has worst-case effects, avoid
  // growing its storageAccessSet.
  if (hasWorstEffects())
    return false;

  // When `this` == `other` (for self-recursion), insertion in DenseMap
  // invalidates the iterator. We still need to propagate and merge in that case
  // because arguments can be recursively dependent. The alternative would be
  // treating all self-recursion conservatively.
  const AccessedStorageResult *otherRegionAccesses = &other;
  AccessedStorageResult regionAccessCopy;
  if (this == &other) {
    regionAccessCopy = other;
    otherRegionAccesses = &regionAccessCopy;
  }
  bool changed = false;
  // Nondeterminstically iterate for the sole purpose of inserting into another
  // unordered set.
  for (auto &rawStorageInfo : otherRegionAccesses->storageAccessSet) {
    const StorageAccessInfo &otherStorageInfo =
        transformStorage(rawStorageInfo);
    // If transformStorage() returns invalid storage object for local storage,
    // that should not be merged with the caller.
    if (!otherStorageInfo)
      continue;

    if (otherStorageInfo.getKind() == AccessedStorage::Unidentified) {
      changed |= updateUnidentifiedAccess(otherStorageInfo.getAccessKind());
      continue;
    }
    // Attempt to add identified AccessedStorage to this map.
    auto result = insertStorageAccess(otherStorageInfo);
    if (result.second) {
      // A new AccessedStorage key was added to this map.
      changed = true;
      continue;
    }
    // Merge StorageAccessInfo into already-mapped AccessedStorage.
    changed |= result.first->mergeFrom(otherStorageInfo);
  }
  if (other.unidentifiedAccess != None)
    changed |= updateUnidentifiedAccess(other.unidentifiedAccess.getValue());

  return changed;
}

bool AccessedStorageResult::mergeFrom(const AccessedStorageResult &other) {
  // Merge accesses from other. Both `this` and `other` are either from the same
  // function or are both callees of the same call site, so their parameters
  // indices coincide. transformStorage is the identity function.
  return mergeAccesses(other, [](const StorageAccessInfo &s) { return s; });
}

/// Returns the argument of the full apply or partial apply corresponding to the
/// callee's parameter index, or returns an invalid SILValue if the applied
/// closure cannot be found. This walks up the apply chain starting at the given
/// `fullApply` to find the applied argument.
static SILValue getCallerArg(FullApplySite fullApply, unsigned paramIndex) {
  if (paramIndex < fullApply.getNumArguments())
    return fullApply.getArgument(paramIndex);

  SILValue callee = fullApply.getCalleeOrigin();
  auto *PAI = dyn_cast<PartialApplyInst>(callee);
  if (!PAI)
    return SILValue();

  unsigned appliedIndex =
    paramIndex - ApplySite(PAI).getCalleeArgIndexOfFirstAppliedArg();
  if (appliedIndex < PAI->getNumArguments())
    return PAI->getArgument(appliedIndex);

  // This must be a chain of partial_applies. We don't expect this in practice,
  // so handle it conservatively.
  return SILValue();
}

/// Transform AccessedStorage from a callee into the caller context. If this is
/// uniquely identified local storage, then return an invalid storage object.
///
/// For correctness, AccessEnforcementOpts relies on all Argument access to
/// either be mapped into the caller's context or marked as an unidentified
/// access at the call site.
///
/// Note: This does *not* map the storage index into the caller function's index
/// range. (When the storage value doesn't need to be remapped, it returns the
/// original storage value.) It's simpler to set the storage index later when it
/// is actually added to the function's storageAccessSet.
static StorageAccessInfo
transformCalleeStorage(const StorageAccessInfo &storage,
                       FullApplySite fullApply) {
  switch (storage.getKind()) {
  case AccessedStorage::Box:
  case AccessedStorage::Stack:
    // Do not merge local storage.
    return StorageAccessInfo(AccessedStorage(), storage);
  case AccessedStorage::Global:
    // Global accesses is universal.
    return storage;
  case AccessedStorage::Class: {
    // If the object's value is an argument, translate it into a value on the
    // caller side.
    SILValue obj = storage.getObject();
    if (auto *arg = dyn_cast<SILFunctionArgument>(obj)) {
      SILValue argVal = getCallerArg(fullApply, arg->getIndex());
      if (argVal) {
        unsigned idx = storage.getPropertyIndex();
        // Remap this storage info. The argument source value is now the new
        // object. The old storage info is inherited.
        return StorageAccessInfo(AccessedStorage::forClass(argVal, idx),
                                 storage);
      }
    }
    // Otherwise, continue to reference the value in the callee because we don't
    // have any better placeholder for a callee-defined object.
    return storage;
  }
  case AccessedStorage::Argument: {
    // Transitively search for the storage base in the caller.
    SILValue argVal = getCallerArg(fullApply, storage.getParamIndex());
    if (argVal) {
      // Remap the argument source value and inherit the old storage info.
      auto calleeStorage = findAccessedStorageNonNested(argVal);
      if (calleeStorage)
        return StorageAccessInfo(calleeStorage, storage);
    }
    // If the argument can't be transformed, demote it to an unidentified
    // access.
    //
    // This is an untested bailout. It is only reachable if the call graph
    // contains an edge that getCallerArg is unable to analyze OR if
    // findAccessedStorageNonNested returns an invalid SILValue, which won't
    // pass SIL verification.
    //
    // FIXME: In case argVal is invalid, support Unidentified access for invalid
    // values. This would also be useful for partially invalidating results.
    return StorageAccessInfo(
        AccessedStorage(argVal, AccessedStorage::Unidentified), storage);
  }
  case AccessedStorage::Nested:
    llvm_unreachable("Unexpected nested access");
  case AccessedStorage::Yield:
    // Continue to hold on to yields from the callee because we don't have
    // any better placeholder in the callee.
    return storage;
  case AccessedStorage::Unidentified:
    // For unidentified storage, continue to reference the value in the callee
    // because we don't have any better placeholder for a callee-defined object.
    return storage;
  }
  llvm_unreachable("unhandled kind");
}

bool AccessedStorageResult::mergeFromApply(
    const AccessedStorageResult &calleeAccess, FullApplySite fullApply) {
  // Merge accesses from calleeAccess. Transform any Argument type
  // AccessedStorage into the caller context to be added to `this` storage map.
  return mergeAccesses(calleeAccess, [&fullApply](const StorageAccessInfo &s) {
    return transformCalleeStorage(s, fullApply);
  });
}

template <typename B>
void AccessedStorageResult::visitBeginAccess(B *beginAccess) {
  if (beginAccess->getEnforcement() != SILAccessEnforcement::Dynamic)
    return;

  const AccessedStorage &storage =
      findAccessedStorageNonNested(beginAccess->getSource());

  if (storage.getKind() == AccessedStorage::Unidentified) {
    // This also catches invalid storage.
    updateOptionalAccessKind(unidentifiedAccess, beginAccess->getAccessKind());
    return;
  }
  StorageAccessInfo storageAccess(storage, beginAccess);
  auto result = insertStorageAccess(storageAccess);
  if (!result.second)
    result.first->mergeFrom(storageAccess);
}

void AccessedStorageResult::analyzeInstruction(SILInstruction *I) {
  assert(!FullApplySite::isa(I) && "caller should merge");

  if (auto *BAI = dyn_cast<BeginAccessInst>(I))
    visitBeginAccess(BAI);
  else if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(I))
    visitBeginAccess(BUAI);
}

void StorageAccessInfo::print(raw_ostream &os) const {
  os << "  [" << getSILAccessKindName(getAccessKind()) << "] ";
  if (hasNoNestedConflict())
    os << "[no_nested_conflict] ";
  AccessedStorage::print(os);
}

void StorageAccessInfo::dump() const { print(llvm::dbgs()); }

void AccessedStorageResult::print(raw_ostream &os) const {
  for (auto &storageAccess : storageAccessSet)
    storageAccess.print(os);

  if (unidentifiedAccess != None) {
    os << "  unidentified accesses: "
       << getSILAccessKindName(unidentifiedAccess.getValue()) << "\n";
  }
}

void AccessedStorageResult::dump() const { print(llvm::dbgs()); }

// -----------------------------------------------------------------------------
// MARK: FunctionAccessedStorage, implementation of
// GenericFunctionEffectAnalysis.
// -----------------------------------------------------------------------------

bool FunctionAccessedStorage::summarizeFunction(SILFunction *F) {
  assert(accessResult.isEmpty() && "expected uninitialized results.");

  if (F->isDefinition())
    return false;

  // If the function definition is unavailable, set unidentifiedAccess to a
  // conservative value, since analyzeInstruction will never be called.
  //
  // If FunctionSideEffects can be summarized, use that information.
  FunctionSideEffects functionSideEffects;
  if (!functionSideEffects.summarizeFunction(F)) {
    setWorstEffects();
    // May as well consider this a successful summary since there are no
    // instructions to visit anyway.
    return true;
  }
  bool mayRead = functionSideEffects.getGlobalEffects().mayRead();
  bool mayWrite = functionSideEffects.getGlobalEffects().mayWrite();
  for (auto &paramEffects : functionSideEffects.getParameterEffects()) {
    mayRead |= paramEffects.mayRead();
    mayWrite |= paramEffects.mayWrite();
  }
  if (mayWrite)
    accessResult.setUnidentifiedAccess(SILAccessKind::Modify);
  else if (mayRead)
    accessResult.setUnidentifiedAccess(SILAccessKind::Read);

  // If function side effects is "readnone" then this result will have an empty
  // storageAccessSet and unidentifiedAccess == None.
  return true;
}

SILAnalysis *swift::createAccessedStorageAnalysis(SILModule *) {
  return new AccessedStorageAnalysis();
}
<commit_msg>Remove a stray llvm::dbgs() from compile time debugging.<commit_after>//===--- AccessedStorageAnalysis.cpp  - Accessed Storage Analysis ---------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "sil-sea"

#include "swift/SILOptimizer/Analysis/AccessedStorageAnalysis.h"
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
#include "swift/SILOptimizer/Analysis/FunctionOrder.h"
#include "swift/SILOptimizer/PassManager/PassManager.h"

using namespace swift;

// -----------------------------------------------------------------------------
// MARK: Accessing the results.
// -----------------------------------------------------------------------------

bool AccessedStorageResult::hasNoNestedConflict(
    const AccessedStorage &otherStorage) const {
  assert(otherStorage.isUniquelyIdentified());
  assert(!hasUnidentifiedAccess());

  return getStorageAccessInfo(otherStorage).hasNoNestedConflict();
}

bool AccessedStorageResult::mayConflictWith(
    SILAccessKind otherAccessKind, const AccessedStorage &otherStorage) const {
  if (hasUnidentifiedAccess()
      && accessKindMayConflict(otherAccessKind,
                               unidentifiedAccess.getValue())) {
    return true;
  }
  for (auto &storageAccess : storageAccessSet) {
    assert(storageAccess && "FunctionAccessedStorage mapped invalid storage.");

    if (!accessKindMayConflict(otherAccessKind, storageAccess.getAccessKind()))
      continue;

    if (!otherStorage.isDistinctFrom(storageAccess))
      return true;
  }
  return false;
}

StorageAccessInfo AccessedStorageResult::getStorageAccessInfo(
    const AccessedStorage &otherStorage) const {
  // Construct a fake StorageAccessInfo to do a hash lookup for the real
  // StorageAccessInfo. The DenseSet key is limited to the AccessedStorage base
  // class members.
  StorageAccessInfo storageKey(otherStorage, SILAccessKind::Read, false);
  auto iter = storageAccessSet.find(storageKey);
  assert(iter != storageAccessSet.end());
  return *iter;
}

// -----------------------------------------------------------------------------
// MARK: Constructing the results.
// -----------------------------------------------------------------------------

static bool updateAccessKind(SILAccessKind &LHS, SILAccessKind RHS) {
  bool changed = false;
  // Assume we don't track Init/Deinit.
  if (LHS == SILAccessKind::Read && RHS == SILAccessKind::Modify) {
    LHS = RHS;
    changed = true;
  }
  return changed;
}

static bool updateOptionalAccessKind(Optional<SILAccessKind> &LHS,
                                     Optional<SILAccessKind> RHS) {
  if (RHS == None)
    return false;

  if (LHS == None) {
    LHS = RHS;
    return true;
  }
  return updateAccessKind(LHS.getValue(), RHS.getValue());
}

bool StorageAccessInfo::mergeFrom(const StorageAccessInfo &RHS) {
  bool changed = false;
  SILAccessKind accessKind = getAccessKind();
  assert(accessKind == SILAccessKind::Read
         || accessKind == SILAccessKind::Modify && "uninitialized info");
  if (updateAccessKind(accessKind, RHS.getAccessKind())) {
    setAccessKind(accessKind);
    changed = true;
  }
  if (hasNoNestedConflict() && !RHS.hasNoNestedConflict()) {
    setNoNestedConflict(false);
    changed = true;
  }
  return changed;
}

bool AccessedStorageResult::updateUnidentifiedAccess(SILAccessKind accessKind) {
  if (unidentifiedAccess == None) {
    unidentifiedAccess = accessKind;
    return true;
  }
  return updateAccessKind(unidentifiedAccess.getValue(), accessKind);
}

// Merge the given AccessedStorageResult in `other` into this
// AccessedStorageResult. Use the given `transformStorage` to map `other`
// AccessedStorage into this context. If `other` is from a callee, argument
// substitution will be performed if possible. However, there's no guarantee
// that the merged access values will belong to this region.
//
// Return true if these results changed, requiring further propagation through
// the call graph.
bool AccessedStorageResult::mergeAccesses(
    const AccessedStorageResult &other,
    std::function<StorageAccessInfo(const StorageAccessInfo &)>
        transformStorage) {

  // The cost of BottomUpIPAnalysis can be quadratic for large recursive call
  // graphs. That cost is multiplied by the size of storageAccessSet. Slowdowns
  // can occur ~1000 elements. 200 is large enough to cover "normal" code,
  // while ensuring compile time isn't affected.
  if (storageAccessSet.size() > 200) {
    setWorstEffects();
    return true;
  }
  // To save compile time, if this storage already has worst-case effects, avoid
  // growing its storageAccessSet.
  if (hasWorstEffects())
    return false;

  // When `this` == `other` (for self-recursion), insertion in DenseMap
  // invalidates the iterator. We still need to propagate and merge in that case
  // because arguments can be recursively dependent. The alternative would be
  // treating all self-recursion conservatively.
  const AccessedStorageResult *otherRegionAccesses = &other;
  AccessedStorageResult regionAccessCopy;
  if (this == &other) {
    regionAccessCopy = other;
    otherRegionAccesses = &regionAccessCopy;
  }
  bool changed = false;
  // Nondeterminstically iterate for the sole purpose of inserting into another
  // unordered set.
  for (auto &rawStorageInfo : otherRegionAccesses->storageAccessSet) {
    const StorageAccessInfo &otherStorageInfo =
        transformStorage(rawStorageInfo);
    // If transformStorage() returns invalid storage object for local storage,
    // that should not be merged with the caller.
    if (!otherStorageInfo)
      continue;

    if (otherStorageInfo.getKind() == AccessedStorage::Unidentified) {
      changed |= updateUnidentifiedAccess(otherStorageInfo.getAccessKind());
      continue;
    }
    // Attempt to add identified AccessedStorage to this map.
    auto result = insertStorageAccess(otherStorageInfo);
    if (result.second) {
      // A new AccessedStorage key was added to this map.
      changed = true;
      continue;
    }
    // Merge StorageAccessInfo into already-mapped AccessedStorage.
    changed |= result.first->mergeFrom(otherStorageInfo);
  }
  if (other.unidentifiedAccess != None)
    changed |= updateUnidentifiedAccess(other.unidentifiedAccess.getValue());

  return changed;
}

bool AccessedStorageResult::mergeFrom(const AccessedStorageResult &other) {
  // Merge accesses from other. Both `this` and `other` are either from the same
  // function or are both callees of the same call site, so their parameters
  // indices coincide. transformStorage is the identity function.
  return mergeAccesses(other, [](const StorageAccessInfo &s) { return s; });
}

/// Returns the argument of the full apply or partial apply corresponding to the
/// callee's parameter index, or returns an invalid SILValue if the applied
/// closure cannot be found. This walks up the apply chain starting at the given
/// `fullApply` to find the applied argument.
static SILValue getCallerArg(FullApplySite fullApply, unsigned paramIndex) {
  if (paramIndex < fullApply.getNumArguments())
    return fullApply.getArgument(paramIndex);

  SILValue callee = fullApply.getCalleeOrigin();
  auto *PAI = dyn_cast<PartialApplyInst>(callee);
  if (!PAI)
    return SILValue();

  unsigned appliedIndex =
    paramIndex - ApplySite(PAI).getCalleeArgIndexOfFirstAppliedArg();
  if (appliedIndex < PAI->getNumArguments())
    return PAI->getArgument(appliedIndex);

  // This must be a chain of partial_applies. We don't expect this in practice,
  // so handle it conservatively.
  return SILValue();
}

/// Transform AccessedStorage from a callee into the caller context. If this is
/// uniquely identified local storage, then return an invalid storage object.
///
/// For correctness, AccessEnforcementOpts relies on all Argument access to
/// either be mapped into the caller's context or marked as an unidentified
/// access at the call site.
///
/// Note: This does *not* map the storage index into the caller function's index
/// range. (When the storage value doesn't need to be remapped, it returns the
/// original storage value.) It's simpler to set the storage index later when it
/// is actually added to the function's storageAccessSet.
static StorageAccessInfo
transformCalleeStorage(const StorageAccessInfo &storage,
                       FullApplySite fullApply) {
  switch (storage.getKind()) {
  case AccessedStorage::Box:
  case AccessedStorage::Stack:
    // Do not merge local storage.
    return StorageAccessInfo(AccessedStorage(), storage);
  case AccessedStorage::Global:
    // Global accesses is universal.
    return storage;
  case AccessedStorage::Class: {
    // If the object's value is an argument, translate it into a value on the
    // caller side.
    SILValue obj = storage.getObject();
    if (auto *arg = dyn_cast<SILFunctionArgument>(obj)) {
      SILValue argVal = getCallerArg(fullApply, arg->getIndex());
      if (argVal) {
        unsigned idx = storage.getPropertyIndex();
        // Remap this storage info. The argument source value is now the new
        // object. The old storage info is inherited.
        return StorageAccessInfo(AccessedStorage::forClass(argVal, idx),
                                 storage);
      }
    }
    // Otherwise, continue to reference the value in the callee because we don't
    // have any better placeholder for a callee-defined object.
    return storage;
  }
  case AccessedStorage::Argument: {
    // Transitively search for the storage base in the caller.
    SILValue argVal = getCallerArg(fullApply, storage.getParamIndex());
    if (argVal) {
      // Remap the argument source value and inherit the old storage info.
      auto calleeStorage = findAccessedStorageNonNested(argVal);
      if (calleeStorage)
        return StorageAccessInfo(calleeStorage, storage);
    }
    // If the argument can't be transformed, demote it to an unidentified
    // access.
    //
    // This is an untested bailout. It is only reachable if the call graph
    // contains an edge that getCallerArg is unable to analyze OR if
    // findAccessedStorageNonNested returns an invalid SILValue, which won't
    // pass SIL verification.
    //
    // FIXME: In case argVal is invalid, support Unidentified access for invalid
    // values. This would also be useful for partially invalidating results.
    return StorageAccessInfo(
        AccessedStorage(argVal, AccessedStorage::Unidentified), storage);
  }
  case AccessedStorage::Nested:
    llvm_unreachable("Unexpected nested access");
  case AccessedStorage::Yield:
    // Continue to hold on to yields from the callee because we don't have
    // any better placeholder in the callee.
    return storage;
  case AccessedStorage::Unidentified:
    // For unidentified storage, continue to reference the value in the callee
    // because we don't have any better placeholder for a callee-defined object.
    return storage;
  }
  llvm_unreachable("unhandled kind");
}

bool AccessedStorageResult::mergeFromApply(
    const AccessedStorageResult &calleeAccess, FullApplySite fullApply) {
  // Merge accesses from calleeAccess. Transform any Argument type
  // AccessedStorage into the caller context to be added to `this` storage map.
  return mergeAccesses(calleeAccess, [&fullApply](const StorageAccessInfo &s) {
    return transformCalleeStorage(s, fullApply);
  });
}

template <typename B>
void AccessedStorageResult::visitBeginAccess(B *beginAccess) {
  if (beginAccess->getEnforcement() != SILAccessEnforcement::Dynamic)
    return;

  const AccessedStorage &storage =
      findAccessedStorageNonNested(beginAccess->getSource());

  if (storage.getKind() == AccessedStorage::Unidentified) {
    // This also catches invalid storage.
    updateOptionalAccessKind(unidentifiedAccess, beginAccess->getAccessKind());
    return;
  }
  StorageAccessInfo storageAccess(storage, beginAccess);
  auto result = insertStorageAccess(storageAccess);
  if (!result.second)
    result.first->mergeFrom(storageAccess);
}

void AccessedStorageResult::analyzeInstruction(SILInstruction *I) {
  assert(!FullApplySite::isa(I) && "caller should merge");

  if (auto *BAI = dyn_cast<BeginAccessInst>(I))
    visitBeginAccess(BAI);
  else if (auto *BUAI = dyn_cast<BeginUnpairedAccessInst>(I))
    visitBeginAccess(BUAI);
}

void StorageAccessInfo::print(raw_ostream &os) const {
  os << "  [" << getSILAccessKindName(getAccessKind()) << "] ";
  if (hasNoNestedConflict())
    os << "[no_nested_conflict] ";
  AccessedStorage::print(os);
}

void StorageAccessInfo::dump() const { print(llvm::dbgs()); }

void AccessedStorageResult::print(raw_ostream &os) const {
  for (auto &storageAccess : storageAccessSet)
    storageAccess.print(os);

  if (unidentifiedAccess != None) {
    os << "  unidentified accesses: "
       << getSILAccessKindName(unidentifiedAccess.getValue()) << "\n";
  }
}

void AccessedStorageResult::dump() const { print(llvm::dbgs()); }

// -----------------------------------------------------------------------------
// MARK: FunctionAccessedStorage, implementation of
// GenericFunctionEffectAnalysis.
// -----------------------------------------------------------------------------

bool FunctionAccessedStorage::summarizeFunction(SILFunction *F) {
  assert(accessResult.isEmpty() && "expected uninitialized results.");

  if (F->isDefinition())
    return false;

  // If the function definition is unavailable, set unidentifiedAccess to a
  // conservative value, since analyzeInstruction will never be called.
  //
  // If FunctionSideEffects can be summarized, use that information.
  FunctionSideEffects functionSideEffects;
  if (!functionSideEffects.summarizeFunction(F)) {
    setWorstEffects();
    // May as well consider this a successful summary since there are no
    // instructions to visit anyway.
    return true;
  }
  bool mayRead = functionSideEffects.getGlobalEffects().mayRead();
  bool mayWrite = functionSideEffects.getGlobalEffects().mayWrite();
  for (auto &paramEffects : functionSideEffects.getParameterEffects()) {
    mayRead |= paramEffects.mayRead();
    mayWrite |= paramEffects.mayWrite();
  }
  if (mayWrite)
    accessResult.setUnidentifiedAccess(SILAccessKind::Modify);
  else if (mayRead)
    accessResult.setUnidentifiedAccess(SILAccessKind::Read);

  // If function side effects is "readnone" then this result will have an empty
  // storageAccessSet and unidentifiedAccess == None.
  return true;
}

SILAnalysis *swift::createAccessedStorageAnalysis(SILModule *) {
  return new AccessedStorageAnalysis();
}
<|endoftext|>


<commit_before>#include "mmsapt.h"
using namespace std;
using namespace Moses;

// currently broken

Mmsapt* PT;
int main(int argc, char* argv[])
{
  // string base = argv[1];
  // string L1   = argv[2];
  // string L2   = argv[3];
  // ostringstream buf;
  // buf << "Mmsapt name=PT0 output-factor=0 num-features=5 base="
  //     << base << " L1=" << L1 << " L2=" << L2;
  // string configline = buf.str();
  // PT = new Mmsapt(configline);
  // PT->Load();
  // float w[] = { 0.0582634, 0.0518865, 0.0229819, 0.00640856,  0.647506 };
  // vector<float> weights(w,w+5);
  // PT->setWeights(weights);
  // // these values are taken from a moses.ini file;
  // // is there a convenient way of accessing them from within mmsapt ???
  // string eline,fline;
  // // TokenIndex V; V.open("crp/trn/mm/de.tdx");
  // while (getline(cin,eline) && getline(cin,fline))
  //   {
  //     cout << eline << endl;
  //     cout << fline << endl;
  //     PT->align(eline,fline);
  //   }
  // delete PT;
}

<commit_msg>Work in progress.<commit_after>#include "mm/ug_bitext.h"
#include <boost/format.hpp>
using namespace std;
using namespace Moses;
using namespace ugdiss;

typedef L2R_Token<SimpleWordId> Token;
typedef mmTtrack<Token> ttrack_t;
typedef mmTSA<Token>     tsa_t;

TokenIndex V1,V2;
boost::shared_ptr<ttrack_t> T1,T2;
tsa_t I1,I2;

namespace stats
{
  using namespace Moses::bitext;
  float
  pmi(size_t j,size_t m1, size_t m2, size_t N)
  {
    float p1 = lbop(N,m1,.1);
    float p2 = lbop(N,m2,.1);
    float p12 = lbop(N,j,.1);
    return log(p12) - log(p1) - log(p2);
    // return log(j) + log(N) - log(m1) - log(m2);
  }

  float
  npmi(size_t j,size_t m1, size_t m2, size_t N)
  {

    float p1 = lbop(N,m1,.1);
    float p2 = lbop(N,m2,.1);
    float p12 = lbop(N,j,.1);
    return (log(p12) - log(p1) - log(p2)) / -log(p12);
    // return pmi(j,m1,m2,N) / (log(N) - log(j));
  }

  float
  mi(size_t j,size_t m1, size_t m2, size_t N)
  {
    float ret = 0;
    if (j)    ret += float(j)/N * pmi(j,m1,m2,N);
    if (m1>j) ret += float(m1-j)/N * pmi(m1-j,m1,N-m2,N);
    if (m2>j) ret += float(m2-j)/N * pmi(m2-j,N-m1,m2,N);
    if (N>m1+m2-j) ret += float(N-m1-m2+j)/N * pmi(N-m1-m2+j,N-m1,N-m2,N);
    return ret;
  }
}

struct SinglePhrase
{
  typedef map<uint64_t,sptr<SinglePhrase> > cache_t;
  uint64_t pid; // phrase id
  vector<ttrack::Position> occs; // occurrences
};

struct PhrasePair
{
  struct score_t;
  uint64_t p1,p2;
  ushort s1,e1,s2,e2;
  int parent;

  struct stats_t
  {
    typedef map<pair<uint64_t,uint64_t>, sptr<stats_t> > cache_t;
    size_t m1,m2,j;
    float  npmi; // normalized point-wise mutual information
    float   pmi; // point-wise mutual information
    float    mi; // mutual information
    float score;

    void
    set(vector<ttrack::Position> const& o1,
	vector<ttrack::Position> const& o2,
	size_t const N)
    {
      m1 = m2 = j = 0;
      size_t i1=0,i2=0;
      while (i1 < o1.size() && i2 < o2.size())
	{
	  if (i1 && o1[i1].sid == o1[i1-1].sid) { ++i1; continue; }
	  if (i2 && o2[i2].sid == o2[i2-1].sid) { ++i2; continue; }

	  if (o1[i1].sid == o2[i2].sid) { ++j; ++i1; ++i2; ++m1; ++m2; }
	  else if (o1[i1].sid < o2[i2].sid) { ++i1; ++m1; }
	  else { ++i2; ++m2; }
	}
      // for (++i1; i1 < o1.size(); ++i1)
      // 	if (o1[i1-1].sid != o1[i1].sid) ++m1;
      // for (++i2; i2 < o2.size(); ++i2)
      // 	if (o2[i2-1].sid != o2[i2].sid) ++m2;

      m1 = 1; m2 = 1;
      for (i1=1; i1 < o1.size(); ++i1)
       	if (o1[i1-1].sid != o1[i1].sid) ++m1;
      for (i2=1; i2 < o2.size(); ++i2)
	if (o2[i2-1].sid != o2[i2].sid) ++m2;

      this->mi = stats::mi(j,m1,m2,N);
      this->pmi = stats::pmi(j,m1,m2,N);
      this->npmi = stats::npmi(j,m1,m2,N);
      // float z = float(m1)/N * float(m2)/N;
      float hmean = 2.*j/(m1+m2);
      this->score = npmi; // hmean; // /sqrt(z);
    }
  } stats;

  PhrasePair(ushort s1_=0, ushort e1_=0, ushort s2_=0, ushort e2_=0)
    : s1(s1_), e1(e1_), s2(s2_), e2(e2_), parent(-1) { }

  bool
  operator<(PhrasePair const& other) const
  {
    return (this->stats.score == other.stats.score
	    ? (e1-s1 + e2-s2 > other.e1-other.s1 + other.e2-other.s2)
	    : (this->stats.score > other.stats.score));
  }

};

SinglePhrase::cache_t cache1,cache2;
PhrasePair::stats_t::cache_t ppcache;

struct SortByPositionInCorpus
{
  bool
  operator()(ttrack::Position const& a,
	     ttrack::Position const& b) const
  {
    return a.sid != b.sid ? a.sid < b.sid : a.offset < b.offset;
  }
};

void
getoccs(tsa_t::tree_iterator const& m,
	vector<ttrack::Position>& occs)
{
  occs.clear();
  occs.reserve(m.approxOccurrenceCount()+10);
  tsa::ArrayEntry I(m.lower_bound(-1));
  char const* stop = m.upper_bound(-1);
  do {
    m.root->readEntry(I.next,I);
    occs.push_back(I);
  } while (I.next != stop);
  sort(occs.begin(),occs.end(),SortByPositionInCorpus());
}

void
lookup_phrases(vector<id_type> const& snt,
	       TokenIndex& V, ttrack_t const& T,
	       tsa_t const& I, SinglePhrase::cache_t& cache,
	       vector<vector<sptr<SinglePhrase> > >& dest)
{
  dest.resize(snt.size());
  for (size_t i = 0; i < snt.size(); ++i)
    {
      tsa_t::tree_iterator m(&I);
      dest[i].clear();
      for (size_t k = i; k < snt.size() && m.extend(snt[k]); ++k)
	{
	  sptr<SinglePhrase>& o = cache[m.getPid()];
	  if (!o)
	    {
	      o.reset(new SinglePhrase());
	      o->pid = m.getPid();
	      getoccs(m,o->occs);
	    }
	  dest[i].push_back(o);
	}
    }
}

struct
RowIndexSorter
{
  vector<vector<float> > const& M;
  size_t const my_col;
  RowIndexSorter(vector<vector<float> > const& m, size_t const c)
    : M(m), my_col(c) { }

  template<typename T>
  bool
  operator()(T const& a, T const& b) const
  {
    return M.at(a).at(my_col) > M.at(b).at(my_col);
  }
};

struct
ColIndexSorter
{
  vector<vector<float> > const& M;
  size_t const my_row;
  ColIndexSorter(vector<vector<float> > const& m, size_t const r)
    : M(m), my_row(r) { }

  template<typename T>
  bool
  operator()(T const& a, T const& b) const
  {
    return M.at(my_row).at(a) > M[my_row].at(b);
  }

};

int main(int argc, char* argv[])
{
  string base = argv[1];
  string L1   = argv[2];
  string L2   = argv[3];

  T1.reset(new ttrack_t());
  T2.reset(new ttrack_t());

  V1.open(base + L1 + ".tdx");
  T1->open(base + L1 + ".mct");
  I1.open(base + L1 + ".sfa", T1);

  V2.open(base + L2 + ".tdx");
  T2->open(base + L2 + ".mct");
  I2.open(base + L2 + ".sfa", T2);

  tsa_t::tree_iterator m1(&I1);
  tsa_t::tree_iterator m2(&I1);
  string line1, line2;
  while (getline(cin,line1) and getline(cin,line2))
    {
      cout << line1 << "\n" << line2 << endl;
      vector<vector<sptr<SinglePhrase> > > M1,M2;
      vector<id_type> snt1,snt2;
      V1.fillIdSeq(line1,snt1);
      V2.fillIdSeq(line2,snt2);
      lookup_phrases(snt1,V1,*T1,I1,cache1,M1);
      lookup_phrases(snt2,V2,*T2,I2,cache2,M2);

      vector<PhrasePair> pp_all,pp_good;
      vector<int> a1(snt1.size(),-1);
      vector<int> a2(snt2.size(),-1);

      vector<vector<int> > z1(snt1.size(),vector<int>(snt1.size(),-1));
      vector<vector<int> > z2(snt2.size(),vector<int>(snt2.size(),-1));
      vector<vector<vector<PhrasePair> > >ppm1(M1.size()),ppm2(M2.size());
      vector<vector<float> >  M(snt1.size(), vector<float>(snt2.size(),0));
      vector<vector<size_t> > best1(snt1.size()), best2(snt2.size());
      for (size_t i1 = 0; i1 < M1.size(); ++i1)
	{
	  PhrasePair pp;
	  pp.s1 = i1;
	  ppm1[i1].resize(M1[i1].size());
	  for (size_t i2 = 0; i2 < M2.size(); ++i2)
	    {
	      pp.s2 = i2;
	      pp.stats.j = 1;
	      ppm2[i2].resize(M2[i2].size());
	      for (size_t k1 = 0; k1 < M1[i1].size(); ++k1)
		{
		  pp.e1 = i1 + k1 + 1;
		  // if (pp.stats.j == 0) break;
		  for (size_t k2 = 0; k2 < M2[i2].size(); ++k2)
		    {
		      pp.e2 = i2 + k2 + 1;
		      sptr<PhrasePair::stats_t> & s
			= ppcache[make_pair(M1[i1][k1]->pid,M2[i2][k2]->pid)];
		      if (!s)
			{
			  s.reset(new PhrasePair::stats_t());
			  s->set(M1[i1][k1]->occs,M2[i2][k2]->occs,T1->size());
			}
		      pp.stats = *s;
		      if (pp.stats.j == 0) break;
		      // ppm1[i1][k1].push_back(pp);
		      // ppm2[i2][k2].push_back(pp);
		      if (pp.stats.score > 0)
			pp_all.push_back(pp);
		    }
		}
	    }
	}
      sort(pp_all.begin(),pp_all.end());
      BOOST_FOREACH(PhrasePair const& pp,pp_all)
	{
	  if (pp.stats.npmi < 0) continue;
	  for (size_t r = pp.s1; r < pp.e1; ++r)
	    for (size_t c = pp.s2; c < pp.e2; ++c)
	      {
		// M[r][c] += log(1-pp.stats.npmi);
		M[r][c] += log(1-pp.stats.mi);
	      }
	}
      for (size_t r = 0; r < M.size(); ++r)
	for (size_t c = 0; c < M[r].size(); ++c)
	  M[r][c] = 1.-exp(M[r][c]);
      for (size_t r = 0; r < best1.size(); ++r)
	{
	  best1[r].resize(snt2.size());
	  for (size_t c = 0; c < best1[r].size(); ++c)
	    best1[r][c] = c;
	  sort(best1[r].begin(),best1[r].end(),ColIndexSorter(M,r));
	}
      for (size_t c = 0; c < best2.size(); ++c)
	{
	  best2[c].resize(snt1.size());
	  for (size_t r = 0; r < best2[c].size(); ++r)
	    best2[c][r] = r;
	  sort(best2[c].begin(),best2[c].end(),RowIndexSorter(M,c));
	}
      for (size_t r = 0; r < best1.size(); ++r)
	{
	  cout << V1[snt1[r]] << ":";
	  for (size_t i = 0; i < min(3UL,M[r].size()); ++i)
	    {
	      size_t k = best1[r][i];
	      // if (M[r][k] >= M[best2[k][min(2UL,M.size())]][k])
	      cout << " " << k << ":" << V2[snt2[k]] << " " << M[r][k];
	    }
	  cout << endl;
	}

#if 0
      for (size_t k = 1; k < pp_all.size(); ++k)
	for (size_t i = k; i--;)
	  if (pp_all[i].s1 >= pp_all[k].s1 &&
	      pp_all[i].e1 <= pp_all[k].e1 &&
	      pp_all[i].s2 >= pp_all[k].s2 &&
	      pp_all[i].e2 <= pp_all[k].e2)
	    pp_all[i].stats.score += pp_all[k].stats.score;
      sort(pp_all.begin(),pp_all.end());
#endif

#if 1
      for (size_t p = 0; p < pp_all.size(); ++p)
	{
	  PhrasePair const& x = pp_all[p];
	  // if (x.stats.npmi < .7) break;
	  // if (z1[x.s1][x.e1-1] >= 0 || z2[x.s2][x.e2-1] >=0)
	  // continue;
	  z1[x.s1][x.e1-1] = p;
	  z2[x.s2][x.e2-1] = p;
	  cout << (boost::format("%.4f %.4f %.4f")
		   % x.stats.score
		   % x.stats.mi
		   % x.stats.npmi);
	  for (size_t z = x.s1; z < x.e1; ++z)
	    cout << " " << V1[snt1[z]];
	  cout << " :::";
	  for (size_t z = x.s2; z < x.e2; ++z)
	    cout << " " << V2[snt2[z]];
	  cout << " ["
	       << x.stats.m1 << "/" << x.stats.j << "/" << x.stats.m2
	       << "]" << endl;
	}
#endif
      // sort(pp_all.begin(),pp_all.end());
      // BOOST_FOREACH(PhrasePair const& pp, pp_all)
      // 	{
      // 	  while (ppm1[pp.s1].size() < pp.e1 - pp.s1)
      // 	    ppm1[pp.s1].push_back(vector<PhrasePair>());
      // 	  vector<PhrasePair>& v1 = ppm1[pp.s1][pp.e1-pp.s1-1];
      // 	  if (v1.size() && v1[0].stats.score > pp.stats.score)
      // 	    continue;
      // 	  while (ppm2[pp.s2].size() < pp.e2 - pp.s2)
      // 	    ppm2[pp.s2].push_back(vector<PhrasePair>());
      // 	  vector<PhrasePair>& v2 = ppm2[pp.s2][pp.e2-pp.s2-1];
      // 	  if (v2.size() && v2[0].stats.score > pp.stats.score)
      // 	    continue;
      // 	  v1.push_back(pp);
      // 	  v2.push_back(pp);
      // 	}

      // BOOST_FOREACH(vector<vector<PhrasePair> >& vv, ppm1)
      // 	{
      // 	  BOOST_FOREACH(vector<PhrasePair>& v, vv)
      // 	    {
      // 	      sort(v.begin(),v.end());
      // 	      if (v.size() > 1 && v[0].stats.score == v[1].stats.score)
      // 		v.clear();
      // 	    }
      // 	}
      // for (size_t i2 = 0; i2 < ppm2.size(); ++i2)
      // 	{
      // 	  for (size_t k2 = 0; k2 < ppm2[i2].size(); ++k2)
      // 	    {
      // 	      vector<PhrasePair>& v2 = ppm2[i2][k2];
      // 	      sort(v2.begin(),v2.end());
      // 	      if (v2.size() > 1 && v2[0].stats.score == v2[1].stats.score)
      // 		{
      // 		  v2.clear();
      // 		  continue;
      // 		}
      // 	      ushort i1 = v2[0].s1;
      // 	      ushort k1 = v2[0].e1 - i1 -1;

      // 	      if (ppm1[i1][k1].size() == 0 ||
      // 		  ppm1[i1][k1][0].s2 != i2 ||
      // 		  ppm1[i1][k1][0].e2 != i2 + k2 + 1)
      // 		{ v2.clear(); }
      // 	      else pp_good.push_back(ppm2[i2][k2][0]);
      // 	    }
      // 	}
      // BOOST_FOREACH(PhrasePair const& pp, pp_good)
      // 	{
      // 	  cout << pp.stats.mi << " ";
      // 	  for (size_t z = pp.s1; z < pp.e1; ++z)
      // 	    cout << V1[snt1[z]] << " ";
      // 	  cout << " ::: ";
      // 	  for (size_t z = pp.s2; z < pp.e2; ++z)
      // 	    cout << V2[snt2[z]] << " ";
      // 	  cout << pp.stats.m1 << "/" << pp.stats.j << "/" << pp.stats.m2 << endl;
      // 	}
      // // cout << string(80,'=') << endl;
      // // sort(pp_all.begin(),pp_all.end());
      // // BOOST_FOREACH(PhrasePair const& pp, pp_all)
      // // 	{
      // // 	  cout << pp.mi << " ";
      // // 	  for (size_t z = pp.s1; z < pp.e1; ++z)
      // // 	    cout << V1[snt1[z]] << " ";
      // // 	  cout << " ::: ";
      // // 	  for (size_t z = pp.s2; z < pp.e2; ++z)
      // // 	    cout << V2[snt2[z]] << " ";
      // // 	  cout << pp.m1 << "/" << pp.j << "/" << pp.m2 << endl;
      // // 	}

    }
}

<|endoftext|>


<commit_before>#include <list>
#include <string>

#include <AlpinoCorpus/CompactCorpusReader.hh>
#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/CorpusReaderFactory.hh>
#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/DbCorpusReader.hh>
#include <AlpinoCorpus/DirectoryCorpusReader.hh>
#include <AlpinoCorpus/Error.hh>
#include <AlpinoCorpus/RecursiveCorpusReader.hh>

namespace alpinocorpus {

    CorpusReader *CorpusReaderFactory::open(std::string const &corpusPath)
    {
        try {
            return new DirectoryCorpusReader(corpusPath);
        } catch (OpenError const &) {}

        try {
            return new CompactCorpusReader(corpusPath);
        } catch (OpenError const &) {}

#if defined(USE_DBXML)
        try {
            return new DbCorpusReader(corpusPath);
        } catch (OpenError const &) {}
#endif

        throw OpenError(corpusPath);
    }

    CorpusReader *CorpusReaderFactory::openRecursive(std::string const &path)
    {
      return new RecursiveCorpusReader(path);
    }

    bool CorpusReaderFactory::readerAvailable(ReaderType readerType)
    {
#ifndef USE_DBXML
        if (readerType == DBXML_CORPUS_READER)
            return false;
#endif USE_DBXML

        return true;
    }

    std::list<CorpusReaderFactory::ReaderInfo> CorpusReaderFactory::readersAvailable()
    {
        std::list<ReaderInfo> readers;

        // XXX - How to present directory corpus readers?

        readers.push_back(ReaderInfo(DIRECTORY_CORPUS_READER,
            "Directory reader", std::list<std::string>()));

        #ifdef USE_DBXML
        readers.push_back(ReaderInfo(DBXML_CORPUS_READER,
            "Dact (DBXML) corpus reader", std::list<std::string>(1, "dact")));
        #endif

        readers.push_back(ReaderInfo(COMPACT_CORPUS_READER,
            "Compact corpus reader", std::list<std::string>(1, "data.dz")));

        return readers;
    }

}
<commit_msg>CorpusReaderFactory: include config.hh<commit_after>#include <list>
#include <string>

#include <AlpinoCorpus/CompactCorpusReader.hh>
#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/CorpusReaderFactory.hh>
#include <AlpinoCorpus/CorpusReader.hh>
#include <AlpinoCorpus/DbCorpusReader.hh>
#include <AlpinoCorpus/DirectoryCorpusReader.hh>
#include <AlpinoCorpus/Error.hh>
#include <AlpinoCorpus/RecursiveCorpusReader.hh>

#include <config.hh>

namespace alpinocorpus {

    CorpusReader *CorpusReaderFactory::open(std::string const &corpusPath)
    {
        try {
            return new DirectoryCorpusReader(corpusPath);
        } catch (OpenError const &) {}

        try {
            return new CompactCorpusReader(corpusPath);
        } catch (OpenError const &) {}

#if defined(USE_DBXML)
        try {
            return new DbCorpusReader(corpusPath);
        } catch (OpenError const &) {}
#endif

        throw OpenError(corpusPath);
    }

    CorpusReader *CorpusReaderFactory::openRecursive(std::string const &path)
    {
      return new RecursiveCorpusReader(path);
    }

    bool CorpusReaderFactory::readerAvailable(ReaderType readerType)
    {
#ifndef USE_DBXML
        if (readerType == DBXML_CORPUS_READER)
            return false;
#endif USE_DBXML

        return true;
    }

    std::list<CorpusReaderFactory::ReaderInfo> CorpusReaderFactory::readersAvailable()
    {
        std::list<ReaderInfo> readers;

        // XXX - How to present directory corpus readers?

        readers.push_back(ReaderInfo(DIRECTORY_CORPUS_READER,
            "Directory reader", std::list<std::string>()));

        #ifdef USE_DBXML
        readers.push_back(ReaderInfo(DBXML_CORPUS_READER,
            "Dact (DBXML) corpus reader", std::list<std::string>(1, "dact")));
        #endif

        readers.push_back(ReaderInfo(COMPACT_CORPUS_READER,
            "Compact corpus reader", std::list<std::string>(1, "data.dz")));

        return readers;
    }

}
<|endoftext|>


<commit_before>// CppSample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

int main()
{
    return 0;
}

<commit_msg>basic class<commit_after>// CppSample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <string.h>

#define BOOL int
#define TRUE 1
#define FALSE !TRUE

class Worker
{
private:
	char m_FullName[256];
public:
	Worker();

	void	SetName(const char* pFullName);
	void	PrintName() const;
};

Worker::Worker()
{
	memset(m_FullName, 0, sizeof(m_FullName));
}

void Worker::SetName(const char* pFullName)
{
	strncpy(m_FullName, pFullName, sizeof(m_FullName));
}

void Worker::PrintName() const
{
	puts("Hello ");
	puts(m_FullName);
}

int main()
{
	Worker w;
	w.SetName("Andrea");

	w.PrintName();

	getchar();
    return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    UnstructuredGridCellGradients.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkActor.h"
#include "vtkArrowSource.h"
#include "vtkAssignAttribute.h"
#include "vtkCamera.h"
#include "vtkCellCenters.h"
#include "vtkExtractEdges.h"
#include "vtkGlyph3D.h"
#include "vtkGradientFilter.h"
#include "vtkPointDataToCellData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStdString.h"
#include "vtkTubeFilter.h"
#include "vtkUnstructuredGridReader.h"

#include "vtkSmartPointer.h"
#define VTK_CREATE(type, var) \
  vtkSmartPointer<type> var = vtkSmartPointer<type>::New()

int UnstructuredGridCellGradients(int argc, char *argv[])
{
  int i;
  // Need to get the data root.
  const char *data_root = NULL;
  for (i = 0; i < argc-1; i++)
    {
    if (strcmp("-D", argv[i]) == 0)
      {
      data_root = argv[i+1];
      break;
      }
    }
  if (!data_root)
    {
    cout << "Need to specify the directory to VTK_DATA_ROOT with -D <dir>." << endl;
    return 1;
    }

  // Create the reader for the data.
  // This is the data that will be volume rendered.
  vtkStdString filename;
  filename = data_root;
  filename += "/Data/uGridEx.vtk";
  cout << "Loading " << filename.c_str() << endl;
  VTK_CREATE(vtkUnstructuredGridReader, reader);
  reader->SetFileName(filename.c_str());

  VTK_CREATE(vtkExtractEdges, edges);
  edges->SetInputConnection(reader->GetOutputPort());

  VTK_CREATE(vtkTubeFilter, tubes);
  tubes->SetInputConnection(edges->GetOutputPort());
  tubes->SetRadius(0.0625);
  tubes->SetVaryRadiusToVaryRadiusOff();
  tubes->SetNumberOfSides(32);

  VTK_CREATE(vtkPolyDataMapper, tubesMapper);
  tubesMapper->SetInputConnection(tubes->GetOutputPort());
  tubesMapper->SetScalarRange(0.0, 26.0);

  VTK_CREATE(vtkActor, tubesActor);
  tubesActor->SetMapper(tubesMapper);

  VTK_CREATE(vtkPointDataToCellData, pd2cd);
  pd2cd->SetInputConnection(reader->GetOutputPort());

  VTK_CREATE(vtkGradientFilter, gradients);
  gradients->SetInputConnection(pd2cd->GetOutputPort());
  gradients->SetInputScalars(vtkDataObject::FIELD_ASSOCIATION_CELLS,
                             vtkDataSetAttributes::SCALARS);

  VTK_CREATE(vtkCellCenters, cellCenters);
  cellCenters->SetInputConnection(gradients->GetOutputPort());

  VTK_CREATE(vtkAssignAttribute, vectors);
  vectors->SetInputConnection(cellCenters->GetOutputPort());
  vectors->Assign("Gradients", vtkDataSetAttributes::VECTORS,
                  vtkAssignAttribute::POINT_DATA);

  VTK_CREATE(vtkArrowSource, arrow);

  VTK_CREATE(vtkGlyph3D, glyphs);
  glyphs->SetInputConnection(0, vectors->GetOutputPort());
  glyphs->SetInputConnection(1, arrow->GetOutputPort());
  glyphs->ScalingOn();
  glyphs->SetScaleModeToScaleByVector();
  glyphs->SetScaleFactor(0.25);
  glyphs->OrientOn();
  glyphs->ClampingOff();
  glyphs->SetVectorModeToUseVector();
  glyphs->SetIndexModeToOff();

  VTK_CREATE(vtkPolyDataMapper, glyphMapper);
  glyphMapper->SetInputConnection(glyphs->GetOutputPort());
  glyphMapper->ScalarVisibilityOff();

  VTK_CREATE(vtkActor, glyphActor);
  glyphActor->SetMapper(glyphMapper);

  VTK_CREATE(vtkRenderer, renderer);
  renderer->AddActor(tubesActor);
  renderer->AddActor(glyphActor);
  renderer->SetBackground(0.328125, 0.347656, 0.425781);

  VTK_CREATE(vtkRenderWindow, renwin);
  renwin->AddRenderer(renderer);
  renwin->SetSize(350, 500);

  renderer->ResetCamera();
  vtkCamera *camera = renderer->GetActiveCamera();
  camera->Elevation(-90.0);
  camera->OrthogonalizeViewUp();
  camera->Elevation(-10.0);
  camera->Azimuth(55.0);

  int retVal = vtkTesting::Test(argc, argv, renwin, 5.0);
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    VTK_CREATE(vtkRenderWindowInteractor, iren);
    iren->SetRenderWindow(renwin);
    iren->Initialize();
    iren->Start();
    retVal = vtkRegressionTester::PASSED;
    }

  if (retVal == vtkRegressionTester::PASSED)
    {
    return 0;
    }
  else
    {
    return 1;
    }
}
<commit_msg>BUG: Fix a problem where some machines were flipping the data over.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    UnstructuredGridCellGradients.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
/*----------------------------------------------------------------------------
 Copyright (c) Sandia Corporation
 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
----------------------------------------------------------------------------*/

#include "vtkActor.h"
#include "vtkArrowSource.h"
#include "vtkAssignAttribute.h"
#include "vtkCamera.h"
#include "vtkCellCenters.h"
#include "vtkExtractEdges.h"
#include "vtkGlyph3D.h"
#include "vtkGradientFilter.h"
#include "vtkPointDataToCellData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStdString.h"
#include "vtkTubeFilter.h"
#include "vtkUnstructuredGridReader.h"

#include "vtkSmartPointer.h"
#define VTK_CREATE(type, var) \
  vtkSmartPointer<type> var = vtkSmartPointer<type>::New()

int UnstructuredGridCellGradients(int argc, char *argv[])
{
  int i;
  // Need to get the data root.
  const char *data_root = NULL;
  for (i = 0; i < argc-1; i++)
    {
    if (strcmp("-D", argv[i]) == 0)
      {
      data_root = argv[i+1];
      break;
      }
    }
  if (!data_root)
    {
    cout << "Need to specify the directory to VTK_DATA_ROOT with -D <dir>." << endl;
    return 1;
    }

  // Create the reader for the data.
  // This is the data that will be volume rendered.
  vtkStdString filename;
  filename = data_root;
  filename += "/Data/uGridEx.vtk";
  cout << "Loading " << filename.c_str() << endl;
  VTK_CREATE(vtkUnstructuredGridReader, reader);
  reader->SetFileName(filename.c_str());

  VTK_CREATE(vtkExtractEdges, edges);
  edges->SetInputConnection(reader->GetOutputPort());

  VTK_CREATE(vtkTubeFilter, tubes);
  tubes->SetInputConnection(edges->GetOutputPort());
  tubes->SetRadius(0.0625);
  tubes->SetVaryRadiusToVaryRadiusOff();
  tubes->SetNumberOfSides(32);

  VTK_CREATE(vtkPolyDataMapper, tubesMapper);
  tubesMapper->SetInputConnection(tubes->GetOutputPort());
  tubesMapper->SetScalarRange(0.0, 26.0);

  VTK_CREATE(vtkActor, tubesActor);
  tubesActor->SetMapper(tubesMapper);

  VTK_CREATE(vtkPointDataToCellData, pd2cd);
  pd2cd->SetInputConnection(reader->GetOutputPort());

  VTK_CREATE(vtkGradientFilter, gradients);
  gradients->SetInputConnection(pd2cd->GetOutputPort());
  gradients->SetInputScalars(vtkDataObject::FIELD_ASSOCIATION_CELLS,
                             vtkDataSetAttributes::SCALARS);

  VTK_CREATE(vtkCellCenters, cellCenters);
  cellCenters->SetInputConnection(gradients->GetOutputPort());

  VTK_CREATE(vtkAssignAttribute, vectors);
  vectors->SetInputConnection(cellCenters->GetOutputPort());
  vectors->Assign("Gradients", vtkDataSetAttributes::VECTORS,
                  vtkAssignAttribute::POINT_DATA);

  VTK_CREATE(vtkArrowSource, arrow);

  VTK_CREATE(vtkGlyph3D, glyphs);
  glyphs->SetInputConnection(0, vectors->GetOutputPort());
  glyphs->SetInputConnection(1, arrow->GetOutputPort());
  glyphs->ScalingOn();
  glyphs->SetScaleModeToScaleByVector();
  glyphs->SetScaleFactor(0.25);
  glyphs->OrientOn();
  glyphs->ClampingOff();
  glyphs->SetVectorModeToUseVector();
  glyphs->SetIndexModeToOff();

  VTK_CREATE(vtkPolyDataMapper, glyphMapper);
  glyphMapper->SetInputConnection(glyphs->GetOutputPort());
  glyphMapper->ScalarVisibilityOff();

  VTK_CREATE(vtkActor, glyphActor);
  glyphActor->SetMapper(glyphMapper);

  VTK_CREATE(vtkRenderer, renderer);
  renderer->AddActor(tubesActor);
  renderer->AddActor(glyphActor);
  renderer->SetBackground(0.328125, 0.347656, 0.425781);

  VTK_CREATE(vtkRenderWindow, renwin);
  renwin->AddRenderer(renderer);
  renwin->SetSize(350, 500);

  renderer->ResetCamera();
  vtkCamera *camera = renderer->GetActiveCamera();
  camera->Elevation(-85.0);
  camera->OrthogonalizeViewUp();
  camera->Elevation(-5.0);
  camera->OrthogonalizeViewUp();
  camera->Elevation(-10.0);
  camera->Azimuth(55.0);

  int retVal = vtkTesting::Test(argc, argv, renwin, 5.0);
  if (retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    VTK_CREATE(vtkRenderWindowInteractor, iren);
    iren->SetRenderWindow(renwin);
    iren->Initialize();
    iren->Start();
    retVal = vtkRegressionTester::PASSED;
    }

  if (retVal == vtkRegressionTester::PASSED)
    {
    return 0;
    }
  else
    {
    return 1;
    }
}
<|endoftext|>