Exemple #1
0
bool MultiAggregate::notificationAggregateLit( Solver& solver, Literal lit, int p )
{
    assert( p != 0 );
    if( solver.getImplicant( lit.getVariable() ) != this )
        addInTrail( solver, lit, false, p );    
    
    if( solver.getDecisionLevel( lit ) > 0 )
    {
        assert( positionInTrail.find( lit.getId() ) != positionInTrail.end() );
        assert( positionInTrail[ lit.getId() ] < trail.size() );
        trail[ positionInTrail[ lit.getId() ] ].setPropagated();
    }
    
    if( p > 0 )
    {
        unsigned int pos = p;        
        trace_msg( multiaggregates, 2, "Updating current sum to " << ( currentSum + getWeight( pos ) ) << " (was " << currentSum << ")");           
        currentSum += getWeight( pos );
        
        if( currentSum >= getBound( w1 + 1 ) )
        {
            assert( solver.isTrue( getId( w1 ) ) );            
            unsigned int tmp = w1;
            while( currentSum >= getBound( tmp + 1 ) )
                ++tmp;
            if( !inferLiteral( solver, getId( tmp ), true, tmp ) )
                return true;
        }
        checkFalseInference( solver, lit );
    }
    else
    {
        unsigned int pos = -p;
        trace_msg( multiaggregates, 2, "Updating max possible sum to " << ( maxPossibleSum - getWeight( pos ) ) << " (was " << maxPossibleSum << ")");
        maxPossibleSum -= getWeight( pos );        

        if( maxPossibleSum < getBound( w2 - 1 ) )
        {
            assert( solver.isFalse( getId( w2 ) ) );
            unsigned int tmp = w2;
            while( maxPossibleSum < getBound( tmp - 1 ) )
                --tmp;
            if( !inferLiteral( solver, getId( tmp ).getOppositeLiteral(), true, -tmp ) )
                return true;            
        }
        checkTrueInference( solver, lit );
    }
    return true;
}
Exemple #2
0
bool
OcclusionQueryNode::getPassed( const osg::Camera* camera, float distanceToEyePoint )
{
    if ( !_enabled )
        // Queries are not enabled. The caller should be osgUtil::CullVisitor,
        //   return true to traverse the subgraphs.
        return true;

    // In the future, we could hold a reference directly to the QueryDrawable
    //   to avoid the dynamic_cast.
    QueryGeometry* qg = dynamic_cast< QueryGeometry* >( _queryGeode->getDrawable( 0 ) );
    if (qg == NULL)
    {
        osg::notify( osg::FATAL ) <<
            "osgOQ: OcclusionQueryNode: No QueryGeometry." << std::endl;
        // Something's broke. Return true so we at least render correctly.
        return true;
    }

    // If the distance to the bounding sphere shell is positive, retrieve
    //   the results. Others (we're inside the BS shell) we are considered
    //   to have passed and don't need to retrieve the query.
    const osg::BoundingSphere& bs = getBound();
    float distance = distanceToEyePoint  - bs._radius;
    _passed = ( distance <= 0.f );
    if (!_passed)
    {
        int result = qg->getNumPixels( camera );
        _passed = ( (unsigned int)(result) > _visThreshold );
    }

    return _passed;
}
Exemple #3
0
    void ShaderProgram::bindTextures() const
    {
        for(const auto& i : textures_)
        {
            //Activate the appropriate texture unit and texture
            Texture::setActiveUnit(i.first);
            i.second.second->bind();

            if(!ext::separateShaderObjects()) //If we can't do uniforms without binding
            {
                //Get the currently-bound program and bind this program
                auto previous = getBound();
                bind();

                //Set the uniform
                glCheck(glUniform1i(i.second.first, i.first));

                //Set the previous values back
                glCheck(glUseProgram(previous));

            }
            else //If we can do uniforms without binding
            {
                //Set the uniform with this program
                glCheck(glProgramUniform1i(program_, i.second.first, i.first));
            }
        }

        //Reset the active texture unit to 0
        Texture::setActiveUnit(0);
    }
Exemple #4
0
void PlayScene::moveMap(float offsetX, float offsetY)
{
  float posX = mTileMap->getPosition().x + offsetX;
  float posY = mTileMap->getPosition().y + offsetY;
  if (posX > 0)
    posX = 0;
  if (posX < getBound().x)
    posX = getBound().x;
  if (posY > 0)
    posY = 0;
  if (posY < getBound().y)
  {
    posY = getBound().y;
  }
  mTileMap->setPosition(ccp(posX, posY));
}
void OSGViewerWidget::centerSceneIfNecessary(void)
{
  bool locked = mutex_.tryLock();
  scene_root_->accept(UpdateVisitor());
  if (locked)
    mutex_.unlock();

  osg::BoundingSphere bounding_sphere = getBound();
  if (bounding_sphere.center() == osg::Vec3(0, 0, 0))
    return;

  MainWindow::getInstance()->getRegistrator()->init();

  osg::Vec3d eye, center, up;
  getCamera()->getViewMatrixAsLookAt(eye, center, up);

  double c2 = (eye-bounding_sphere.center()).length2();
  osg::Vec3d view_direction = eye - center;
  view_direction.normalize();
  double a = (eye-bounding_sphere.center())*view_direction;
  double distance = std::sqrt(c2-a*a);
  if (distance < 16*bounding_sphere.radius()) // Line and sphere intersect
    return;

  centerSceneImpl();

  return;
}
Exemple #6
0
 PySparseTensor innerProduct(const nta::UInt32 dim1, const nta::UInt32 dim2, const PySparseTensor& B) const
 {
   // Only works on rank 2 tensors right now
   if((getRank() != 2) || (B.getRank() != 2))
     throw std::invalid_argument("innerProduct only works for rank 2 tensors.");
   PySparseTensor C(PyTensorIndex(getBound(1-dim1),B.getBound(1-dim2)));
   tensor_.inner_product_nz(dim1, dim2, B.tensor_, C.tensor_, std::multiplies<nta::Real>(), std::plus<nta::Real>());
   return C;
 }
void bimWorld::CameraManipulator::setModelCenterKeepViewPoint(void* ptr)
{
	auto node = static_cast<osg::Node*>(ptr);
	if (!ptr)
	{
		return;
	}
	getBIMCameraManip()->setModelCenter(node->getBound().center());
}
//如果是简单的单击处理,只需要在Began中处理就可以了,无需到ccTouchEnded中
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {

    //如果输入盘打开了,并且点中了输入盘的某个数字,则填入选择的数字,并隐藏输入盘
    if(g_pad->isVisible() && g_pad->containsTouchLocation(pTouch)) {
        int number = g_pad->getNumber(pTouch);
        _inputGrid->setValue(number);
        g_pad->setVisible(false);
        if(checkWin()) {
            //此处关闭单点触摸,只能点击按钮进行下一步
            CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this); 
            showWin();
        }
        return true;
    }

    //如果是初始的数字,不允许修改
    if(!canInput(pTouch)) {
        g_pad->setVisible(false);
        return true;
    }
    CCPoint pos = pTouch->getLocation();

    pos.x = getBound(pos.x,g_pad->rect().getMaxX(),0,_background->getContentSize().width);
    pos.y = getBound(pos.y,g_pad->rect().getMaxY(),0,_background->getContentSize().height);

    //CCLOG("final pos x:%0.1f,y:%0.1f",pos.x,pos.y);

    runFx(pos);
    
    g_pad->setPosition(pos);
    g_pad->setScale(0.1f);
	g_pad->setVisible(true);
    SimpleAudioEngine::sharedEngine()->playEffect(CLICK_FILE);
    CCActionInterval*  actionTo = CCScaleTo::create(0.05f, 1.2f);
    CCActionInterval*  actionBack = CCScaleTo::create(0.05f,1.0f);
    //添加一些动作,可以仅仅是单个动作,也可以是多个动作组合
    //g_pad->runAction(actionTo);
    g_pad->runAction( CCSequence::create(actionTo, actionBack, NULL));
    _inputGrid = getGrid(pTouch);
    
    return true;
}
Exemple #9
0
bool OcclusionQueryNode::getPassed( const Camera* camera, NodeVisitor& nv )
{
    if ( !_enabled )
        // Queries are not enabled. The caller should be osgUtil::CullVisitor,
        //   return true to traverse the subgraphs.
        return true;

    {
        // Two situations where we want to simply do a regular traversal:
        //  1) it's the first frame for this camera
        //  2) we haven't rendered for an abnormally long time (probably because we're an out-of-range LOD child)
        // In these cases, assume we're visible to avoid blinking.
        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( _frameCountMutex );
        const unsigned int& lastQueryFrame( _frameCountMap[ camera ] );
        if( ( lastQueryFrame == 0 ) ||
            ( (nv.getTraversalNumber() - lastQueryFrame) >  (_queryFrameCount + 1) ) )
            return true;
    }

    if (_queryGeode->getDrawable( 0 ) == NULL)
    {
        OSG_FATAL << "osgOQ: OcclusionQueryNode: No QueryGeometry." << std::endl;
        // Something's broke. Return true so we at least render correctly.
        return true;
    }
    QueryGeometry* qg = static_cast< QueryGeometry* >( _queryGeode->getDrawable( 0 ) );

    // Get the near plane for the upcoming distance calculation.
    float nearPlane;
    const osg::Matrix& proj( camera->getProjectionMatrix() );
    if( ( proj(3,3) != 1. ) || ( proj(2,3) != 0. ) || ( proj(1,3) != 0. ) || ( proj(0,3) != 0.) )
        nearPlane = proj(3,2) / (proj(2,2)-1.);  // frustum / perspective
    else
        nearPlane = (proj(3,2)+1.) / proj(2,2);  // ortho

    // If the distance from the near plane to the bounding sphere shell is positive, retrieve
    //   the results. Otherwise (near plane inside the BS shell) we are considered
    //   to have passed and don't need to retrieve the query.
    const osg::BoundingSphere& bs = getBound();
    float distanceToEyePoint = nv.getDistanceToEyePoint( bs._center, false );

    float distance = distanceToEyePoint - nearPlane - bs._radius;
    _passed = ( distance <= 0.f );
    if (!_passed)
    {
        int result = qg->getNumPixels( camera );
        _passed = ( (unsigned int)(result) > _visThreshold );
    }

    return _passed;
}
Exemple #10
0
void
MultiAggregate::checkTrueInference( Solver& solver, Literal lit )
{
    trace_msg( multiaggregates, 3, "Checking true inference: max possible sum = " << maxPossibleSum );
    unsigned int posInTrail = solver.getPositionInTrail( lit.getVariable() );
    for( unsigned int i = 1; i < literals.size(); i++ )
    {
        Literal current = getLiteral( i );
        trace_msg( multiaggregates, 4, "Considering literal " << current );
        if( solver.isTrue( current ) ) continue;
        if( solver.isUndefined( current ) || solver.getPositionInTrail( current.getVariable() ) > posInTrail )
        {
            if( maxPossibleSum - getWeight( i ) >= getBound( w1 ) ) break;
            if( !inferLiteral( solver, current, false, i ) )
                return;
        }
    }
}
Exemple #11
0
    void ShaderProgram::setUniform(const std::string& name, float first, float second, float third, float fourth)
    {
        if(!ext::separateShaderObjects()) //If we can't do uniforms without binding
        {
            //Get the currently-bound program and bind this program
            auto previous = getBound();
            bind();

            //Set the uniform
            glCheck(glUniform4f(uniformLocation(name), first, second, third, fourth));

            //Set the previous program back
            glCheck(glUseProgram(previous));
        }
        else //If we can do uniforms without binding
        {
            //Set the uniform with this program
            glCheck(glProgramUniform4f(program_, uniformLocation(name), first, second, third, fourth));
        }
    }
Exemple #12
0
    void ShaderProgram::setUniform(const std::string& name, const glm::mat4& matrix)
    {
        if(!ext::separateShaderObjects()) //If we can't do uniforms without binding
        {
            //Get the currently-bound program and bind this program
            auto previous = getBound();
            bind();

            //Set the uniform
            glCheck(glUniformMatrix4fv(uniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)));

            //Set the previous program back
            glCheck(glUseProgram(previous));
        }
        else //If we can do uniforms without binding
        {
            //Set the uniform with this program
            glCheck(glProgramUniformMatrix4fv(program_, uniformLocation(name), 1, GL_FALSE, glm::value_ptr(matrix)));
        }
    }
void PointCloud::updateImpl()
{

  visualizePoints(0, size());

  if (show_draggers_)
  {
    osg::BoundingSphere boundingSphere = getBound();
    osg::Matrix trans = osg::Matrix::translate(boundingSphere.center());
    double radius = boundingSphere.radius();
    float t_scale = radius/4;
    float r_scale = radius/8;
    osg::Matrix flip(osg::Matrix::rotate(osg::Vec3(0, 1, 0), osg::Vec3(0, -1, 0)));
    translate_dragger_->setMatrix(flip*osg::Matrix::scale(t_scale, t_scale, t_scale)*trans);
    trackball_dragger_->setMatrix(osg::Matrix::scale(r_scale, r_scale, r_scale)*trans);

    addChild(translate_dragger_);
    addChild(trackball_dragger_);
  }

  return;
}
void OSGViewerWidget::centerSceneImpl(void)
{
  osgGA::CameraManipulator* camera_manipulator = getCameraManipulator();

  osg::BoundingSphere bounding_sphere = getBound();
  double radius = bounding_sphere.radius();
  osg::Vec3d eye_offset(0.0, 0.0, -2*radius);
  camera_manipulator->setHomePosition(bounding_sphere.center() + eye_offset, bounding_sphere.center(), osg::Vec3d(0.0f,-1.0f,0.0f));
  camera_manipulator->home(0);

  double offset = radius/1.5;
  std::vector<osg::Vec3> offsets;
  offsets.push_back(osg::Vec3(0, 0, -offset));
  offsets.push_back(osg::Vec3(0, 0, offset));
  offsets.push_back(osg::Vec3(-offset, 0, 0));
  offsets.push_back(osg::Vec3(offset, 0, 0));
  offsets.push_back(osg::Vec3(0, -offset, 0));
  offsets.push_back(osg::Vec3(0, offset, 0));
  for (int i = 0; i < 6; ++ i)
    light_sources_[i]->init(bounding_sphere.center() + offsets[i]);

  return;
}
void bimWorld::CameraManipulator::switchMatrixManipulator(ManipulatorType emanip)
{
	auto viewer = m_host->_ViewerData()->ModelViewer();
	auto sceneRoot = m_host->_ViewerData()->getSceneRoot();
	auto modelRoot = m_host->_ViewerData()->getModelRoot();
	if (!viewer || !sceneRoot || !modelRoot)
	{
		return;
	}
	m_host->_RenderingThreads()->setIsExternalRendering(true);
	auto manip = viewer->getCameraManipulator();
	osg::Vec3d eye, center, up;
	auto matrix = manip->getMatrix();
	manip->getHomePosition(eye, center, up);
	switch (emanip)
	{
	case ManipulatorType::Default:
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT0,
			osg::StateAttribute::ON);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT1,
			osg::StateAttribute::ON);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT2,
			osg::StateAttribute::OFF);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT3,
			osg::StateAttribute::OFF);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT4,
			osg::StateAttribute::OFF);
		((BIMCameraManipulator*)m_d.get())->setPosition(eye, center, up, matrix);

		////                BIMCameraManipulator* mat = (BIMCameraManipulator*)(m_d.get());
		//                 ((BIMCameraManipulator*)m_d.get())->beginSetCameraMatrix();
		//                ((BIMCameraM-anipulator*)m_d.get())->setByMatrix(matrix);
		//               ((BIMCameraManipulator*)m_d.get())->endSetCameraMatrix();
		viewer->setCameraManipulator(((BIMCameraManipulator*)m_d.get()), false);
		break;
	case ManipulatorType::Person:
	{
		auto oldManip = static_cast<BIMCameraManipulator*>(manip);
		if (!oldManip)
			break;
		auto rotation = oldManip->getRotation();
		auto dist = oldManip->getDistance();
		auto personManip = static_cast<PersonManipulator*>(m_p.get());
		if (!personManip)
			break;
		personManip->setScreenRotation(rotation);
		personManip->setScreenDistance(dist);
		personManip->setPosition(eye, center, up, matrix);
		viewer->setCameraManipulator(personManip, false);
		break;
	}
	case ManipulatorType::FirstPerson:
	{
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT0,
			osg::StateAttribute::OFF);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT1,
			osg::StateAttribute::OFF);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT2,
			osg::StateAttribute::ON);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT3,
			osg::StateAttribute::ON);
		sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHT4,
			osg::StateAttribute::ON);

		osgGA::CameraManipulator* first = new BIMFirstPersonManipulator(m_host);
		viewer->setCameraManipulator(first, true);

		first->setHomePosition(modelRoot->getBound().center(), osg::Vec3(0, 0, 0), up);
		viewer->home();
		break;
	}
	}
	m_host->_RenderingThreads()->setIsExternalRendering(false);

	return;

	//		osgGA::KeySwitchMatrixManipulator *switchmanipulator = dynamic_cast<osgGA::KeySwitchMatrixManipulator*>(m_mViewer->getCameraManipulator());
	//
	//		//m_ptrKeySwitchMatrixManipulator=new osgGA::KeySwitchMatrixManipulator;
	//		//m_ptrKeySwitchMatrixManipulator->addMatrixManipulator(1,"deflaut",createCameraManipulator());
	//		//m_ptrKeySwitchMatrixManipulator->addMatrixManipulator(2,"person",createPersonManipulator());
	//		switchmanipulator->selectMatrixManipulator((int)emanip);
	//		if (emanip == deflaut)
	//		{
	//			BIMCameraManipulator* manipulator = dynamic_cast<BIMCameraManipulator*>(switchmanipulator->getCurrentMatrixManipulator());
	//
	//			zoomTo(m_modelRoot);
	//			//if (manipulator)
	//			//{
	//			//	manipulator->setupFrameRateController(m_modelRoot.get());
	//			//	manipulator->setModelRoot(m_modelRoot);
	//			//}
	//		}
	//		else if (emanip == person)
	//		{
	//			PersonManipulator* manipulator = dynamic_cast<PersonManipulator*>(switchmanipulator->getCurrentMatrixManipulator());
	//			zoomTo(m_modelRoot);
	//			//if (manipulator)
	//			//{
	//			//	manipulator->setupFrameRateController(m_modelRoot.get());
	//			//	manipulator->setModelRoot(m_modelRoot);
	//			//}
	//		}

	m_host->_RenderingThreads()->updateSeveralTimes(1);
}
/*
void IGUIElement::load(io::IDeserializer* stream) throw(CIOException)
{
	const c8* BOUND_NAME = "bound";
	const c8* SIZE_NAME = "size";
	const c8* IS_VISIBLE_NAME = "isVisible";
	const c8* STATE_NAME = "state";
	const c8* IS_ENABLED_NAME = "isEnabled";

	log::LOG_DEBUG("Deserializing element.");

	setBound(stream->readRectangle(BOUND_NAME));
	//setSize(stream->readVector(SIZE_NAME));
	setIsVisible(stream->readBoolean(IS_VISIBLE_NAME));

	//TODO
	//setState(stream->readBoolean(IS_ENABLED_NAME)?EES_ENABLED : EES_DISABLED);

	//log::LOG_DEBUG("Element deserialized.");
}
*/
void IGUIElement::save(io::IAttributeExchangingObject* aeo) throw(CIOException)
{
	aeo->addBoolean(VISIBLE_ATTR, isVisible());
	aeo->addRectangle(BOUND_ATTR, getBound());
	aeo->addInteger(STATE_ATTR, getState());	
}
void VariationalBayes::optimize(bool verbose,OPT_TYPE method,long maxIter,double ftol, double gtol){//{{{
   bool usedSteepest;
   long iteration=0,i,r;
   double boundOld,bound,squareNorm,squareNormOld=1,valBeta=0,valBetaDiv,natGrad_i,gradGamma_i,phiGradPhiSum_r;
   double *gradPhi,*natGrad,*gradGamma,*searchDir,*tmpD,*phiOld;
   gradPhi=natGrad=gradGamma=searchDir=tmpD=phiOld=NULL;
   MyTimer timer;
   // allocate stuff {{{
   //SimpleSparse *phiGradPhi=new SimpleSparse(beta);
   gradPhi = new double[T];
   // phiOld = new double[T]; will use gradPhi memory for this
   phiOld = NULL;
   natGrad = new double[T];
   if(method == OPTT_HS)
      gradGamma = new double[T];
   searchDir = new double[T];
   //searchDirOld = new double[T];
   //phiGradPhi_sum = new double[N];
   // }}}
#ifdef LOG_CONV
   ofstream logF(logFileName.c_str());
   logF.precision(15);
   logF<<"# iter bound squareNorm time(m) [M*means M*vars]"<<endl;
   if(logTimer)logTimer->setQuiet();
   #ifdef LONG_LOG
   vector<double> dirAlpha(M);
   #endif
#endif
   boundOld=getBound();
   timer.start();
   while(true){
      negGradient(gradPhi);
      // "yuck"
      //setVal(phiGradPhi,i,phi->val[i]*gradPhi[i]);
      //phiGradPhi->sumRows(phiGradPhi_sum);
      // removed need for phiGradPhi matrix:
      // removed need for phiGradPhi_sum
      /*for(r=0;r<N;r++){
         phiGradPhi_sum[r] = 0;
         for(i=phi->rowStart[r];i<phi->rowStart[r+1];i++) phiGradPhi_sum[r] += phi->val[i] * gradPhi[i];
      }*/

      // set natGrad & gradGamma
      squareNorm=0;
      valBeta = 0;
      valBetaDiv = 0;
      #pragma omp parallel for private(i,phiGradPhiSum_r,natGrad_i,gradGamma_i) reduction(+:squareNorm,valBeta,valBetaDiv)
      for(r=0;r<N;r++){
         phiGradPhiSum_r = 0;
         for(i = phi->rowStart[r]; i < phi->rowStart[r+1]; i++) 
            phiGradPhiSum_r += phi->val[i] * gradPhi[i];
         
         for(i = phi->rowStart[r]; i < phi->rowStart[r+1]; i++){
            natGrad_i = gradPhi[i] - phiGradPhiSum_r;
            gradGamma_i = natGrad_i * phi->val[i];
            squareNorm += natGrad_i * gradGamma_i;
            
            if(method==OPTT_PR){
               valBeta += (natGrad_i - natGrad[i])*gradGamma_i;
            }
            if(method==OPTT_HS){
               valBeta += (natGrad_i-natGrad[i])*gradGamma_i;
               valBetaDiv += (natGrad_i-natGrad[i])*gradGamma[i];
               gradGamma[i] = gradGamma_i;
            }
            natGrad[i] = natGrad_i;
         }
      }
      
      if((method==OPTT_STEEPEST) || (iteration % (N*M)==0)){
         valBeta=0;
      }else if(method==OPTT_PR ){
         // already computed:
         // valBeta=0;
         // for(i=0;i<T;i++)valBeta+= (natGrad[i]-natGradOld[i])*gradGamma[i];
         valBeta /= squareNormOld;
      }else if(method==OPTT_FR ){
         valBeta = squareNorm / squareNormOld;
      }else if(method==OPTT_HS ){
         // already computed:
         //valBeta=div=0;
         //for(i=0;i<T;i++){
         //   valBeta += (natGrad[i]-natGradOld[i])*gradGamma[i];
         //   div += (natGrad[i]-natGradOld[i])*gradGammaOld[i];
         //}
         if(valBetaDiv!=0)valBeta /= valBetaDiv;
         else valBeta = 0;
      }

      if(valBeta>0){
         usedSteepest = false;
         //for(i=0;i<T;i++)searchDir[i]= -natGrad[i] + valBeta*searchDirOld[i];
         // removed need for searchDirOld:
         #pragma omp parallel for
         for(i=0;i<T;i++)
            searchDir[i]= -natGrad[i] + valBeta*searchDir[i];
      }else{
         usedSteepest = true;
         #pragma omp parallel for
         for(i=0;i<T;i++)
            searchDir[i]= -natGrad[i];
      }

      //try conjugate step
      SWAPD(gradPhi,phiOld);
      memcpy(phiOld,phi_sm->val,T*sizeof(double)); // memcpy(phiOld,pack(),T*sizeof(double));
      unpack(phiOld,searchDir);
      bound = getBound();
      iteration++;
      // make sure there is an increase in L, else revert to steepest
      if((bound<boundOld) && (valBeta>0)){
         usedSteepest = true;
         #pragma omp parallel for
         for(i=0;i<T;i++)
            searchDir[i]= -natGrad[i];
         unpack(phiOld,searchDir);
         bound = getBound();
         // this should not be increased: iteration++;
      }
      if(bound<boundOld) { // If bound decreased even after using steepest, step back and quit.
         unpack(phiOld);
      }
      SWAPD(gradPhi,phiOld);
      if(verbose){
         #ifdef SHOW_FIXED
            messageF("iter(%c): %5.ld  bound: %.3lf grad: %.7lf  beta: %.7lf  fixed: %ld\n",(usedSteepest?'s':'o'),iteration,bound,squareNorm,valBeta,phi->countAboveDelta(0.999));
         #else
            messageF("iter(%c)[%5.lds]: %5.ld  bound: %.3lf grad: %.7lf  beta: %.7lf\n",(usedSteepest?'s':'o'),(long)timer.getTime(),iteration,bound,squareNorm,valBeta);
         #endif
      }else if(!quiet){
         messageF("\riter(%c): %5.ld  bound: %.3lf grad: %.7lf  beta: %.7lf      ",(usedSteepest?'s':'o'),iteration,bound,squareNorm,valBeta);
      }
#ifdef LOG_CONV
   if((iteration%100==0) ||
      ((iteration<500) && (iteration%50==0)) ||
      ((iteration<150) && (iteration%10==0)) ||
      ((iteration<50) && (iteration%5==0))){
      logF<<iteration<<" "<<bound<<" "<<squareNorm;
      if(logTimer)logF<<" "<<logTimer->current(0,'m');
      #ifdef LONG_LOG
      double alphaSum = 0, alphaVarNorm;
      // True 'alpha' - Dirichlet parameter is alpha+phiHat.
      for(i=1;i<M;i++){
         dirAlpha[i] = alpha[i] + phiHat[i];
         alphaSum += dirAlpha[i];
      }
      for(i=1;i<M;i++)logF<< " " << dirAlpha[i] / alphaSum;
      alphaVarNorm = alphaSum*alphaSum*(alphaSum+1);
      for(i=1;i<M;i++)logF<<" "<<dirAlpha[i]*(alphaSum-dirAlpha[i])/alphaVarNorm;
      #endif
      logF<<endl;
   }
#endif

      // convergence check {{{
      if(bound<boundOld){
         message("\nEnd: bound decrease\n");
         break;
      }
      if(abs(bound-boundOld)<=ftol){
         message("\nEnd: converged (ftol)\n");
         break;
      }
      if(squareNorm<=gtol){
         message("\nEnd: converged (gtol)\n");
         break;
      }
      if(iteration>=maxIter){
         message("\nEnd: maxIter exceeded\n");
         break;
      }
      // }}}
      // store essentials {{{
      squareNormOld=squareNorm;
      boundOld=bound;
      // }}}
      R_INTERUPT;
   }
   if(quiet){
      messageF("iter(%c): %5.ld  bound: %.3lf grad: %.7lf  beta: %.7lf\n",(usedSteepest?'s':'o'),iteration,bound,squareNorm,valBeta);
   }
#ifdef LOG_CONV
   logF<<iteration<<" "<<bound<<" "<<squareNorm;
   if(logTimer)logF<<" "<<logTimer->current(0,'m');
   #ifdef LONG_LOG
   double alphaSum = 0, alphaVarNorm;
   // True 'alpha' - Dirichlet parameter is alpha+phiHat.
   for(i=1;i<M;i++){
      dirAlpha[i] = alpha[i] + phiHat[i];
      alphaSum += dirAlpha[i];
   }
   for(i=1;i<M;i++)logF<< " " << dirAlpha[i] / alphaSum;
   alphaVarNorm = alphaSum*alphaSum*(alphaSum+1);
   for(i=1;i<M;i++)logF<<" "<<dirAlpha[i]*(alphaSum-dirAlpha[i])/alphaVarNorm;
   #endif
   logF<<endl;
   if(logTimer)logTimer->setVerbose();
   logF.close();
#endif
   // free memory {{{
   //delete phiGradPhi;
   delete[] gradPhi;
   delete[] natGrad;
   if(method == OPTT_HS)
      delete[] gradGamma;
   delete[] searchDir;
   //delete[] searchDirOld;
   //delete[] phiGradPhi_sum;
   // }}}
}//}}}