void CCombinedKernel::compute_batch(
	int32_t num_vec, int32_t* vec_idx, float64_t* result, int32_t num_suppvec,
	int32_t* IDX, float64_t* weights, float64_t factor)
{
	ASSERT(num_vec<=get_num_vec_rhs())
	ASSERT(num_vec>0);
	ASSERT(vec_idx);
	ASSERT(result);

	//we have to do the optimization business ourselves but lets
	//make sure we start cleanly
	delete_optimization();

	CListElement* current = NULL ;
	CKernel * k = get_first_kernel(current) ;

	while(k)
	{
		if (k && k->has_property(KP_BATCHEVALUATION))
		{
			if (k->get_combined_kernel_weight()!=0)
				k->compute_batch(num_vec, vec_idx, result, num_suppvec, IDX, weights, k->get_combined_kernel_weight());
		}
		else
			emulate_compute_batch(k, num_vec, vec_idx, result, num_suppvec, IDX, weights);

		SG_UNREF(k);
		k = get_next_kernel(current);
	}

	//clean up
	delete_optimization();
}
void CCombinedKernel::compute_by_subkernel(
	int32_t idx, float64_t * subkernel_contrib)
{
	if (append_subkernel_weights)
	{
		int32_t i=0 ;
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);
		while(k)
		{
			int32_t num = -1 ;
			k->get_subkernel_weights(num);
			if (num>1)
				k->compute_by_subkernel(idx, &subkernel_contrib[i]) ;
			else
				subkernel_contrib[i] += k->get_combined_kernel_weight() * k->compute_optimized(idx) ;

			SG_UNREF(k);
			k = get_next_kernel(current);
			i += num ;
		}
	}
	else
	{
		int32_t i=0 ;
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);
		while(k)
		{
			if (k->get_combined_kernel_weight()!=0)
				subkernel_contrib[i] += k->get_combined_kernel_weight() * k->compute_optimized(idx) ;

			SG_UNREF(k);
			k = get_next_kernel(current);
			i++ ;
		}
	}
}
const float64_t* CCombinedKernel::get_subkernel_weights(int32_t& num_weights)
{
	SG_DEBUG("entering CCombinedKernel::get_subkernel_weights()\n");

	num_weights = get_num_subkernels() ;
	SG_FREE(subkernel_weights_buffer);
	subkernel_weights_buffer = SG_MALLOC(float64_t, num_weights);

	if (append_subkernel_weights)
	{
		SG_DEBUG("appending kernel weights\n");

		int32_t i=0 ;
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);
		while(k)
		{
			int32_t num = -1 ;
			const float64_t *w = k->get_subkernel_weights(num);
			ASSERT(num==k->get_num_subkernels());
			for (int32_t j=0; j<num; j++)
				subkernel_weights_buffer[i+j]=w[j] ;

			SG_UNREF(k);
			k = get_next_kernel(current);
			i += num ;
		}
	}
	else
	{
		SG_DEBUG("not appending kernel weights\n");
		int32_t i=0 ;
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);
		while(k)
		{
			subkernel_weights_buffer[i] = k->get_combined_kernel_weight();

			SG_UNREF(k);
			k = get_next_kernel(current);
			i++ ;
		}
	}

	SG_DEBUG("leaving CCombinedKernel::get_subkernel_weights()\n");
	return subkernel_weights_buffer ;
}
SGMatrix<float64_t> CCombinedKernel::get_parameter_gradient(TParameter* param,
		CSGObject* obj, index_t index)
{
	SGMatrix<float64_t> result(0,0);

	if (strcmp(param->m_name, "combined_kernel_weight") == 0)
	{
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);

		if (append_subkernel_weights)
		{
			while(k)
			{
				result = k->get_parameter_gradient(param, obj, index);

				SG_UNREF(k);

				if (result.num_cols*result.num_rows > 0)
					return result;

				k = get_next_kernel(current);
			}
		}

		else
		{
			while(k)
			{
				if(obj == k)
				{
					result = k->get_kernel_matrix();
					SG_UNREF(k);
					return result;
				}

				SG_UNREF(k);

				k = get_next_kernel(current);
			}
		}
	}

	else
	{
		CListElement* current = NULL ;
		CKernel* k = get_first_kernel(current);
		float64_t coeff;
		while(k)
		{
			SGMatrix<float64_t> derivative =
					k->get_parameter_gradient(param, obj, index);

			coeff = 1.0;

			if (!append_subkernel_weights)
				coeff = k->get_combined_kernel_weight();


			for (index_t g = 0; g < derivative.num_rows; g++)
			{
				for (index_t h = 0; h < derivative.num_cols; h++)
					derivative(g,h) *= coeff;
			}

			if (derivative.num_cols*derivative.num_rows > 0)
			{
				if (result.num_cols == 0 && result.num_rows == 0)
					result = derivative;

				else
				{
					for (index_t g = 0; g < derivative.num_rows; g++)
					{
						for (index_t h = 0; h < derivative.num_cols; h++)
							result(g,h) += derivative(g,h);
					}
				}
			}

			SG_UNREF(k);
			k = get_next_kernel(current);
		}
	}

	return result;
}