double GillespieIntegrator::integrate(double t, double hstep)
{
    double tf = 0;
    bool singleStep;

    assert(hstep > 0 && "hstep must be > 0");

    if (options.integratorFlags & VARIABLE_STEP)
    {
        if (options.minimumTimeStep > 0.0)
        {
            tf = t + options.minimumTimeStep;
            singleStep = false;
        }
        else
        {
            tf = t + hstep;
            singleStep = true;
        }
    }
    else
    {
        tf = t + hstep;
        singleStep = false;
    }

    Log(Logger::LOG_DEBUG) << "ssa(" << t << ", " << tf << ")";

    // get the initial state vector
    model->setTime(t);
    model->getStateVector(stateVector);

    while (t < tf)
    {
        // random uniform numbers
        double r1 = urand();
        double r2 = urand();

        assert(r1 > 0 && r1 <= 1 && r2 >= 0 && r2 <= 1);

        // sum of propensities
        double s = 0;

        // next time
        double tau = 0;

        // get the 'propensity' -- reaction rates
        model->getReactionRates(nReactions, 0, reactionRates);

        // sum the propensity
        for (int k = 0; k < nReactions; k++)
        {
            Log(Logger::LOG_DEBUG) << "reac rate: " << k << ": "
                    << reactionRates[k];

            // if reaction rate is negative, that means reaction goes in reverse,
            // this is fine, we just have to reverse the stoichiometry,
            // but still need to sum the absolute value of the propensities
            // to get tau.
            s += std::abs(reactionRates[k]);
        }

        // sample tau
        if (s > 0)
        {
            tau = -log(r1) / s;
        }
        else
        {
            // no reaction occurs
            return std::numeric_limits<double>::infinity();
        }

        t = t + tau;

        // select reaction
        int reaction = -1;
        double sp = 0.0;

        r2 = r2 * s;
        for (int i = 0; i < nReactions; ++i)
        {
            sp += std::abs(reactionRates[i]);
            if (r2 < sp)
            {
                reaction = i;
                break;
            }
        }

        assert(reaction >= 0 && reaction < nReactions);

        // update chemical species
        // if rate is negative, means reaction goes in reverse, so
        // multiply by sign
        double sign = (reactionRates[reaction] > 0)
                - (reactionRates[reaction] < 0);


        for (int i = floatingSpeciesStart; i < stateVectorSize; ++i)
        {
            stateVector[i] = stateVector[i]
                    + getStoich(i - floatingSpeciesStart, reaction)
                            * stoichScale * sign;

            if(stateVector[i] < 0.0) {
            	Log(Logger::LOG_WARNING) << "Error, negative value of "
            	   << stateVector[i]
				   << " encountred for floating species "
				   << model->getFloatingSpeciesId(i - floatingSpeciesStart);
            	t = std::numeric_limits<double>::infinity();
            }
        }

        // rates could be time dependent
        model->setTime(t);
        model->setStateVector(stateVector);

        if (singleStep)
        {
            return t;
        }
    }

    return t;
}
	double GillespieIntegrator::integrate(double t, double hstep)
	{
		double tf = 0;
		bool singleStep;

		assert(hstep > 0 && "hstep must be > 0");

		if (getValue("variable_step_size").convert<bool>())
		{
			if (getValue("minimum_time_step").convert<double>() > 0.0)
			{
				tf = t + getValue("minimum_time_step").convert<double>();
				singleStep = false;
			}
			else
			{
				tf = t + hstep;
				singleStep = true;
			}
		}
		else
		{
			tf = t + hstep;
			singleStep = false;
		}

		Log(Logger::LOG_DEBUG) << "ssa(" << t << ", " << tf << ")";

		// get the initial state vector
		model->setTime(t);
		model->getStateVector(stateVector);

		while (t < tf)
		{
			// random uniform numbers
			double r1 = urand();
			double r2 = urand();

			assert(r1 > 0 && r1 <= 1 && r2 >= 0 && r2 <= 1);

			// sum of propensities
			double s = 0;

			// next time
			double tau = 0;

			// get the 'propensity' -- reaction rates
			model->getReactionRates(nReactions, 0, reactionRates);

			// sum the propensity
			for (int k = 0; k < nReactions; k++)
			{
				Log(Logger::LOG_DEBUG) << "reac rate: " << k << ": "
					<< reactionRates[k];

				// if reaction rate is negative, that means reaction goes in reverse,
				// this is fine, we just have to reverse the stoichiometry,
				// but still need to sum the absolute value of the propensities
				// to get tau.
				s += std::abs(reactionRates[k]);
			}

			// sample tau
			if (s > 0)
			{
				tau = -log(r1) / s;
			}
			else
			{
				// no reaction occurs
				return std::numeric_limits<double>::infinity();
			}

			t = t + tau;

			// select reaction
			int reaction = -1;
			double sp = 0.0;

			r2 = r2 * s;
			for (int i = 0; i < nReactions; ++i)
			{
				sp += std::abs(reactionRates[i]);
				if (r2 < sp)
				{
					reaction = i;
					break;
				}
			}

			assert(reaction >= 0 && reaction < nReactions);

			// update chemical species
			// if rate is negative, means reaction goes in reverse, so
			// multiply by sign
			double sign = (reactionRates[reaction] > 0)
				- (reactionRates[reaction] < 0);

			bool skip = false;

			if (getValueAsBool("nonnegative")) {
				// skip reactions which cause species amts to become negative
				for (int i = floatingSpeciesStart; i < stateVectorSize; ++i) {
					if (stateVector[i]
						+ getStoich(i - floatingSpeciesStart, reaction)
						* stoichScale * sign < 0.0) {
							skip = true;
							break;
						}
				}
			}

			if (!skip) {
				for (int i = floatingSpeciesStart; i < stateVectorSize; ++i)
				{
					stateVector[i] = stateVector[i]
						+ getStoich(i - floatingSpeciesStart, reaction)
						* stoichScale * sign;

					if (stateVector[i] < 0.0) {
						Log(Logger::LOG_WARNING) << "Error, negative value of "
							<< stateVector[i]
							<< " encountred for floating species "
							<< model->getFloatingSpeciesId(i - floatingSpeciesStart);
						t = std::numeric_limits<double>::infinity();
					}
				}
			}

			// rates could be time dependent
			model->setTime(t);
			model->setStateVector(stateVector);

      // events
      bool triggered = false;

      model->getEventTriggers(eventStatus.size(), NULL, eventStatus.size() ? &eventStatus[0] : NULL);
      for(int k_=0; k_<eventStatus.size(); ++k_) {
        if (eventStatus.at(k_))
          triggered = true;
      }

      if (triggered) {
        applyEvents(t, previousEventStatus);
      }

      if (eventStatus.size())
        memcpy(&previousEventStatus[0], &eventStatus[0], eventStatus.size()*sizeof(unsigned char));


			if (singleStep)
			{
				return t;
			}
		}

		return t;
	}