<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2018-2020 The Neblio developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "script_error.h"

const char* ScriptErrorString(const ScriptError serror)
{
    switch (serror)
    {
        case SCRIPT_ERR_OK:
            return "No error";
        case SCRIPT_ERR_EVAL_FALSE:
            return "Script evaluated without error but finished with a false/empty top stack element";
        case SCRIPT_ERR_VERIFY:
            return "Script failed an OP_VERIFY operation";
        case SCRIPT_ERR_EQUALVERIFY:
            return "Script failed an OP_EQUALVERIFY operation";
        case SCRIPT_ERR_CHECKCOLDSTAKEVERIFY:
            return "Script failed an OP_CHECKCOLDSTAKEVERIFY operation";
        case SCRIPT_ERR_CHECKMULTISIGVERIFY:
            return "Script failed an OP_CHECKMULTISIGVERIFY operation";
        case SCRIPT_ERR_CHECKSIGVERIFY:
            return "Script failed an OP_CHECKSIGVERIFY operation";
        case SCRIPT_ERR_NUMEQUALVERIFY:
            return "Script failed an OP_NUMEQUALVERIFY operation";
        case SCRIPT_ERR_SCRIPT_SIZE:
            return "Script is too big";
        case SCRIPT_ERR_PUSH_SIZE:
            return "Push value size limit exceeded";
        case SCRIPT_ERR_OP_COUNT:
            return "Operation limit exceeded";
        case SCRIPT_ERR_STACK_SIZE:
            return "Stack size limit exceeded";
        case SCRIPT_ERR_SIG_COUNT:
            return "Signature count negative or greater than pubkey count";
        case SCRIPT_ERR_PUBKEY_COUNT:
            return "Pubkey count negative or limit exceeded";
        case SCRIPT_ERR_BAD_OPCODE:
            return "Opcode missing or not understood";
        case SCRIPT_ERR_DISABLED_OPCODE:
            return "Attempted to use a disabled opcode";
        case SCRIPT_ERR_INVALID_STACK_OPERATION:
            return "Operation not valid with the current stack size";
        case SCRIPT_ERR_INVALID_ALTSTACK_OPERATION:
            return "Operation not valid with the current altstack size";
        case SCRIPT_ERR_OP_RETURN:
            return "OP_RETURN was encountered";
        case SCRIPT_ERR_UNBALANCED_CONDITIONAL:
            return "Invalid OP_IF construction";
        case SCRIPT_ERR_NEGATIVE_LOCKTIME:
            return "Negative locktime";
        case SCRIPT_ERR_UNSATISFIED_LOCKTIME:
            return "Locktime requirement not satisfied";
        case SCRIPT_ERR_SIG_HASHTYPE:
            return "Signature hash type missing or not understood";
        case SCRIPT_ERR_SIG_DER:
            return "Non-canonical DER signature";
        case SCRIPT_ERR_MINIMALDATA:
            return "Data push larger than necessary";
        case SCRIPT_ERR_SIG_PUSHONLY:
            return "Only non-push operators allowed in signatures";
        case SCRIPT_ERR_SIG_HIGH_S:
            return "Non-canonical signature: S value is unnecessarily high";
        case SCRIPT_ERR_SIG_NULLDUMMY:
            return "Dummy CHECKMULTISIG argument must be zero";
        case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS:
            return "NOPx reserved for soft-fork upgrades";
        case SCRIPT_ERR_PUBKEYTYPE:
            return "Public key is neither compressed or uncompressed";
        case SCRIPT_ERR_UNKNOWN_ERROR:
        case SCRIPT_ERR_ERROR_COUNT:
        default: break;
    }
    return "unknown error";
}
<commit_msg>Improve script error handling<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers
// Copyright (c) 2018-2020 The Neblio developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "script_error.h"

const char* ScriptErrorString(const ScriptError serror)
{
    switch (serror) {
    case SCRIPT_ERR_OK:
        return "No error";
    case SCRIPT_ERR_EVAL_FALSE:
        return "Script evaluated without error but finished with a false/empty top stack element";
    case SCRIPT_ERR_VERIFY:
        return "Script failed an OP_VERIFY operation";
    case SCRIPT_ERR_EQUALVERIFY:
        return "Script failed an OP_EQUALVERIFY operation";
    case SCRIPT_ERR_CHECKCOLDSTAKEVERIFY:
        return "Script failed an OP_CHECKCOLDSTAKEVERIFY operation";
    case SCRIPT_ERR_CHECKMULTISIGVERIFY:
        return "Script failed an OP_CHECKMULTISIGVERIFY operation";
    case SCRIPT_ERR_CHECKSIGVERIFY:
        return "Script failed an OP_CHECKSIGVERIFY operation";
    case SCRIPT_ERR_NUMEQUALVERIFY:
        return "Script failed an OP_NUMEQUALVERIFY operation";
    case SCRIPT_ERR_SCRIPT_SIZE:
        return "Script is too big";
    case SCRIPT_ERR_PUSH_SIZE:
        return "Push value size limit exceeded";
    case SCRIPT_ERR_OP_COUNT:
        return "Operation limit exceeded";
    case SCRIPT_ERR_STACK_SIZE:
        return "Stack size limit exceeded";
    case SCRIPT_ERR_SIG_COUNT:
        return "Signature count negative or greater than pubkey count";
    case SCRIPT_ERR_PUBKEY_COUNT:
        return "Pubkey count negative or limit exceeded";
    case SCRIPT_ERR_BAD_OPCODE:
        return "Opcode missing or not understood";
    case SCRIPT_ERR_DISABLED_OPCODE:
        return "Attempted to use a disabled opcode";
    case SCRIPT_ERR_INVALID_STACK_OPERATION:
        return "Operation not valid with the current stack size";
    case SCRIPT_ERR_INVALID_ALTSTACK_OPERATION:
        return "Operation not valid with the current altstack size";
    case SCRIPT_ERR_OP_RETURN:
        return "OP_RETURN was encountered";
    case SCRIPT_ERR_UNBALANCED_CONDITIONAL:
        return "Invalid OP_IF construction";
    case SCRIPT_ERR_NEGATIVE_LOCKTIME:
        return "Negative locktime";
    case SCRIPT_ERR_UNSATISFIED_LOCKTIME:
        return "Locktime requirement not satisfied";
    case SCRIPT_ERR_SIG_HASHTYPE:
        return "Signature hash type missing or not understood";
    case SCRIPT_ERR_SIG_DER:
        return "Non-canonical DER signature";
    case SCRIPT_ERR_MINIMALDATA:
        return "Data push larger than necessary";
    case SCRIPT_ERR_SIG_PUSHONLY:
        return "Only non-push operators allowed in signatures";
    case SCRIPT_ERR_SIG_HIGH_S:
        return "Non-canonical signature: S value is unnecessarily high";
    case SCRIPT_ERR_SIG_NULLDUMMY:
        return "Dummy CHECKMULTISIG argument must be zero";
    case SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS:
        return "NOPx reserved for soft-fork upgrades";
    case SCRIPT_ERR_PUBKEYTYPE:
        return "Public key is neither compressed or uncompressed";
    case SCRIPT_ERR_MAX_ELEMENT_SIZE:
        return "Element size in stack larger than maximum";
    case SCRIPT_ERR_ELEMENT_SIZE:
        return "Invalid index for element";
    case SCRIPT_ERR_ARITHMETIC_OP_FAILED:
        return "Arithmetic script operation failed";
    case SCRIPT_ERR_OP_CHECKSIGVERIFY_FAILED:
        return "Signature verification failed";
    case SCRIPT_ERR_UNKNOWN_ERROR:
        return "Unknown error";
    case SCRIPT_ERR_ERROR_COUNT:
        break;
    }
    return "unknown error";
}
<|endoftext|>


<commit_before><commit_msg>Add support for basic grid search<commit_after><|endoftext|>


<commit_before><commit_msg>Another performance warning.<commit_after><|endoftext|>


<commit_before>/*
    Copyright 2015 Ahnaf Siddiqui

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "Q_CollisionTest2D.h"

#include <typeindex>

typedef bool(*ColFunc)(const Quantum2D::Collider2D*, const Quantum2D::Collider2D*);

namespace Quantum2D {
    namespace CollisionTest2D {
        static bool initialized = false;

        static ColFunc col_funcs[eNUMCOLTYPES][eNUMCOLTYPES];

        static bool colNONE(const Collider2D *a, const Collider2D *b) {
            return false;
        }

        static bool colAABB2(const Collider2D *a, const Collider2D *b) {
            return AABB2(static_cast<const AABBCollider2D*>(a),
                         static_cast<const AABBCollider2D*>(b));
        }

        static bool colCircle2(const Collider2D *a, const Collider2D *b) {
            return circle2(static_cast<const CircleCollider*>(a),
                           static_cast<const CircleCollider*>(b));
        }

        static bool colCircleAABB(const Collider2D *a, const Collider2D *b) {
            return circleAABB(static_cast<const CircleCollider*>(a),
                              static_cast<const AABBCollider2D*>(b));
        }

        static bool colAABBCircle(const Collider2D *a, const Collider2D *b) {
            return circleAABB(static_cast<const CircleCollider*>(b),
                              static_cast<const AABBCollider2D*>(a));
        }

        static bool colPoly2(const Collider2D *a, const Collider2D *b) {
            return poly2(static_cast<const PolyCollider*>(a),
                         static_cast<const PolyCollider*>(b));
        }

        static bool colCirclePoly(const Collider2D *a, const Collider2D *b) {
            return circlePoly(static_cast<const CircleCollider*>(a),
                              static_cast<const PolyCollider*>(b));
        }

        static bool colPolyCircle(const Collider2D *a, const Collider2D *b) {
            return circlePoly(static_cast<const CircleCollider*>(b),
                              static_cast<const PolyCollider*>(a));
        }

        // ea and eb must be in clockwise order!
        static bool edgeVertsOutside(const Diamond::Vector2<tQ_pos> &ea,
                          const Diamond::Vector2<tQ_pos> &eb,
                          const PointList &verts) {
            using namespace Diamond;

            bool sep = true;

            for (Vector2<tQ_pos> vert : verts) {
                if (!Math::leftOf(vert, ea, eb)) {
                    sep = false;
                    break;
                }
            }

            // DEBUG
            /*
            std::cout << "Points ";

            for (Vector2<tQ_pos> vert : verts)
                std::cout << vert << " ";

            std::cout << std::endl << "are";
            std::cout << (sep ? " " : " NOT ");
            std::cout << "to the left of line "
                << ea << " to " << eb << std::endl;
            */

            return sep;
        }

        // edge points must be specified in clockwise order!
        static bool polyVertsOutside(const PointList &edgePoints,
                                     const PointList &verts) {
            for (int i = 1; i < edgePoints.size(); ++i) {
                if (edgeVertsOutside(edgePoints[i-1],
                                     edgePoints[i],
                                     verts))
                    return true;
            }

            return edgeVertsOutside(edgePoints.back(),
                                    edgePoints.front(),
                                    verts);
        }

        static bool circlePolyIntersect(const CircleCollider *a,
                                        const PolyCollider *b) {
            using namespace Diamond;

            for (int i = 1; i < b->worldPoints().size(); ++i) {
                if (Math::dist2SegmentPoint(b->worldPoints()[i],
                                            b->worldPoints()[i-1],
                                            a->getWorldPos()) < a->getRadiusSq()) {
                    return true;
                }
            }

            return Math::dist2SegmentPoint(b->worldPoints().front(),
                                           b->worldPoints().back(),
                                           a->getWorldPos()) < a->getRadiusSq();
        }
    }
}

bool Quantum2D::CollisionTest2D::init() {
    if (!initialized) {
        // Initialize invalid collision functions
        col_funcs[eNONE][eNONE] = colNONE;
        for (int i = eNONE + 1; i < eNUMCOLTYPES; ++i) {
            col_funcs[eNONE][i] = colNONE;
            col_funcs[i][eNONE] = colNONE;
        }

        col_funcs[eAABB][eAABB] = colAABB2;
        col_funcs[eCIRCLE][eCIRCLE] = colCircle2;
        col_funcs[ePOLY][ePOLY] = colPoly2;

        col_funcs[eAABB][eCIRCLE] = colAABBCircle;
        col_funcs[eCIRCLE][eAABB] = colCircleAABB;

        // TODO: Initialize collision functions for all collider type pairs
        col_funcs[eAABB][ePOLY] = colNONE;
        col_funcs[ePOLY][eAABB] = colNONE;

        col_funcs[eCIRCLE][ePOLY] = colCirclePoly;
        col_funcs[ePOLY][eCIRCLE] = colPolyCircle;

        initialized = true;
    }
    return true;
}

bool Quantum2D::CollisionTest2D::collide(const Collider2D *a,
                                         const Collider2D *b) {
    return col_funcs[a->getType()][b->getType()](a, b);
}

bool Quantum2D::CollisionTest2D::AABB2(const AABBCollider2D *a,
                                       const AABBCollider2D *b) {
    return !(a->getMin().x - b->getMax().x > 0.0f ||
             a->getMin().y - b->getMax().y > 0.0f ||
             b->getMin().x - a->getMax().x > 0.0f ||
             b->getMin().y - a->getMax().y > 0.0f);
}

bool Quantum2D::CollisionTest2D::circle2(const CircleCollider *a,
                                         const CircleCollider *b) {
    tQ_pos rad_tot = a->getRadius() + b->getRadius();
    return a->getWorldPos().distanceSq(b->getWorldPos()) < rad_tot * rad_tot;
}

bool Quantum2D::CollisionTest2D::circleAABB(const CircleCollider *a,
                                            const AABBCollider2D *b) {
    tQ_pos distSq = 0, diff;

    if (a->getWorldPos().x < b->getMin().x) {
        diff = b->getMin().x - a->getWorldPos().x;
        distSq += diff * diff;
    }
    if (a->getWorldPos().x > b->getMax().x) {
        diff = a->getWorldPos().x - b->getMax().x;
        distSq += diff * diff;
    }

    if (a->getWorldPos().y < b->getMin().y) {
        diff = b->getMin().y - a->getWorldPos().y;
        distSq += diff * diff;
    }
    if (a->getWorldPos().y > b->getMax().y) {
        diff = a->getWorldPos().y - b->getMax().y;
        distSq += diff * diff;
    }

    return distSq < a->getRadiusSq();
}

bool Quantum2D::CollisionTest2D::poly2(const PolyCollider *a, const PolyCollider *b) {
    return !polyVertsOutside(a->worldPoints(), b->worldPoints()) &&
           !polyVertsOutside(b->worldPoints(), a->worldPoints());
}

bool Quantum2D::CollisionTest2D::circlePoly(const CircleCollider *a, const PolyCollider *b) {
    return circlePolyIntersect(a, b);
}
<commit_msg>Added a TODO<commit_after>/*
    Copyright 2015 Ahnaf Siddiqui

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

#include "Q_CollisionTest2D.h"

#include <typeindex>

typedef bool(*ColFunc)(const Quantum2D::Collider2D*, const Quantum2D::Collider2D*);

namespace Quantum2D {
    namespace CollisionTest2D {
        static bool initialized = false;

        static ColFunc col_funcs[eNUMCOLTYPES][eNUMCOLTYPES];

        static bool colNONE(const Collider2D *a, const Collider2D *b) {
            return false;
        }

        static bool colAABB2(const Collider2D *a, const Collider2D *b) {
            return AABB2(static_cast<const AABBCollider2D*>(a),
                         static_cast<const AABBCollider2D*>(b));
        }

        static bool colCircle2(const Collider2D *a, const Collider2D *b) {
            return circle2(static_cast<const CircleCollider*>(a),
                           static_cast<const CircleCollider*>(b));
        }

        static bool colCircleAABB(const Collider2D *a, const Collider2D *b) {
            return circleAABB(static_cast<const CircleCollider*>(a),
                              static_cast<const AABBCollider2D*>(b));
        }

        static bool colAABBCircle(const Collider2D *a, const Collider2D *b) {
            return circleAABB(static_cast<const CircleCollider*>(b),
                              static_cast<const AABBCollider2D*>(a));
        }

        static bool colPoly2(const Collider2D *a, const Collider2D *b) {
            return poly2(static_cast<const PolyCollider*>(a),
                         static_cast<const PolyCollider*>(b));
        }

        static bool colCirclePoly(const Collider2D *a, const Collider2D *b) {
            return circlePoly(static_cast<const CircleCollider*>(a),
                              static_cast<const PolyCollider*>(b));
        }

        static bool colPolyCircle(const Collider2D *a, const Collider2D *b) {
            return circlePoly(static_cast<const CircleCollider*>(b),
                              static_cast<const PolyCollider*>(a));
        }

        // ea and eb must be in clockwise order!
        static bool edgeVertsOutside(const Diamond::Vector2<tQ_pos> &ea,
                          const Diamond::Vector2<tQ_pos> &eb,
                          const PointList &verts) {
            using namespace Diamond;

            bool sep = true;

            for (Vector2<tQ_pos> vert : verts) {
                if (!Math::leftOf(vert, ea, eb)) {
                    sep = false;
                    break;
                }
            }

            // DEBUG
            /*
            std::cout << "Points ";

            for (Vector2<tQ_pos> vert : verts)
                std::cout << vert << " ";

            std::cout << std::endl << "are";
            std::cout << (sep ? " " : " NOT ");
            std::cout << "to the left of line "
                << ea << " to " << eb << std::endl;
            */

            return sep;
        }

        // edge points must be specified in clockwise order!
        static bool polyVertsOutside(const PointList &edgePoints,
                                     const PointList &verts) {
            for (int i = 1; i < edgePoints.size(); ++i) {
                if (edgeVertsOutside(edgePoints[i-1],
                                     edgePoints[i],
                                     verts))
                    return true;
            }

            return edgeVertsOutside(edgePoints.back(),
                                    edgePoints.front(),
                                    verts);
        }

        static bool circlePolyIntersect(const CircleCollider *a,
                                        const PolyCollider *b) {
            using namespace Diamond;

            for (int i = 1; i < b->worldPoints().size(); ++i) {
                if (Math::dist2SegmentPoint(b->worldPoints()[i],
                                            b->worldPoints()[i-1],
                                            a->getWorldPos()) < a->getRadiusSq()) {
                    return true;
                }
            }

            return Math::dist2SegmentPoint(b->worldPoints().front(),
                                           b->worldPoints().back(),
                                           a->getWorldPos()) < a->getRadiusSq();
        }
    }
}

bool Quantum2D::CollisionTest2D::init() {
    if (!initialized) {
        // Initialize invalid collision functions
        col_funcs[eNONE][eNONE] = colNONE;
        for (int i = eNONE + 1; i < eNUMCOLTYPES; ++i) {
            col_funcs[eNONE][i] = colNONE;
            col_funcs[i][eNONE] = colNONE;
        }

        col_funcs[eAABB][eAABB] = colAABB2;
        col_funcs[eCIRCLE][eCIRCLE] = colCircle2;
        col_funcs[ePOLY][ePOLY] = colPoly2;

        col_funcs[eAABB][eCIRCLE] = colAABBCircle;
        col_funcs[eCIRCLE][eAABB] = colCircleAABB;

        // TODO: Initialize collision functions for all collider type pairs
        col_funcs[eAABB][ePOLY] = colNONE;
        col_funcs[ePOLY][eAABB] = colNONE;

        col_funcs[eCIRCLE][ePOLY] = colCirclePoly;
        col_funcs[ePOLY][eCIRCLE] = colPolyCircle;

        initialized = true;
    }
    return true;
}

bool Quantum2D::CollisionTest2D::collide(const Collider2D *a,
                                         const Collider2D *b) {
    return col_funcs[a->getType()][b->getType()](a, b);
}

bool Quantum2D::CollisionTest2D::AABB2(const AABBCollider2D *a,
                                       const AABBCollider2D *b) {
    return !(a->getMin().x - b->getMax().x > 0.0f ||
             a->getMin().y - b->getMax().y > 0.0f ||
             b->getMin().x - a->getMax().x > 0.0f ||
             b->getMin().y - a->getMax().y > 0.0f);
}

bool Quantum2D::CollisionTest2D::circle2(const CircleCollider *a,
                                         const CircleCollider *b) {
    tQ_pos rad_tot = a->getRadius() + b->getRadius();
    return a->getWorldPos().distanceSq(b->getWorldPos()) < rad_tot * rad_tot;
}

bool Quantum2D::CollisionTest2D::circleAABB(const CircleCollider *a,
                                            const AABBCollider2D *b) {
    tQ_pos distSq = 0, diff;

    if (a->getWorldPos().x < b->getMin().x) {
        diff = b->getMin().x - a->getWorldPos().x;
        distSq += diff * diff;
    }
    if (a->getWorldPos().x > b->getMax().x) {
        diff = a->getWorldPos().x - b->getMax().x;
        distSq += diff * diff;
    }

    if (a->getWorldPos().y < b->getMin().y) {
        diff = b->getMin().y - a->getWorldPos().y;
        distSq += diff * diff;
    }
    if (a->getWorldPos().y > b->getMax().y) {
        diff = a->getWorldPos().y - b->getMax().y;
        distSq += diff * diff;
    }

    return distSq < a->getRadiusSq();
}

bool Quantum2D::CollisionTest2D::poly2(const PolyCollider *a, const PolyCollider *b) {
    return !polyVertsOutside(a->worldPoints(), b->worldPoints()) &&
           !polyVertsOutside(b->worldPoints(), a->worldPoints());
}

bool Quantum2D::CollisionTest2D::circlePoly(const CircleCollider *a, const PolyCollider *b) {
    // TODO: handle case when circle is inside polygon
    return circlePolyIntersect(a, b);
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id:

#include "ballviewDemo.h"
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/common.h>
#include <BALL/KERNEL/system.h>
#include <BALL/VIEW/DIALOGS/displayProperties.h>
#include <BALL/VIEW/WIDGETS/molecularStructure.h>
#include <BALL/VIEW/DIALOGS/FDPBDialog.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/FORMAT/HINFile.h>
#include <BALL/DATATYPE/contourSurface.h>
#include <BALL/VIEW/PRIMITIVES/mesh.h>
#include <BALL/STRUCTURE/HBondProcessor.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/VIEW/DATATYPE/colorTable.h>
#include <BALL/VIEW/DIALOGS/colorMeshDialog.h>
#include <BALL/VIEW/DIALOGS/molecularFileDialog.h>

#include <qlabel.h>
#include <qpushbutton.h>
#include <qwidgetstack.h>

namespace BALL
{
	namespace VIEW
	{

BALLViewDemo::BALLViewDemo(QWidget* parent, const char* name)
	throw()
	:	BALLViewDemoData(parent, name),
		ModularWidget(name)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new BALLViewDemo " << this << std::endl;
#endif
	// register the widget with the MainControl
 	ModularWidget::registerWidget(this);
	hide();
}

BALLViewDemo::~BALLViewDemo()
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "deleting BALLViewDemo " << this << std::endl;
#endif
}

void BALLViewDemo::show()
{
	widget_stack->raiseWidget(0);
	buttonOk->setEnabled(true);
	DisplayProperties* dp = DisplayProperties::getInstance(0);
	dp->setDrawingPrecision(DRAWING_PRECISION_HIGH);
	dp->setSurfaceDrawingPrecision(6.5);
	dp->enableCreationForNewMolecules(false);
	system_ = new System();

	try
	{
		Path path;
		String file_name(path.getDataPath());
		file_name = file_name.before("data");
		file_name += "data";
		file_name += FileSystem::PATH_SEPARATOR;
		file_name += String("structures");
		file_name += FileSystem::PATH_SEPARATOR;
		file_name += "bpti.pdb";
		MolecularFileDialog* dialog = MolecularFileDialog::getInstance(0);
		system_ = dialog->openFile(file_name);
	}
	catch(Exception::FileNotFound e)
	{
		Log.error() << "Could not open " << e.getFilename() << std::endl;
		return;
	}

	composites_.clear();
	composites_.push_back(system_);
	QDialog::show();
	raise();
}

void BALLViewDemo::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "BALLViewDemo " << this << " onNotify " << message << std::endl;
#endif

	if (!isVisible()) return;

//   	CompositeMessage* cmsg = RTTI::castTo<CompositeMessage>(*message);
	RepresentationMessage* rmsg = RTTI::castTo<RepresentationMessage>(*message);

	Index id = widget_stack->id(widget_stack->visibleWidget());

	if (id == 12)
	{
		if (RTTI::isKindOf<FinishedSimulationMessage>(*message))
		{
			nextStep_();
		}
		return;
	}

	if (id == 13)
	{
		RegularData3DMessage* msg = RTTI::castTo<RegularData3DMessage>(*message);
		if (msg != 0 &&
			  ((RegularData3DMessage::RegularDataMessageType)msg->getType()) == RegularDataMessage::NEW)
		{
			grid_ = msg->getData();
			nextStep_();
		}
		return;
	}

	if (//id <= MODEL_HBONDS + 6 &&
		  rmsg != 0 &&
			rmsg->getType() == RepresentationMessage::UPDATE)
	{
		nextStep_();
	}

}

void BALLViewDemo::nextStep_()
{
	buttonOk->setEnabled(true);
	widget_stack->raiseWidget(widget_stack->id(widget_stack->visibleWidget()) + 1);
}

void BALLViewDemo::accept()
{
	Index id = widget_stack->id(widget_stack->visibleWidget());
	MolecularStructure* ms = MolecularStructure::getInstance(0);
	bool disable_button = true;

//   	if (id < MODEL_HBONDS + 7)
	{
		// remove representations
		PrimitiveManager& pm = getMainControl()->getPrimitiveManager();
		Size nr = pm.getNumberOfRepresentations();
		list<Representation*> reps = pm.getRepresentations();
		for (Position p = 0; p < nr; p++)
		{
			getMainControl()->remove(**reps.begin());
			reps.pop_front();
		}
	}

	if (id < 7)
	{
		ModelType type = (ModelType) id;
		if (type >= MODEL_SA_SURFACE) ((Index)type) ++;
if (type == MODEL_SE_SURFACE) type = MODEL_LINES;
 		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, type, COLORING_ELEMENT);
		notify_(crmsg);
	}
	else if (id == 7)
	{
   	CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
   	notify_(crmsg);
 		crmsg = new CreateRepresentationMessage(composites_, MODEL_HBONDS, COLORING_ELEMENT);
 		notify_(crmsg);
	}
	else if (id == 8)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_VDW, COLORING_TEMPERATURE_FACTOR);
		notify_(crmsg);
	}
	else if (id == 9)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_CARTOON, COLORING_SECONDARY_STRUCTURE);
		notify_(crmsg);
	}
	else if (id == 10)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_CARTOON, COLORING_RESIDUE_INDEX);
		notify_(crmsg);
	}
	else if (id == 11)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_RESIDUE_NAME);
		notify_(crmsg);
	}
	else if (id == 12)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
		notify_(crmsg);

		ms->chooseAmberFF();
		ms->getMDSimulationDialog().setTimeStep(0.001);
 		ms->getMDSimulationDialog().setNumberOfSteps(30);
		ms->MDSimulation(false);
	}
	else if (id == 13) //FDPB
	{
		ms->calculateFDPB();
		ms->getFDPBDialog()->okPressed();
		disable_button = false;
	}
	else if (id == 14) // SES colored
	{
		getMainControl()->getPrimitiveManager().setMultithreadingMode(false);
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_SE_SURFACE, COLORING_ELEMENT);
		notify_(crmsg);

		Representation* rep = *getMainControl()->getPrimitiveManager().begin();
		Mesh* mesh = dynamic_cast<Mesh*> (*rep->getGeometricObjects().begin());

		ColorMeshDialog* cdialog = ColorMeshDialog::getInstance(0);
		cdialog->setMesh(mesh, rep);
		cdialog->setGrid(grid_);
		cdialog->setMinValue(-0.7);
		cdialog->setMaxValue(3.0);
		cdialog->applyPressed();

		rep->setColorProcessor(0);
		getMainControl()->getPrimitiveManager().setMultithreadingMode(false);

 		SceneMessage* smsg = new SceneMessage(SceneMessage::REBUILD_DISPLAY_LISTS);
 		notify_(smsg);

		/*
		ContourSurface cs(*grid_, 0.01);
		Mesh* mesh = new Mesh;
		mesh->Surface::operator = (static_cast<Surface&>(cs));

		Vector3 center;
		for (Position i = 0; i < mesh->vertex.size(); i++)
		{
			center += mesh->vertex[i];
		}

		center /= mesh->vertex.size();

		Size nr_of_strange_normals = 0;
		for (Position i = 0; i < mesh->normal.size(); i++)
		{
			if ((mesh->vertex[i] + mesh->normal[i]).getDistance(center) < (mesh->vertex[i] - mesh->normal[i]).getDistance(center))
			{
				nr_of_strange_normals ++;
			}
		}

		if (nr_of_strange_normals > mesh->normal.size() / 2.0)
		{
			for (Position i = 0; i < mesh->normal.size(); i++)
			{
				mesh->normal[i] *= -1;
			}
		}

		Stage stage = *Scene::getInstance(0)->getStage();
		stage.clearLightSources();
		LightSource ls;
		ls.setPosition(Vector3(0,0,4000));
		ls.setDirection(Vector3(0,0,0));
		stage.addLightSource(ls);
		SceneMessage* smsg = new SceneMessage(SceneMessage::UPDATE_CAMERA);
		smsg->setStage(stage);
		notify_(smsg);
		// Create a new representation containing the contour surface.
		Representation* rep = getMainControl()->getPrimitiveManager().createRepresentation();
		rep->insert(*mesh);
		rep->setModelType(MODEL_CONTOUR_SURFACE);

		// Make sure BALLView knows about the new representation.
		RepresentationMessage* message = new RepresentationMessage(*rep, RepresentationMessage::ADD);
		notify_(message);

*/
 		disable_button = false;

	}
	else if (id == 15) // last
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
		notify_(crmsg);
	}

	buttonOk->setEnabled(!disable_button);
}

} } // namespaces
<commit_msg>no message<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id:

#include "ballviewDemo.h"
#include <BALL/VIEW/KERNEL/mainControl.h>
#include <BALL/VIEW/KERNEL/common.h>
#include <BALL/KERNEL/system.h>
#include <BALL/VIEW/DIALOGS/displayProperties.h>
#include <BALL/VIEW/WIDGETS/molecularStructure.h>
#include <BALL/VIEW/DIALOGS/FDPBDialog.h>
#include <BALL/FORMAT/PDBFile.h>
#include <BALL/FORMAT/HINFile.h>
#include <BALL/DATATYPE/contourSurface.h>
#include <BALL/VIEW/PRIMITIVES/mesh.h>
#include <BALL/STRUCTURE/HBondProcessor.h>
#include <BALL/VIEW/WIDGETS/scene.h>
#include <BALL/VIEW/DATATYPE/colorTable.h>
#include <BALL/VIEW/DIALOGS/colorMeshDialog.h>
#include <BALL/VIEW/DIALOGS/molecularFileDialog.h>

#include <qlabel.h>
#include <qpushbutton.h>
#include <qwidgetstack.h>

namespace BALL
{
	namespace VIEW
	{

BALLViewDemo::BALLViewDemo(QWidget* parent, const char* name)
	throw()
	:	BALLViewDemoData(parent, name),
		ModularWidget(name)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new BALLViewDemo " << this << std::endl;
#endif
	// register the widget with the MainControl
 	ModularWidget::registerWidget(this);
	hide();
}

BALLViewDemo::~BALLViewDemo()
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "deleting BALLViewDemo " << this << std::endl;
#endif
}

void BALLViewDemo::show()
{
	widget_stack->raiseWidget(0);
	buttonOk->setEnabled(true);
	DisplayProperties* dp = DisplayProperties::getInstance(0);
	dp->setDrawingPrecision(DRAWING_PRECISION_HIGH);
	dp->setSurfaceDrawingPrecision(6.5);
	dp->enableCreationForNewMolecules(false);
	system_ = new System();

	try
	{
		Path path;
		String file_name(path.getDataPath());
		file_name = file_name.before("data");
		file_name += "data";
		file_name += FileSystem::PATH_SEPARATOR;
		file_name += String("structures");
		file_name += FileSystem::PATH_SEPARATOR;
		file_name += "bpti.pdb";
		MolecularFileDialog* dialog = MolecularFileDialog::getInstance(0);
		system_ = dialog->openFile(file_name);
	}
	catch(Exception::FileNotFound e)
	{
		Log.error() << "Could not open " << e.getFilename() << std::endl;
		return;
	}

	composites_.clear();
	composites_.push_back(system_);
	QDialog::show();
	raise();
}

void BALLViewDemo::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "BALLViewDemo " << this << " onNotify " << message << std::endl;
#endif

	if (!isVisible()) return;

	RepresentationMessage* rmsg = RTTI::castTo<RepresentationMessage>(*message);

	Index id = widget_stack->id(widget_stack->visibleWidget());

	if (id == 12)
	{
		if (RTTI::isKindOf<FinishedSimulationMessage>(*message))
		{
			nextStep_();
		}
		return;
	}

	if (id == 13)
	{
		RegularData3DMessage* msg = RTTI::castTo<RegularData3DMessage>(*message);
		if (msg != 0 &&
			  ((RegularData3DMessage::RegularDataMessageType)msg->getType()) == RegularDataMessage::NEW)
		{
			grid_ = msg->getData();
			nextStep_();
		}
		return;
	}

	if (rmsg != 0 &&
			rmsg->getType() == RepresentationMessage::UPDATE)
	{
		nextStep_();
	}
}

void BALLViewDemo::nextStep_()
{
	buttonOk->setEnabled(true);
	widget_stack->raiseWidget(widget_stack->id(widget_stack->visibleWidget()) + 1);
}

void BALLViewDemo::accept()
{
	Index id = widget_stack->id(widget_stack->visibleWidget());
	MolecularStructure* ms = MolecularStructure::getInstance(0);
	bool disable_button = true;

	// remove representations
	PrimitiveManager& pm = getMainControl()->getPrimitiveManager();
	Size nr = pm.getNumberOfRepresentations();
	list<Representation*> reps = pm.getRepresentations();
	for (Position p = 0; p < nr; p++)
	{
		getMainControl()->remove(**reps.begin());
		reps.pop_front();
	}

	if (id < 7)
	{
		ModelType type = (ModelType) id;
		if (type >= MODEL_SA_SURFACE) ((Index)type) ++;
 		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, type, COLORING_ELEMENT);
		notify_(crmsg);
	}
	else if (id == 7)
	{
		HBondProcessor proc;
		system_->apply(proc);
		getMainControl()->update(*system_);
   	CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
   	notify_(crmsg);
 		crmsg = new CreateRepresentationMessage(composites_, MODEL_HBONDS, COLORING_ELEMENT);
 		notify_(crmsg);
	}
	else if (id == 8)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_VDW, COLORING_TEMPERATURE_FACTOR);
		notify_(crmsg);
	}
	else if (id == 9)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_CARTOON, COLORING_SECONDARY_STRUCTURE);
		notify_(crmsg);
	}
	else if (id == 10)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_CARTOON, COLORING_RESIDUE_INDEX);
		notify_(crmsg);
	}
	else if (id == 11)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_RESIDUE_NAME);
		notify_(crmsg);
	}
	else if (id == 12)
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
		notify_(crmsg);

		ms->chooseAmberFF();
		ms->getMDSimulationDialog().setTimeStep(0.001);
 		ms->getMDSimulationDialog().setNumberOfSteps(30);
		ms->MDSimulation(false);
	}
	else if (id == 13) //FDPB
	{
		ms->calculateFDPB();
		ms->getFDPBDialog()->okPressed();
		disable_button = false;
	}
	else if (id == 14) // SES colored
	{
		getMainControl()->getPrimitiveManager().setMultithreadingMode(false);
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_SE_SURFACE, COLORING_ELEMENT);
		notify_(crmsg);

		Representation* rep = *getMainControl()->getPrimitiveManager().begin();
		Mesh* mesh = dynamic_cast<Mesh*> (*rep->getGeometricObjects().begin());

		ColorMeshDialog* cdialog = ColorMeshDialog::getInstance(0);
		cdialog->setMesh(mesh, rep);
		cdialog->setGrid(grid_);
		cdialog->setMinValue(-0.7);
		cdialog->setMaxValue(3.0);
		cdialog->applyPressed();

		rep->setColorProcessor(0);
		getMainControl()->getPrimitiveManager().setMultithreadingMode(false);

 		SceneMessage* smsg = new SceneMessage(SceneMessage::REBUILD_DISPLAY_LISTS);
 		notify_(smsg);

		/*
		ContourSurface cs(*grid_, 0.01);
		Mesh* mesh = new Mesh;
		mesh->Surface::operator = (static_cast<Surface&>(cs));

		Vector3 center;
		for (Position i = 0; i < mesh->vertex.size(); i++)
		{
			center += mesh->vertex[i];
		}

		center /= mesh->vertex.size();

		Size nr_of_strange_normals = 0;
		for (Position i = 0; i < mesh->normal.size(); i++)
		{
			if ((mesh->vertex[i] + mesh->normal[i]).getDistance(center) < (mesh->vertex[i] - mesh->normal[i]).getDistance(center))
			{
				nr_of_strange_normals ++;
			}
		}

		if (nr_of_strange_normals > mesh->normal.size() / 2.0)
		{
			for (Position i = 0; i < mesh->normal.size(); i++)
			{
				mesh->normal[i] *= -1;
			}
		}

		Stage stage = *Scene::getInstance(0)->getStage();
		stage.clearLightSources();
		LightSource ls;
		ls.setPosition(Vector3(0,0,4000));
		ls.setDirection(Vector3(0,0,0));
		stage.addLightSource(ls);
		SceneMessage* smsg = new SceneMessage(SceneMessage::UPDATE_CAMERA);
		smsg->setStage(stage);
		notify_(smsg);
		// Create a new representation containing the contour surface.
		Representation* rep = getMainControl()->getPrimitiveManager().createRepresentation();
		rep->insert(*mesh);
		rep->setModelType(MODEL_CONTOUR_SURFACE);

		// Make sure BALLView knows about the new representation.
		RepresentationMessage* message = new RepresentationMessage(*rep, RepresentationMessage::ADD);
		notify_(message);

*/
 		disable_button = false;

	}
	else if (id == 15) // last
	{
		CreateRepresentationMessage* crmsg = new CreateRepresentationMessage(composites_, MODEL_STICK, COLORING_ELEMENT);
		notify_(crmsg);
	}

	buttonOk->setEnabled(!disable_button);
}

} } // namespaces
<|endoftext|>


<commit_before>#include <winsock2.h>

#include "IDAClientManager.h"
#include "SocketOperation.h"
#include "DataBaseWriter.h"
#include "ProcessUtils.h"
#include "LogOperation.h"

extern LogOperation Logger;

#define DATA_BUFSIZE 4096
#define DEFAULT_IDA_PATH TEXT( "c:\\Program Files\\IDA\\idag.exe" )

IDAClientManager::IDAClientManager():
	EscapedOutputFilename( NULL ),
	EscapedLogFilename( NULL ),
	ListeningSocket( INVALID_SOCKET ),
	TheSource( NULL ),
	TheTarget( NULL ),
	IDACommandProcessorThreadId( -1 )
{
	IDAPath=_strdup( DEFAULT_IDA_PATH );
}

void IDAClientManager::SetDatabase( DBWrapper *OutputDB )
{
	m_OutputDB=OutputDB;
}

bool IDAClientManager::StartIDAListener( unsigned short port )
{
	StopIDAListener();
	ListeningPort=port;
	if( ListeningPort>0 )
	{
		ListeningSocket = CreateListener( NULL, port );
		Logger.Log( 10, "%s: ListeningSocket=%d\n", __FUNCTION__, ListeningSocket );
		return TRUE;
	}
	return FALSE;
}

bool IDAClientManager::StopIDAListener()
{
	if( ListeningSocket != INVALID_SOCKET )
	{
		closesocket( ListeningSocket );
		return TRUE;
	}
	return FALSE;
}

IDAClientManager::~IDAClientManager()
{
	StopIDAListener();

	if( IDAPath )
		free( IDAPath );
	if( EscapedOutputFilename )
		free( EscapedOutputFilename );
	if( EscapedLogFilename )
		free( EscapedLogFilename );

	if( TheSource )
		delete TheSource;

	if( TheTarget )
		delete TheTarget;
}

OneIDAClientManager *IDAClientManager::GetOneIDAClientManagerFromFile( char *DataFile )
{
	OneIDAClientManager *pOneIDAClientManager=new OneIDAClientManager( m_OutputDB );
	pOneIDAClientManager->Retrieve( DataFile );
	return pOneIDAClientManager;
}

BOOL IDAClientManager::AcceptIDAClient( OneIDAClientManager *pOneIDAClientManager, bool RetrieveData )
{
	SOCKET ClientSocket=accept( ListeningSocket, NULL, NULL );
	Logger.Log( 10, "%s: accepting=%d\n", __FUNCTION__, ClientSocket );
	if( ClientSocket==INVALID_SOCKET )
	{
		int error=WSAGetLastError();
		Logger.Log( 10, "Socket error=%d\n", error );
		return FALSE;
	}else
	{
		if( RetrieveData )
		{
			Logger.Log( 10, "%s: Calling RetrieveIDARawDataFromSocket\n", __FUNCTION__ );
			pOneIDAClientManager->RetrieveIDARawDataFromSocket( ClientSocket );
		}
		else
		{
			Logger.Log( 10, "%s: SetSocket\n", __FUNCTION__ );
			pOneIDAClientManager->SetSocket( ClientSocket );
		}
		return TRUE;
	}
	return FALSE;
}

DWORD IDAClientManager::SetMembers( OneIDAClientManager *OneIDAClientManagerTheSource, OneIDAClientManager *OneIDAClientManagerTheTarget, DiffMachine *pArgDiffMachine )
{
	TheSource=OneIDAClientManagerTheSource;
	TheTarget=OneIDAClientManagerTheTarget;
	pDiffMachine=pArgDiffMachine;
	return 1;
}

DWORD IDAClientManager::IDACommandProcessor()
{
	SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSANETWORKEVENTS NetworkEvents;
	DWORD EventTotal=0, index;

	SocketArray[0]=TheSource->GetSocket();
	SocketArray[1]=TheTarget->GetSocket();
	for( int i=0;i<2;i++ )
	{
		WSAEVENT NewEvent=WSACreateEvent();
		WSAEventSelect( SocketArray[i], NewEvent, FD_READ|FD_CLOSE );
		EventArray[EventTotal]=NewEvent;
		EventTotal++;
	}
	while( 1 )
	{
		index=WSAWaitForMultipleEvents( EventTotal,
			EventArray,
			FALSE,
			WSA_INFINITE,
			FALSE );

		if( index<0 )
			break;

		index=index-WSA_WAIT_EVENT_0;
		//-------------------------
		// Iterate through all events and enumerate
		// if the wait does not fail.
		for( DWORD i=index; i<EventTotal; i++ )
		{
			if( SocketArray[i]==WSA_INVALID_HANDLE )
				continue;

			index=WSAWaitForMultipleEvents( 1,
				&EventArray[i],
				TRUE,
				1000,
				FALSE );
			if ( ( index !=WSA_WAIT_FAILED ) && ( index !=WSA_WAIT_TIMEOUT ) )
			{
				if( WSAEnumNetworkEvents( SocketArray[i], EventArray[i], &NetworkEvents )==0 )
				{
					Logger.Log( 10, "Signal( %d - %d )\n", i, NetworkEvents.lNetworkEvents );
					if( NetworkEvents.lNetworkEvents==FD_READ )
					{
						char buffer[DATA_BUFSIZE]={0, };
						WSABUF DataBuf;
						DataBuf.len=DATA_BUFSIZE;
						DataBuf.buf=buffer;
						/*
						DWORD RecvBytes;
						DWORD Flags=0;
						if ( WSARecv( SocketArray[i], &DataBuf, 1, &RecvBytes, &Flags, NULL, NULL )==SOCKET_ERROR )
						{
							Logger.Log( 10, "Error occurred at WSARecv()\n" );
						}else
						{
							Logger.Log( 10, "Read %d bytes\n", RecvBytes );
						}*/
						char type;
						DWORD length;
						PBYTE data=RecvTLVData( SocketArray[i], &type, &length );
						if( data )
						{
							Logger.Log( 10, "%s: Type: %d Length: %d data:%x\n", __FUNCTION__, type, length, data );
							if( type==SHOW_MATCH_ADDR && length>=4 )
							{
								DWORD address=*( DWORD * )data;
								Logger.Log( 10, "%s: Showing address=%x\n", __FUNCTION__, address );
								//Get Matching Address
								DWORD MatchingAddress=pDiffMachine->GetMatchAddr( i, address );
								if( MatchingAddress!=0 )
								{
									//Show using JUMP_TO_ADDR
									if( i==0 )
									{
										TheTarget->ShowAddress( MatchingAddress );
									}else
									{
										TheSource->ShowAddress( MatchingAddress );
									}
								}
							}
						}
					}else if( NetworkEvents.lNetworkEvents==FD_CLOSE )
					{
						closesocket( SocketArray[i] );
						WSACloseEvent( EventArray[i] );
						memcpy( SocketArray+i, SocketArray+i+1, EventTotal-i+1 );
						memcpy( EventArray+i, EventArray+i+1, EventTotal-i+1 );
						EventTotal--;
						break;
					}
				}
			}
		}
	}
	return 1;
}

DWORD WINAPI IDACommandProcessorThread( LPVOID lpParameter )
{
	IDAClientManager *pIDAClientManager=( IDAClientManager * )lpParameter;
	pIDAClientManager->IDACommandProcessor();
	return 1;
}

BOOL IDAClientManager::CreateIDACommandProcessorThread()
{
	if( IDACommandProcessorThreadId > 0 )
	{
		HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, IDACommandProcessorThreadId );
		if( hThread )
		{
			CloseHandle( hThread );
		}
		else
		{
			IDACommandProcessorThreadId = -1;
		}
	}

	if( IDACommandProcessorThreadId == -1 )
	{
		CreateThread( NULL, 0, IDACommandProcessorThread, ( PVOID )this, 0, &IDACommandProcessorThreadId );
		return TRUE;
	}
	return FALSE;
}

void SendAddMatchAddrTLVData( FunctionMatchInfo &Data, PVOID Context )
{
	OneIDAClientManager *TheSource=( OneIDAClientManager * )Context;
	if( TheSource )
	{
		TheSource->SendTLVData(
			ADD_MATCH_ADDR,
			( PBYTE )&( Data ),
			sizeof( Data ) );
	}
}

void SendUnidentifiedAddrTLVData( DWORD Data, PVOID Context )
{
	OneIDAClientManager *TheSource=( OneIDAClientManager * )Context;
	if( TheSource )
	{
		TheSource->SendTLVData(
			ADD_UNINDENTIFIED_ADDR,
			( PBYTE )&( Data ),
			sizeof( Data ) );
	}
}

void IDAClientManager::ShowResultsOnIDA()
{
	pDiffMachine->ExecuteOnFunctionMatchInfoList( SendAddMatchAddrTLVData, ( PVOID )TheSource );
	pDiffMachine->ExecuteOnTheSourceUnidentifedBlockHash( SendUnidentifiedAddrTLVData, ( PVOID )TheSource );
	pDiffMachine->ExecuteOnTheTargetUnidentifedBlockHash( SendUnidentifiedAddrTLVData, ( PVOID )TheTarget );
#ifdef TODO
	for( iter=ReverseFunctionMatchInfoList.begin();iter!=ReverseFunctionMatchInfoList.end();iter++ )
	{
		TheTarget->SendTLVData(
			ADD_MATCH_ADDR,
			( PBYTE )&( *iter ),
			sizeof( *iter ) );
	}
#endif
	TheSource->SendTLVData(
		SHOW_DATA,
		( PBYTE )"test",
		4 );
	TheTarget->SendTLVData(
		SHOW_DATA,
		( PBYTE )"test",
		4 );
}

#define RUN_DARUNGRIM2_PLUGIN_STR "static main()\n\
{\n\
	Wait();\n\
	RunPlugin( \"DarunGrim2\", 1 );\n\
	SetLogFile( \"%s\" );\n\
	SaveAnalysisData( \"%s\", %d, %d );\n\
	Exit( 0 );\n\
}"

#define CONNECT_TO_DARUNGRIM2_STR "static main()\n\
{\n\
	Wait();\n\
	RunPlugin( \"DarunGrim2\", 1 );\n\
	SetLogFile( \"%s\" );\n\
	ConnectToDarunGrim2();\n\
	Exit( 0 );\n\
}"

void IDAClientManager::SetIDAPath( const char *ParamIDAPath )
{
	if( IDAPath )
		free( IDAPath );
	IDAPath=_strdup( ParamIDAPath );
}

void IDAClientManager::SetOutputFilename( char *OutputFilename )
{
	//Create IDC file
	EscapedOutputFilename=( char * )malloc( strlen( OutputFilename )*2+1 );

	if( EscapedOutputFilename )
	{
		DWORD i=0, j=0;
		for( ;i<strlen( OutputFilename );i++, j++ )
		{
			EscapedOutputFilename[j]=OutputFilename[i];
			if( OutputFilename[i]=='\\' )
			{
				j++;
				EscapedOutputFilename[j]='\\';
			}
		}
		EscapedOutputFilename[j]=NULL;
	}
}

void IDAClientManager::SetLogFilename( char *LogFilename )
{
	EscapedLogFilename=NULL;
	if( LogFilename )
	{
		EscapedLogFilename=( char * )malloc( strlen( LogFilename )*2+1 );
		if( EscapedLogFilename )
		{
			DWORD i=0, j=0;
			for( ;i<strlen( LogFilename );i++, j++ )
			{
				EscapedLogFilename[j]=LogFilename[i];
				if( LogFilename[i]=='\\' )
				{
					j++;
					EscapedLogFilename[j]='\\';
				}
			}
			EscapedLogFilename[j]=NULL;
		}
	}
}

void IDAClientManager::RunIDAToGenerateDB( char *ida_filename, DWORD StartAddress, DWORD EndAddress )
{
	char *idc_filename=WriteToTemporaryFile( RUN_DARUNGRIM2_PLUGIN_STR,
		EscapedLogFilename?EscapedLogFilename:"",
		EscapedOutputFilename?EscapedOutputFilename:"",
		StartAddress,
		EndAddress );

	if( idc_filename )
	{
		//Run IDA
		Logger.Log( 10, "Analyzing [%s]( %s )\n", ida_filename, idc_filename );
		Logger.Log( 10, "Executing \"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		Execute( TRUE, "\"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		free( idc_filename );
	}
}

void IDAClientManager::ConnectToDarunGrim2( char *ida_filename )
{
	char *idc_filename=WriteToTemporaryFile( CONNECT_TO_DARUNGRIM2_STR, EscapedLogFilename?EscapedLogFilename:"");

	if( idc_filename )
	{
		//Run IDA
		Logger.Log( 10, "Analyzing [%s]( %s )\n", ida_filename, idc_filename );
		Logger.Log( 10, "Executing \"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		Execute( TRUE, "\"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		free( idc_filename );
	}
}<commit_msg>Added sanity checks<commit_after>#include <winsock2.h>

#include "IDAClientManager.h"
#include "SocketOperation.h"
#include "DataBaseWriter.h"
#include "ProcessUtils.h"
#include "LogOperation.h"

extern LogOperation Logger;

#define DATA_BUFSIZE 4096
#define DEFAULT_IDA_PATH TEXT( "c:\\Program Files\\IDA\\idag.exe" )

IDAClientManager::IDAClientManager():
	EscapedOutputFilename( NULL ),
	EscapedLogFilename( NULL ),
	ListeningSocket( INVALID_SOCKET ),
	TheSource( NULL ),
	TheTarget( NULL ),
	IDACommandProcessorThreadId( -1 )
{
	IDAPath=_strdup( DEFAULT_IDA_PATH );
}

void IDAClientManager::SetDatabase( DBWrapper *OutputDB )
{
	m_OutputDB=OutputDB;
}

bool IDAClientManager::StartIDAListener( unsigned short port )
{
	StopIDAListener();
	ListeningPort=port;
	if( ListeningPort>0 )
	{
		ListeningSocket = CreateListener( NULL, port );
		Logger.Log( 10, "%s: ListeningSocket=%d\n", __FUNCTION__, ListeningSocket );
		return TRUE;
	}
	return FALSE;
}

bool IDAClientManager::StopIDAListener()
{
	if( ListeningSocket != INVALID_SOCKET )
	{
		closesocket( ListeningSocket );
		return TRUE;
	}
	return FALSE;
}

IDAClientManager::~IDAClientManager()
{
	StopIDAListener();

	if( IDAPath )
		free( IDAPath );
	if( EscapedOutputFilename )
		free( EscapedOutputFilename );
	if( EscapedLogFilename )
		free( EscapedLogFilename );

	if( TheSource )
		delete TheSource;

	if( TheTarget )
		delete TheTarget;
}

OneIDAClientManager *IDAClientManager::GetOneIDAClientManagerFromFile( char *DataFile )
{
	OneIDAClientManager *pOneIDAClientManager=new OneIDAClientManager( m_OutputDB );
	pOneIDAClientManager->Retrieve( DataFile );
	return pOneIDAClientManager;
}

BOOL IDAClientManager::AcceptIDAClient( OneIDAClientManager *pOneIDAClientManager, bool RetrieveData )
{
	SOCKET ClientSocket=accept( ListeningSocket, NULL, NULL );
	Logger.Log( 10, "%s: accepting=%d\n", __FUNCTION__, ClientSocket );
	if( ClientSocket==INVALID_SOCKET )
	{
		int error=WSAGetLastError();
		Logger.Log( 10, "Socket error=%d\n", error );
		return FALSE;
	}else
	{
		if( RetrieveData )
		{
			Logger.Log( 10, "%s: Calling RetrieveIDARawDataFromSocket\n", __FUNCTION__ );
			pOneIDAClientManager->RetrieveIDARawDataFromSocket( ClientSocket );
		}
		else
		{
			Logger.Log( 10, "%s: SetSocket\n", __FUNCTION__ );
			pOneIDAClientManager->SetSocket( ClientSocket );
		}
		return TRUE;
	}
	return FALSE;
}

DWORD IDAClientManager::SetMembers( OneIDAClientManager *OneIDAClientManagerTheSource, OneIDAClientManager *OneIDAClientManagerTheTarget, DiffMachine *pArgDiffMachine )
{
	TheSource=OneIDAClientManagerTheSource;
	TheTarget=OneIDAClientManagerTheTarget;
	pDiffMachine=pArgDiffMachine;
	return 1;
}

DWORD IDAClientManager::IDACommandProcessor()
{
	SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
	WSANETWORKEVENTS NetworkEvents;
	DWORD EventTotal=0, index;

	SocketArray[0]=TheSource->GetSocket();
	SocketArray[1]=TheTarget->GetSocket();
	for( int i=0;i<2;i++ )
	{
		WSAEVENT NewEvent=WSACreateEvent();
		WSAEventSelect( SocketArray[i], NewEvent, FD_READ|FD_CLOSE );
		EventArray[EventTotal]=NewEvent;
		EventTotal++;
	}
	while( 1 )
	{
		index=WSAWaitForMultipleEvents( EventTotal,
			EventArray,
			FALSE,
			WSA_INFINITE,
			FALSE );

		if( index<0 )
			break;

		index=index-WSA_WAIT_EVENT_0;
		//-------------------------
		// Iterate through all events and enumerate
		// if the wait does not fail.
		for( DWORD i=index; i<EventTotal; i++ )
		{
			if( SocketArray[i]==WSA_INVALID_HANDLE )
				continue;

			index=WSAWaitForMultipleEvents( 1,
				&EventArray[i],
				TRUE,
				1000,
				FALSE );
			if ( ( index !=WSA_WAIT_FAILED ) && ( index !=WSA_WAIT_TIMEOUT ) )
			{
				if( WSAEnumNetworkEvents( SocketArray[i], EventArray[i], &NetworkEvents )==0 )
				{
					Logger.Log( 10, "Signal( %d - %d )\n", i, NetworkEvents.lNetworkEvents );
					if( NetworkEvents.lNetworkEvents==FD_READ )
					{
						char buffer[DATA_BUFSIZE]={0, };
						WSABUF DataBuf;
						DataBuf.len=DATA_BUFSIZE;
						DataBuf.buf=buffer;
						/*
						DWORD RecvBytes;
						DWORD Flags=0;
						if ( WSARecv( SocketArray[i], &DataBuf, 1, &RecvBytes, &Flags, NULL, NULL )==SOCKET_ERROR )
						{
							Logger.Log( 10, "Error occurred at WSARecv()\n" );
						}else
						{
							Logger.Log( 10, "Read %d bytes\n", RecvBytes );
						}*/
						char type;
						DWORD length;
						PBYTE data=RecvTLVData( SocketArray[i], &type, &length );
						if( data )
						{
							Logger.Log( 10, "%s: Type: %d Length: %d data:%x\n", __FUNCTION__, type, length, data );
							if( type==SHOW_MATCH_ADDR && length>=4 )
							{
								DWORD address=*( DWORD * )data;
								Logger.Log( 10, "%s: Showing address=%x\n", __FUNCTION__, address );
								//Get Matching Address
								DWORD MatchingAddress=pDiffMachine->GetMatchAddr( i, address );
								if( MatchingAddress!=0 )
								{
									//Show using JUMP_TO_ADDR
									if( i==0 )
									{
										TheTarget->ShowAddress( MatchingAddress );
									}else
									{
										TheSource->ShowAddress( MatchingAddress );
									}
								}
							}
						}
					}else if( NetworkEvents.lNetworkEvents==FD_CLOSE )
					{
						closesocket( SocketArray[i] );
						WSACloseEvent( EventArray[i] );
						memcpy( SocketArray+i, SocketArray+i+1, EventTotal-i+1 );
						memcpy( EventArray+i, EventArray+i+1, EventTotal-i+1 );
						EventTotal--;
						break;
					}
				}
			}
		}
	}
	return 1;
}

DWORD WINAPI IDACommandProcessorThread( LPVOID lpParameter )
{
	IDAClientManager *pIDAClientManager=( IDAClientManager * )lpParameter;
	pIDAClientManager->IDACommandProcessor();
	return 1;
}

BOOL IDAClientManager::CreateIDACommandProcessorThread()
{
	if( IDACommandProcessorThreadId > 0 )
	{
		HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, IDACommandProcessorThreadId );
		if( hThread )
		{
			CloseHandle( hThread );
		}
		else
		{
			IDACommandProcessorThreadId = -1;
		}
	}

	if( IDACommandProcessorThreadId == -1 )
	{
		CreateThread( NULL, 0, IDACommandProcessorThread, ( PVOID )this, 0, &IDACommandProcessorThreadId );
		return TRUE;
	}
	return FALSE;
}

void SendAddMatchAddrTLVData( FunctionMatchInfo &Data, PVOID Context )
{
	OneIDAClientManager *TheSource=( OneIDAClientManager * )Context;
	if( TheSource )
	{
		TheSource->SendTLVData(
			ADD_MATCH_ADDR,
			( PBYTE )&( Data ),
			sizeof( Data ) );
	}
}

void SendUnidentifiedAddrTLVData( DWORD Data, PVOID Context )
{
	OneIDAClientManager *TheSource=( OneIDAClientManager * )Context;
	if( TheSource )
	{
		TheSource->SendTLVData(
			ADD_UNINDENTIFIED_ADDR,
			( PBYTE )&( Data ),
			sizeof( Data ) );
	}
}

void IDAClientManager::ShowResultsOnIDA()
{
	pDiffMachine->ExecuteOnFunctionMatchInfoList( SendAddMatchAddrTLVData, ( PVOID )TheSource );
	pDiffMachine->ExecuteOnTheSourceUnidentifedBlockHash( SendUnidentifiedAddrTLVData, ( PVOID )TheSource );
	pDiffMachine->ExecuteOnTheTargetUnidentifedBlockHash( SendUnidentifiedAddrTLVData, ( PVOID )TheTarget );
#ifdef TODO
	for( iter=ReverseFunctionMatchInfoList.begin();iter!=ReverseFunctionMatchInfoList.end();iter++ )
	{
		TheTarget->SendTLVData(
			ADD_MATCH_ADDR,
			( PBYTE )&( *iter ),
			sizeof( *iter ) );
	}
#endif
	TheSource->SendTLVData(
		SHOW_DATA,
		( PBYTE )"test",
		4 );
	TheTarget->SendTLVData(
		SHOW_DATA,
		( PBYTE )"test",
		4 );
}

#define RUN_DARUNGRIM2_PLUGIN_STR "static main()\n\
{\n\
	Wait();\n\
	RunPlugin( \"DarunGrim2\", 1 );\n\
	SetLogFile( \"%s\" );\n\
	SaveAnalysisData( \"%s\", %d, %d );\n\
	Exit( 0 );\n\
}"

#define CONNECT_TO_DARUNGRIM2_STR "static main()\n\
{\n\
	Wait();\n\
	RunPlugin( \"DarunGrim2\", 1 );\n\
	SetLogFile( \"%s\" );\n\
	ConnectToDarunGrim2();\n\
	Exit( 0 );\n\
}"

void IDAClientManager::SetIDAPath( const char *ParamIDAPath )
{
	if( IDAPath )
		free( IDAPath );
	IDAPath=_strdup( ParamIDAPath );
}

void IDAClientManager::SetOutputFilename( char *OutputFilename )
{
	//Create IDC file
	EscapedOutputFilename=( char * )malloc( strlen( OutputFilename )*2+1 );

	if( EscapedOutputFilename )
	{
		DWORD i=0, j=0;
		for( ;i<strlen( OutputFilename );i++, j++ )
		{
			EscapedOutputFilename[j]=OutputFilename[i];
			if( OutputFilename[i]=='\\' )
			{
				j++;
				EscapedOutputFilename[j]='\\';
			}
		}
		EscapedOutputFilename[j]=NULL;
	}
}

void IDAClientManager::SetLogFilename( char *LogFilename )
{
	EscapedLogFilename=NULL;
	if( LogFilename )
	{
		EscapedLogFilename=( char * )malloc( strlen( LogFilename )*2+1 );
		if( EscapedLogFilename )
		{
			DWORD i=0, j=0;
			for( ;i<strlen( LogFilename );i++, j++ )
			{
				EscapedLogFilename[j]=LogFilename[i];
				if( LogFilename[i]=='\\' )
				{
					j++;
					EscapedLogFilename[j]='\\';
				}
			}
			EscapedLogFilename[j]=NULL;
		}
	}
}

void IDAClientManager::RunIDAToGenerateDB( char *ida_filename, DWORD StartAddress, DWORD EndAddress )
{
	char *idc_filename=WriteToTemporaryFile( RUN_DARUNGRIM2_PLUGIN_STR,
		EscapedLogFilename?EscapedLogFilename:"",
		EscapedOutputFilename?EscapedOutputFilename:"",
		StartAddress,
		EndAddress );

	if( idc_filename )
	{
		//Run IDA
		Logger.Log( 10, "Analyzing [%s]( %s )\n", ida_filename, idc_filename );
		Logger.Log( 10, "Executing \"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		Execute( TRUE, "\"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		free( idc_filename );
	}
}

void IDAClientManager::ConnectToDarunGrim2( char *ida_filename )
{
	char *idc_filename=WriteToTemporaryFile( CONNECT_TO_DARUNGRIM2_STR, EscapedLogFilename?EscapedLogFilename:"");

	if( idc_filename )
	{
		//Run IDA
		Logger.Log( 10, "Analyzing [%s]( %s )\n", ida_filename, idc_filename );
		Logger.Log( 10, "Executing \"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		Execute( TRUE, "\"%s\" -A -S\"%s\" \"%s\"", IDAPath, idc_filename, ida_filename );
		free( idc_filename );
	}
}<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008, Massachusetts Institute of Technology              //
// All rights reserved.                                                   //
//                                                                        //
// Redistribution and use in source and binary forms, with or without     //
// modification, are permitted provided that the following conditions are //
// met:                                                                   //
//                                                                        //
//     * Redistributions of source code must retain the above copyright   //
//       notice, this list of conditions and the following disclaimer.    //
//                                                                        //
//     * Redistributions 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.                                           //
//                                                                        //
//     * Neither the name of the Massachusetts Institute of Technology    //
//       nor the names of its contributors may 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 COPYRIGHT   //
// OWNER 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.   //
////////////////////////////////////////////////////////////////////////////

#include <algorithm>
#include "util/Logger.h"
#include "NgramLM.h"
#include "Mask.h"
#include "KneserNeySmoothing.h"

using std::min;

///////////////////////////////////////////////////////////////////////////////

namespace mitlm {

void KneserNeySmoothing::Initialize(NgramLM *pLM, size_t order) {
    assert(order != 0);

    _pLM = pLM;
    _order = order;

    // Compute adjusted Kneser-Ney counts.
    if (_order < _pLM->order()) {
        // Compute left-branch counts.
        _effCounts.reset(_pLM->sizes(_order), 0);
        const CountVector &hoCounts(_pLM->counts(_order + 1));
        const IndexVector &hoBackoffs(_pLM->backoffs(_order + 1));
        // TODO: Need to implement operator[BitVector].
        //BinCount(hoBackoffs[hoCounts > 0], _effCounts);
        for (size_t i = 0; i < hoCounts.length(); i++)
            if (hoCounts[i] > 0)
                _effCounts[hoBackoffs[i]]++;

        // Use original counts for n-grams without left context.
        // Ex. N-grams starting with <s>.
        _effCounts.masked(_effCounts == 0) = _pLM->counts(_order);
    } else {
        // Use original counts for highest order.
        _effCounts.attach(_pLM->counts(_order));
    }

    if (pLM->features(order).size() > 0) {
        // If weighting features specified, cannot pre-compute invHistCounts.
        _invHistCounts.reset(_pLM->sizes(order - 1));
        _ngramWeights.reset(_pLM->sizes(order));
    } else {
        // Pre-compute inverse of sum of adjusted counts for each history.
        CountVector histCounts(_pLM->sizes(_order - 1), 0);
        BinWeight(_pLM->hists(_order), _effCounts, histCounts);
        _invHistCounts = CondExpr(histCounts == 0,
                                  0, (Param)1 / asDouble(histCounts));
    }

    // Estimate fixed Kneser-Ney discount factors from count stats.
    CountVector n(_discOrder + 2, 0);
    // BinCount(_effCounts[_effCounts < n.length()], n);
    BinClippedCount(_effCounts, n);
    double Y;
    if (n[1] == 0 && n[2] == 0)
      Y = 1.0;
    else
      Y = (double)n[1] / (n[1] + 2*n[2]);
    Logger::Log(1, "Y %e\n", Y);
    assert(!std::isnan(Y));
    //Range r(1, _discParams.length());
    //_discParams = CondExpr(n == 0, r, r - (r+1) * Y * n[r+1] / n[r]);
    //_discParams = min(r, max(0, _discParams));
    _discParams.resize(_discOrder + 1, 0);
    for (size_t i = 1; i < _discParams.length(); i++) {
        _discParams[i] = (n[i] == 0) ? i : (i - (i+1) * Y * n[i+1] / n[i]);
        if (_discParams[i] < 0) _discParams[i] = 0;
        if (_discParams[i] > i) _discParams[i] = i;
    }

    // Set default parameters.
    if (_tuneParams)
        _defParams = _discParams[Range(1, _discParams.length())];
    else
        _defParams.reset(0);

    // Set n-gram weighting parameters.
    _defParams.resize(_defParams.length() + _pLM->features(order).size(), 0);
}

void
KneserNeySmoothing::UpdateMask(NgramLMMask &lmMask) const {
    BitVector &        probMask(lmMask.ProbMaskVectors[_order]);
    BitVector &        boProbMask(lmMask.ProbMaskVectors[_order - 1]);
    BitVector &        boBowMask(lmMask.BowMaskVectors[_order - 1]);
    const IndexVector &histories(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));

    // Computing prob requires backoff prob and history bow.
    // boProbMask[backoffs] |= probMask;
    // boProbMask[histories] |= probMask;
    for (size_t i = 0; i < probMask.length(); i++) {
        if (probMask[i]) {
            if (!boProbMask[backoffs[i]])
                boProbMask[backoffs[i]] = true;
            if (!boBowMask[histories[i]])
                boBowMask[histories[i]] = true;
        }
    }

    // Compute discounts for any n-gram whose history is in bow mask.
    KneserNeySmoothingMask *pSmoothingMask = new KneserNeySmoothingMask();
    pSmoothingMask->DiscMask = boBowMask[histories];
    lmMask.SmoothingMasks[_order] = pSmoothingMask;
}

bool
KneserNeySmoothing::Estimate(const ParamVector &params,
                             const NgramLMMask *pMask,
                             ProbVector &probs,
                             ProbVector &bows) {

    // Unpack discount parameters.
    if (_tuneParams) {
        // Check of out-of-bounds discount parameters.
        for (size_t i = 0; i < _discOrder; i++)
            if (params[i] < 0 || params[i] > i+1) {
                Logger::Log(2, "Clipping\n");
                return false;
            }
        _discParams[Range(1, _discParams.length())] = params[Range(_discOrder)];
    }
    // Check of out-of-bounds n-gram weighting parameters.
    size_t numDiscParams = _tuneParams ? _discOrder : 0;
    for (size_t i = numDiscParams; i < params.length(); i++)
        if (fabs(params[i] > 100)) {
            Logger::Log(2, "Clipping\n");
            return false;
        }

    // Compute n-gram weights and inverse history counts, if necessary.
    size_t numFeatures = _pLM->features(_order).size();
    if (numFeatures > 0) {
        Range r(numDiscParams, numDiscParams + numFeatures);
        _ComputeWeights(ParamVector(params[r]));
        _invHistCounts.set(0);
        BinWeight(_pLM->hists(_order), _effCounts * _ngramWeights,
                  _invHistCounts);
        _invHistCounts = CondExpr(_invHistCounts == 0,
                                  0, (Param)1 / _invHistCounts);
    }

    // Estimate probs and bows using optimized methods.
    if (numFeatures > 0) {
        if (pMask != NULL)
            _EstimateWeightedMasked(pMask, probs, bows);
        else
            _EstimateWeighted(probs, bows);
    } else {
        if (pMask != NULL)
            _EstimateMasked(pMask, probs, bows);
        else
            _Estimate(probs, bows);
    }
    return true;
}

void
KneserNeySmoothing::_ComputeWeights(const ParamVector &featParams) {
    _ngramWeights.set(0);
    for (size_t f = 0; f < featParams.length(); ++f)
        if (featParams[f] != 0)
            _ngramWeights += _pLM->features(_order)[f] * featParams[f];
    _ngramWeights = exp(_ngramWeights);
}

void
KneserNeySmoothing::_Estimate(ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    discounts = _discParams[min(_effCounts, _discOrder)];

    // Compute backoff weights.
    bows.set(0);
    BinWeight(hists, discounts, bows);
    bows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    assert(!anyTrue(isnan(_invHistCounts)));
    assert(!anyTrue(isnan(bows)));

    // Compute interpolated probabilities.
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs = CondExpr(!_effCounts, 0,
                         (_effCounts - discounts) * _invHistCounts[hists]
                         + boProbs[backoffs] * bows[hists]);
    else
        probs = CondExpr(!_effCounts, 0,
                         (_effCounts - discounts) * _invHistCounts[hists])
                + boProbs[backoffs] * bows[hists];
    assert(!anyTrue(isnan(probs)));
}

void
KneserNeySmoothing::_EstimateMasked(const NgramLMMask *pMask,
                                    ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    const BitVector &discMask(((KneserNeySmoothingMask *)
                              pMask->SmoothingMasks[_order].get())->DiscMask);
    assert(discMask.length() == _effCounts.length());
//    discounts.masked(discMask) = _discParams[min(_effCounts, _discOrder)];
    for (size_t i = 0; i < _effCounts.length(); i++)
        if (discMask[i])
            discounts[i] = _discParams[std::min(_effCounts[i], (int)_discOrder)];

    // Compute backoff weights.
    const BitVector &bowMask(pMask->BowMaskVectors[_order - 1]);
    MaskedVectorClosure<ProbVector, BitVector> maskedBows(bows.masked(bowMask));
    maskedBows.set(0);
    BinWeight(hists, discounts, maskedBows);
//    maskedBows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    for (size_t i = 0; i < bows.length(); i++)
        if (bowMask[i]) {
            if (_invHistCounts[i] == 0)
                bows[i] = 1;
            else
                bows[i] *= _invHistCounts[i];
        }

    // Compute interpolated probabilities.
    const BitVector &probMask(pMask->ProbMaskVectors[_order]);
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     (_effCounts - discounts) * _invHistCounts[hists]
                     + boProbs[backoffs] * bows[hists]);
    else
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     (_effCounts - discounts) * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

void
KneserNeySmoothing::_EstimateWeighted(ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    discounts = _discParams[min(_effCounts, _discOrder)];

    // Compute backoff weights.
    bows.set(0);
    BinWeight(hists, _ngramWeights * discounts, bows);
    bows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);

    // Compute interpolated probabilities.
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs = CondExpr(!_effCounts, 0,
                         _ngramWeights * (_effCounts - discounts)
                         * _invHistCounts[hists]
                         + boProbs[backoffs] * bows[hists]);
    else
        probs = CondExpr(!_effCounts, 0,
                         _ngramWeights * (_effCounts - discounts)
                         * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

void
KneserNeySmoothing::_EstimateWeightedMasked(const NgramLMMask *pMask,
                                            ProbVector &probs,
                                            ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    const BitVector &discMask(((KneserNeySmoothingMask *)
                              pMask->SmoothingMasks[_order].get())->DiscMask);
    assert(discMask.length() == _effCounts.length());
//    discounts.masked(discMask) = _discParams[min(_effCounts, _discOrder)];
    for (size_t i = 0; i < _effCounts.length(); i++)
        if (discMask[i])
            discounts[i] = _discParams[std::min(_effCounts[i], (int)_discOrder)];

    // Compute backoff weights.
    const BitVector &bowMask(pMask->BowMaskVectors[_order - 1]);
    MaskedVectorClosure<ProbVector, BitVector> maskedBows(bows.masked(bowMask));
    maskedBows.set(0);
    BinWeight(hists, _ngramWeights * discounts, maskedBows);
//    maskedBows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    for (size_t i = 0; i < bows.length(); i++)
        if (bowMask[i]) {
            if (_invHistCounts[i] == 0)
                bows[i] = 1;
            else
                bows[i] *= _invHistCounts[i];
        }

    // Compute interpolated probabilities.
    const BitVector &probMask(pMask->ProbMaskVectors[_order]);
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     _ngramWeights * (_effCounts - discounts)
                     * _invHistCounts[hists]
                     + boProbs[backoffs] * bows[hists]);
    else
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     _ngramWeights * (_effCounts - discounts)
                     * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

}
<commit_msg>Fixed minor bug in KneserNeySmoothing.cpp.<commit_after>////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2008, Massachusetts Institute of Technology              //
// All rights reserved.                                                   //
//                                                                        //
// Redistribution and use in source and binary forms, with or without     //
// modification, are permitted provided that the following conditions are //
// met:                                                                   //
//                                                                        //
//     * Redistributions of source code must retain the above copyright   //
//       notice, this list of conditions and the following disclaimer.    //
//                                                                        //
//     * Redistributions 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.                                           //
//                                                                        //
//     * Neither the name of the Massachusetts Institute of Technology    //
//       nor the names of its contributors may 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 COPYRIGHT   //
// OWNER 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.   //
////////////////////////////////////////////////////////////////////////////

#include <algorithm>
#include "util/Logger.h"
#include "NgramLM.h"
#include "Mask.h"
#include "KneserNeySmoothing.h"

using std::min;

///////////////////////////////////////////////////////////////////////////////

namespace mitlm {

void KneserNeySmoothing::Initialize(NgramLM *pLM, size_t order) {
    assert(order != 0);

    _pLM = pLM;
    _order = order;

    // Compute adjusted Kneser-Ney counts.
    if (_order < _pLM->order()) {
        // Compute left-branch counts.
        _effCounts.reset(_pLM->sizes(_order), 0);
        const CountVector &hoCounts(_pLM->counts(_order + 1));
        const IndexVector &hoBackoffs(_pLM->backoffs(_order + 1));
        // TODO: Need to implement operator[BitVector].
        //BinCount(hoBackoffs[hoCounts > 0], _effCounts);
        for (size_t i = 0; i < hoCounts.length(); i++)
            if (hoCounts[i] > 0)
                _effCounts[hoBackoffs[i]]++;

        // Use original counts for n-grams without left context.
        // Ex. N-grams starting with <s>.
        _effCounts.masked(_effCounts == 0) = _pLM->counts(_order);
    } else {
        // Use original counts for highest order.
        _effCounts.attach(_pLM->counts(_order));
    }

    if (pLM->features(order).size() > 0) {
        // If weighting features specified, cannot pre-compute invHistCounts.
        _invHistCounts.reset(_pLM->sizes(order - 1));
        _ngramWeights.reset(_pLM->sizes(order));
    } else {
        // Pre-compute inverse of sum of adjusted counts for each history.
        CountVector histCounts(_pLM->sizes(_order - 1), 0);
        BinWeight(_pLM->hists(_order), _effCounts, histCounts);
        _invHistCounts = CondExpr(histCounts == 0,
                                  0, (Param)1 / asDouble(histCounts));
    }

    // Estimate fixed Kneser-Ney discount factors from count stats.
    CountVector n(_discOrder + 2, 0);
    // BinCount(_effCounts[_effCounts < n.length()], n);
    BinClippedCount(_effCounts, n);
    double Y;
    if (n[1] == 0 && n[2] == 0)
      Y = 1.0;
    else
      Y = (double)n[1] / (n[1] + 2*n[2]);
    Logger::Log(1, "Y %e\n", Y);
    assert(!std::isnan(Y));
    //Range r(1, _discParams.length());
    //_discParams = CondExpr(n == 0, r, r - (r+1) * Y * n[r+1] / n[r]);
    //_discParams = min(r, max(0, _discParams));
    _discParams.resize(_discOrder + 1, 0);
    for (size_t i = 1; i < _discParams.length(); i++) {
        _discParams[i] = (n[i] == 0) ? i : (i - (i+1) * Y * n[i+1] / n[i]);
        if (_discParams[i] < 0) _discParams[i] = 0;
        if (_discParams[i] > i) _discParams[i] = i;
    }

    // Set default parameters.
    if (_tuneParams)
        _defParams = _discParams[Range(1, _discParams.length())];
    else
        _defParams.reset(0);

    // Set n-gram weighting parameters.
    _defParams.resize(_defParams.length() + _pLM->features(order).size(), 0);
}

void
KneserNeySmoothing::UpdateMask(NgramLMMask &lmMask) const {
    BitVector &        probMask(lmMask.ProbMaskVectors[_order]);
    BitVector &        boProbMask(lmMask.ProbMaskVectors[_order - 1]);
    BitVector &        boBowMask(lmMask.BowMaskVectors[_order - 1]);
    const IndexVector &histories(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));

    // Computing prob requires backoff prob and history bow.
    // boProbMask[backoffs] |= probMask;
    // boProbMask[histories] |= probMask;
    for (size_t i = 0; i < probMask.length(); i++) {
        if (probMask[i]) {
            if (!boProbMask[backoffs[i]])
                boProbMask[backoffs[i]] = true;
            if (!boBowMask[histories[i]])
                boBowMask[histories[i]] = true;
        }
    }

    // Compute discounts for any n-gram whose history is in bow mask.
    KneserNeySmoothingMask *pSmoothingMask = new KneserNeySmoothingMask();
    pSmoothingMask->DiscMask = boBowMask[histories];
    lmMask.SmoothingMasks[_order] = pSmoothingMask;
}

bool
KneserNeySmoothing::Estimate(const ParamVector &params,
                             const NgramLMMask *pMask,
                             ProbVector &probs,
                             ProbVector &bows) {

    // Unpack discount parameters.
    if (_tuneParams) {
        // Check of out-of-bounds discount parameters.
        for (size_t i = 0; i < _discOrder; i++)
            if (params[i] < 0 || params[i] > i+1) {
                Logger::Log(2, "Clipping\n");
                return false;
            }
        _discParams[Range(1, _discParams.length())] = params[Range(_discOrder)];
    }
    // Check of out-of-bounds n-gram weighting parameters.
    size_t numDiscParams = _tuneParams ? _discOrder : 0;
    for (size_t i = numDiscParams; i < params.length(); i++)
        if (fabs(params[i]) > 100) {
            Logger::Log(2, "Clipping\n");
            return false;
        }

    // Compute n-gram weights and inverse history counts, if necessary.
    size_t numFeatures = _pLM->features(_order).size();
    if (numFeatures > 0) {
        Range r(numDiscParams, numDiscParams + numFeatures);
        _ComputeWeights(ParamVector(params[r]));
        _invHistCounts.set(0);
        BinWeight(_pLM->hists(_order), _effCounts * _ngramWeights,
                  _invHistCounts);
        _invHistCounts = CondExpr(_invHistCounts == 0,
                                  0, (Param)1 / _invHistCounts);
    }

    // Estimate probs and bows using optimized methods.
    if (numFeatures > 0) {
        if (pMask != NULL)
            _EstimateWeightedMasked(pMask, probs, bows);
        else
            _EstimateWeighted(probs, bows);
    } else {
        if (pMask != NULL)
            _EstimateMasked(pMask, probs, bows);
        else
            _Estimate(probs, bows);
    }
    return true;
}

void
KneserNeySmoothing::_ComputeWeights(const ParamVector &featParams) {
    _ngramWeights.set(0);
    for (size_t f = 0; f < featParams.length(); ++f)
        if (featParams[f] != 0)
            _ngramWeights += _pLM->features(_order)[f] * featParams[f];
    _ngramWeights = exp(_ngramWeights);
}

void
KneserNeySmoothing::_Estimate(ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    discounts = _discParams[min(_effCounts, _discOrder)];

    // Compute backoff weights.
    bows.set(0);
    BinWeight(hists, discounts, bows);
    bows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    assert(!anyTrue(isnan(_invHistCounts)));
    assert(!anyTrue(isnan(bows)));

    // Compute interpolated probabilities.
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs = CondExpr(!_effCounts, 0,
                         (_effCounts - discounts) * _invHistCounts[hists]
                         + boProbs[backoffs] * bows[hists]);
    else
        probs = CondExpr(!_effCounts, 0,
                         (_effCounts - discounts) * _invHistCounts[hists])
                + boProbs[backoffs] * bows[hists];
    assert(!anyTrue(isnan(probs)));
}

void
KneserNeySmoothing::_EstimateMasked(const NgramLMMask *pMask,
                                    ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    const BitVector &discMask(((KneserNeySmoothingMask *)
                              pMask->SmoothingMasks[_order].get())->DiscMask);
    assert(discMask.length() == _effCounts.length());
//    discounts.masked(discMask) = _discParams[min(_effCounts, _discOrder)];
    for (size_t i = 0; i < _effCounts.length(); i++)
        if (discMask[i])
            discounts[i] = _discParams[std::min(_effCounts[i], (int)_discOrder)];

    // Compute backoff weights.
    const BitVector &bowMask(pMask->BowMaskVectors[_order - 1]);
    MaskedVectorClosure<ProbVector, BitVector> maskedBows(bows.masked(bowMask));
    maskedBows.set(0);
    BinWeight(hists, discounts, maskedBows);
//    maskedBows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    for (size_t i = 0; i < bows.length(); i++)
        if (bowMask[i]) {
            if (_invHistCounts[i] == 0)
                bows[i] = 1;
            else
                bows[i] *= _invHistCounts[i];
        }

    // Compute interpolated probabilities.
    const BitVector &probMask(pMask->ProbMaskVectors[_order]);
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     (_effCounts - discounts) * _invHistCounts[hists]
                     + boProbs[backoffs] * bows[hists]);
    else
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     (_effCounts - discounts) * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

void
KneserNeySmoothing::_EstimateWeighted(ProbVector &probs, ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    discounts = _discParams[min(_effCounts, _discOrder)];

    // Compute backoff weights.
    bows.set(0);
    BinWeight(hists, _ngramWeights * discounts, bows);
    bows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);

    // Compute interpolated probabilities.
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs = CondExpr(!_effCounts, 0,
                         _ngramWeights * (_effCounts - discounts)
                         * _invHistCounts[hists]
                         + boProbs[backoffs] * bows[hists]);
    else
        probs = CondExpr(!_effCounts, 0,
                         _ngramWeights * (_effCounts - discounts)
                         * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

void
KneserNeySmoothing::_EstimateWeightedMasked(const NgramLMMask *pMask,
                                            ProbVector &probs,
                                            ProbVector &bows) {
    const IndexVector &hists(_pLM->hists(_order));
    const IndexVector &backoffs(_pLM->backoffs(_order));
    const ProbVector & boProbs(_pLM->probs(_order - 1));

    // Compute discounts.
    ProbVector &discounts(probs);  // Reuse probs vector for discounts.
    const BitVector &discMask(((KneserNeySmoothingMask *)
                              pMask->SmoothingMasks[_order].get())->DiscMask);
    assert(discMask.length() == _effCounts.length());
//    discounts.masked(discMask) = _discParams[min(_effCounts, _discOrder)];
    for (size_t i = 0; i < _effCounts.length(); i++)
        if (discMask[i])
            discounts[i] = _discParams[std::min(_effCounts[i], (int)_discOrder)];

    // Compute backoff weights.
    const BitVector &bowMask(pMask->BowMaskVectors[_order - 1]);
    MaskedVectorClosure<ProbVector, BitVector> maskedBows(bows.masked(bowMask));
    maskedBows.set(0);
    BinWeight(hists, _ngramWeights * discounts, maskedBows);
//    maskedBows = CondExpr(_invHistCounts == 0, 1, bows * _invHistCounts);
    for (size_t i = 0; i < bows.length(); i++)
        if (bowMask[i]) {
            if (_invHistCounts[i] == 0)
                bows[i] = 1;
            else
                bows[i] *= _invHistCounts[i];
        }

    // Compute interpolated probabilities.
    const BitVector &probMask(pMask->ProbMaskVectors[_order]);
    if (_order == 1 && !_pLM->vocab().IsFixedVocab())
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     _ngramWeights * (_effCounts - discounts)
                     * _invHistCounts[hists]
                     + boProbs[backoffs] * bows[hists]);
    else
        probs.masked(probMask) =
            CondExpr(!_effCounts, 0,
                     _ngramWeights * (_effCounts - discounts)
                     * _invHistCounts[hists])
            + boProbs[backoffs] * bows[hists];
}

}
<|endoftext|>