<commit_before>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_config.h"
#include "string_list.h"

#include "ec2resource.h"
#include "gridmanager.h"

#define HASH_TABLE_SIZE	500

HashTable <HashKey, EC2Resource *>
	EC2Resource::ResourcesByName( HASH_TABLE_SIZE, hashFunction );

const char * EC2Resource::HashName( const char * resource_name,
		const char * public_key_file, const char * private_key_file )
{
	static std::string hash_name;
	formatstr( hash_name, "ec2 %s#%s#%s", resource_name, public_key_file, private_key_file );
	return hash_name.c_str();
}

EC2Resource* EC2Resource::FindOrCreateResource(const char * resource_name,
	const char * public_key_file, const char * private_key_file )
{
	int rc;
	EC2Resource *resource = NULL;

	rc = ResourcesByName.lookup( HashKey( HashName( resource_name, public_key_file, private_key_file ) ), resource );
	if ( rc != 0 ) {
		resource = new EC2Resource( resource_name, public_key_file, private_key_file );
		ASSERT(resource);
		resource->Reconfig();
		ResourcesByName.insert( HashKey( HashName( resource_name, public_key_file, private_key_file ) ), resource );
	} else {
		ASSERT(resource);
	}

	return resource;
}

EC2Resource::EC2Resource( const char *resource_name,
	const char * public_key_file, const char * private_key_file ) :
		BaseResource( resource_name ),
		jobsByInstanceID( hashFunction ),
		spotJobsByRequestID( hashFunction ),
		m_hadAuthFailure( false ),
		m_checkSpotNext( false )
{
	// although no one will use resource_name, we still keep it for base class constructor

	m_public_key_file = strdup(public_key_file);
	m_private_key_file = strdup(private_key_file);

	gahp = NULL;

	char * gahp_path = param( "EC2_GAHP" );
	if ( gahp_path == NULL ) {
		dprintf(D_ALWAYS, "EC2_GAHP not defined! \n");
		return;
	}

	ArgList args;
	args.AppendArg("-f");

	gahp = new GahpClient( EC2_RESOURCE_NAME, gahp_path, &args );
	gahp->setNotificationTimerId( pingTimerId );
	gahp->setMode( GahpClient::normal );
	gahp->setTimeout( EC2Job::gahpCallTimeout );

	status_gahp = new GahpClient( EC2_RESOURCE_NAME, gahp_path, &args );

	StartBatchStatusTimer();

    status_gahp->setNotificationTimerId( BatchPollTid() );
	status_gahp->setMode( GahpClient::normal );
	status_gahp->setTimeout( EC2Job::gahpCallTimeout );

	free(gahp_path);
}

EC2Resource::~EC2Resource()
{
	ResourcesByName.remove( HashKey( HashName( resourceName, m_public_key_file,
											   m_private_key_file ) ) );
	if ( gahp ) delete gahp;
	if (m_public_key_file) free(m_public_key_file);
	if (m_private_key_file) free(m_private_key_file);
}

void EC2Resource::Reconfig()
{
	BaseResource::Reconfig();
	gahp->setTimeout( EC2Job::gahpCallTimeout );
}

const char *EC2Resource::ResourceType()
{
	return "ec2";
}

const char *EC2Resource::GetHashName()
{
	return HashName( resourceName, m_public_key_file, m_private_key_file );
}

void EC2Resource::PublishResourceAd( ClassAd *resource_ad )
{
	BaseResource::PublishResourceAd( resource_ad );

	resource_ad->Assign( ATTR_EC2_ACCESS_KEY_ID, m_public_key_file );
	resource_ad->Assign( ATTR_EC2_SECRET_ACCESS_KEY, m_private_key_file );
}

// we will use ec2 command "status_all" to do the Ping work
void EC2Resource::DoPing( time_t& ping_delay, bool& ping_complete, bool& ping_succeeded )
{
	// Since EC2 doesn't use proxy, we should use Startup() to replace isInitialized()
	if ( gahp->isStarted() == false ) {
		dprintf( D_ALWAYS,"gahp server not up yet, delaying ping\n" );
		ping_delay = 5;
		return;
	}

	ping_delay = 0;

	std::string error_code;
	int rc = gahp->ec2_vm_server_type( resourceName, m_public_key_file, m_private_key_file, m_serverType, error_code );

	if ( rc == GAHPCLIENT_COMMAND_PENDING ) {
		ping_complete = false;
	}
	else if ( rc != 0 ) {
		ping_complete = true;

		// If the service returns an authorization failure, that means
		// the service is up, so return true.  Individual jobs with
		// invalid authentication tokens will then go on hold, which is
		// what we want (rather than saying idle).
		if( error_code != "" ) {
			if( strstr( error_code.c_str(), "(401)" ) != NULL ) {
				ping_succeeded = true;
				m_hadAuthFailure = true;
				formatstr( authFailureMessage, "(%s): '%s'", error_code.c_str(), gahp->getErrorString() );
			}
		} else {
		    ping_succeeded = false;
		}
	}
	else {
		ping_complete = true;
		ping_succeeded = true;
	}

	return;
}

EC2Resource::BatchStatusResult EC2Resource::StartBatchStatus() {
    ASSERT( status_gahp );

    // m_checkSpotNext starts out false
    if( ! m_checkSpotNext ) {
        StringList returnStatus;
        std::string errorCode;
        int rc = status_gahp->ec2_vm_status_all( resourceName,
                    m_public_key_file, m_private_key_file,
                    returnStatus, errorCode );

        if( rc == GAHPCLIENT_COMMAND_PENDING ) { return BSR_PENDING; }

        if( rc != 0 ) {
            std::string errorString = status_gahp->getErrorString();
            dprintf( D_ALWAYS, "Error doing batched EC2 status query: %s: %s.\n",
                     errorCode.c_str(), errorString.c_str() );
            return BSR_ERROR;
        }

        //
        // We have to let a job know if we can't find a status report for it.
        //
        List<EC2Job> myJobs;
        EC2Job * nextJob = NULL;
		BaseJob *nextBaseJob = NULL;
		registeredJobs.Rewind();
		while ( (nextBaseJob = registeredJobs.Next()) ) {
			nextJob = dynamic_cast< EC2Job * >( nextBaseJob );
			ASSERT( nextJob );
			if ( !nextJob->m_client_token.empty() ) {
				myJobs.Append( nextJob );
			}
		}

        returnStatus.rewind();
        ASSERT( returnStatus.number() % 6 == 0 );
        for( int i = 0; i < returnStatus.number(); i += 6 ) {
            std::string instanceID = returnStatus.next();
            std::string status = returnStatus.next();
            std::string clientToken = returnStatus.next();
            std::string keyName = returnStatus.next();
            std::string stateReasonCode = returnStatus.next();
            std::string publicDNSName = returnStatus.next();

            // Efficiency suggests we look via the instance ID first,
            // and then try to look things up via the client token
            // (or, for GT #3682, via the keypair ID).

            // We can't use BaseJob::JobsByRemoteId because OpenStack doesn't
            // include the client token in its status responses, and therefore
            // we can't always fully reconstruct the remoteJobID used as the key.
            EC2Job * job = NULL;
            rc = jobsByInstanceID.lookup( HashKey( instanceID.c_str() ), job );
            if( rc == 0 ) {
                ASSERT( job );

                dprintf( D_FULLDEBUG, "Found job object for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
                job->StatusUpdate( instanceID.c_str(), status.c_str(),
                                   stateReasonCode.c_str(), publicDNSName.c_str() );
                myJobs.Delete( job );
                continue;
            }

            // If we got a client token, use that to look up the job.  We
            // don't use the instance ID because we may discover it in
            // this function.  Since we need instance ID -based dispatch
            // code for OpenStack anyway, we'll just use it, rather than
            // trying the remoteJobID with the instance ID if we don't
            // find it using only the client token.
            if( ! clientToken.empty() && clientToken != "NULL" ) {
                std::string remoteJobID;
                formatstr( remoteJobID, "ec2 %s %s", resourceName, clientToken.c_str() );

                BaseJob * tmp = NULL;
                rc = BaseJob::JobsByRemoteId.lookup( HashKey( remoteJobID.c_str() ), tmp );

                if( rc == 0 ) {
                    ASSERT( tmp );
                    EC2Job * job = dynamic_cast< EC2Job * >( tmp );
                    if( job == NULL ) {
                        EXCEPT( "Found non-EC2Job identified by '%s'.", remoteJobID.c_str() );
                    }

                    dprintf( D_FULLDEBUG, "Found job object via client token for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
                    job->StatusUpdate( instanceID.c_str(), status.c_str(),
                                       stateReasonCode.c_str(), publicDNSName.c_str() );
                    myJobs.Delete( job );
                    continue;
                }
            }

			// Some servers (OpenStack, Eucalyptus) silently ignore client
			// tokens. So we need to use the ssh keypair to find jobs that
			// were submitted but which we don't have an instance ID for.
			if ( !ClientTokenWorks() && !keyName.empty() && keyName != "NULL" ) {
				myJobs.Rewind();
				while ( ( job = myJobs.Next() ) ) {
					if ( job->m_key_pair == keyName ) {
						dprintf( D_FULLDEBUG, "Found job object via ssh keypair for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
						job->StatusUpdate( instanceID.c_str(), status.c_str(),
										   stateReasonCode.c_str(),
										   publicDNSName.c_str() );
						myJobs.Delete( job );
						continue;
					}
				}
			}

            dprintf( D_FULLDEBUG, "Found unknown instance '%s'; skipping.\n", instanceID.c_str() );
            continue;
        }

        myJobs.Rewind();
        while( ( nextJob = myJobs.Next() ) ) {
            dprintf( D_FULLDEBUG, "Informing job %p it got no status.\n", nextJob );
            nextJob->StatusUpdate( NULL, NULL, NULL, NULL );
        }

        // Don't ask for spot results unless we know about a spot job.  This
        // should prevent us from breaking OpenStack.
        if( spotJobsByRequestID.getNumElements() == 0 ) {
            m_checkSpotNext = false;
            return BSR_DONE;
        } else {
            m_checkSpotNext = true;
        }
    }

    if( m_checkSpotNext ) {
        StringList spotReturnStatus;
        std::string spotErrorCode;
        int spotRC = status_gahp->ec2_spot_status_all( resourceName,
                        m_public_key_file, m_private_key_file,
                        spotReturnStatus, spotErrorCode );

        if( spotRC == GAHPCLIENT_COMMAND_PENDING ) { return BSR_PENDING; }

        if( spotRC != 0 ) {
            std::string errorString = status_gahp->getErrorString();
            dprintf( D_ALWAYS, "Error doing batched EC2 spot status query: %s: %s.\n",
                     spotErrorCode.c_str(), errorString.c_str() );
            return BSR_ERROR;
        }

        List<EC2Job> mySpotJobs;
        EC2Job * nextSpotJob = NULL;
        spotJobsByRequestID.startIterations();
        while( spotJobsByRequestID.iterate( nextSpotJob ) ) {
            mySpotJobs.Append( nextSpotJob );
        }

        spotReturnStatus.rewind();
        ASSERT( spotReturnStatus.number() % 5 == 0 );
        for( int i = 0; i < spotReturnStatus.number(); i += 5 ) {
            std::string requestID = spotReturnStatus.next();
            std::string state = spotReturnStatus.next();
            /* std::string launchGroup = */ spotReturnStatus.next();
            /* std::string instanceID = */ spotReturnStatus.next();
            std::string statusCode = spotReturnStatus.next();

            EC2Job * spotJob = NULL;
            spotRC = spotJobsByRequestID.lookup( HashKey( requestID.c_str() ), spotJob );
            if( spotRC != 0 ) {
                dprintf( D_FULLDEBUG, "Found unknown spot request '%s'; skipping.\n", requestID.c_str() );
                continue;
            }
            ASSERT( spotJob );

            if( ! statusCode.empty() ) { state = statusCode; }

            dprintf( D_FULLDEBUG, "Found spot job object for '%s', updating status ('%s').\n", requestID.c_str(), state.c_str() );
            spotJob->StatusUpdate( NULL, state.c_str(), NULL, NULL );
            mySpotJobs.Delete( spotJob );
        }

        mySpotJobs.Rewind();
        while( ( nextSpotJob = mySpotJobs.Next() ) ) {
            dprintf( D_FULLDEBUG, "Informing spot job %p it got no status.\n", nextSpotJob );
            nextSpotJob->StatusUpdate( NULL, NULL, NULL, NULL );
        }

        m_checkSpotNext = false;
        return BSR_DONE;
    }

    // This should never happen (but the compiler hates you).
    return BSR_ERROR;
}

EC2Resource::BatchStatusResult EC2Resource::FinishBatchStatus() {
    return StartBatchStatus();
}

bool EC2Resource::ServerTypeQueried( EC2Job *job ) {
	if ( !m_serverType.empty() ) {
		return true;
	}
	std::string type;
	if ( job && job->jobAd->LookupString( ATTR_EC2_SERVER_TYPE, type ) ) {
		return true;
	}
	return false;
}

bool EC2Resource::ClientTokenWorks( EC2Job *job )
{
	if ( m_serverType == "Amazon" || m_serverType == "Nimbus" ) {
		return true;
	}
	std::string type;
	if ( m_serverType.empty() && job &&
		 job->jobAd->LookupString( ATTR_EC2_SERVER_TYPE, type ) ) {
		if ( type == "Amazon" || type == "Nimbus" ) {
			return true;
		}
	}
	return false;
}
<commit_msg>Add comment about how to improve EC2 ssh keypair name search. #3682<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * 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 "condor_common.h"
#include "condor_config.h"
#include "string_list.h"

#include "ec2resource.h"
#include "gridmanager.h"

#define HASH_TABLE_SIZE	500

HashTable <HashKey, EC2Resource *>
	EC2Resource::ResourcesByName( HASH_TABLE_SIZE, hashFunction );

const char * EC2Resource::HashName( const char * resource_name,
		const char * public_key_file, const char * private_key_file )
{
	static std::string hash_name;
	formatstr( hash_name, "ec2 %s#%s#%s", resource_name, public_key_file, private_key_file );
	return hash_name.c_str();
}

EC2Resource* EC2Resource::FindOrCreateResource(const char * resource_name,
	const char * public_key_file, const char * private_key_file )
{
	int rc;
	EC2Resource *resource = NULL;

	rc = ResourcesByName.lookup( HashKey( HashName( resource_name, public_key_file, private_key_file ) ), resource );
	if ( rc != 0 ) {
		resource = new EC2Resource( resource_name, public_key_file, private_key_file );
		ASSERT(resource);
		resource->Reconfig();
		ResourcesByName.insert( HashKey( HashName( resource_name, public_key_file, private_key_file ) ), resource );
	} else {
		ASSERT(resource);
	}

	return resource;
}

EC2Resource::EC2Resource( const char *resource_name,
	const char * public_key_file, const char * private_key_file ) :
		BaseResource( resource_name ),
		jobsByInstanceID( hashFunction ),
		spotJobsByRequestID( hashFunction ),
		m_hadAuthFailure( false ),
		m_checkSpotNext( false )
{
	// although no one will use resource_name, we still keep it for base class constructor

	m_public_key_file = strdup(public_key_file);
	m_private_key_file = strdup(private_key_file);

	gahp = NULL;

	char * gahp_path = param( "EC2_GAHP" );
	if ( gahp_path == NULL ) {
		dprintf(D_ALWAYS, "EC2_GAHP not defined! \n");
		return;
	}

	ArgList args;
	args.AppendArg("-f");

	gahp = new GahpClient( EC2_RESOURCE_NAME, gahp_path, &args );
	gahp->setNotificationTimerId( pingTimerId );
	gahp->setMode( GahpClient::normal );
	gahp->setTimeout( EC2Job::gahpCallTimeout );

	status_gahp = new GahpClient( EC2_RESOURCE_NAME, gahp_path, &args );

	StartBatchStatusTimer();

    status_gahp->setNotificationTimerId( BatchPollTid() );
	status_gahp->setMode( GahpClient::normal );
	status_gahp->setTimeout( EC2Job::gahpCallTimeout );

	free(gahp_path);
}

EC2Resource::~EC2Resource()
{
	ResourcesByName.remove( HashKey( HashName( resourceName, m_public_key_file,
											   m_private_key_file ) ) );
	if ( gahp ) delete gahp;
	if (m_public_key_file) free(m_public_key_file);
	if (m_private_key_file) free(m_private_key_file);
}

void EC2Resource::Reconfig()
{
	BaseResource::Reconfig();
	gahp->setTimeout( EC2Job::gahpCallTimeout );
}

const char *EC2Resource::ResourceType()
{
	return "ec2";
}

const char *EC2Resource::GetHashName()
{
	return HashName( resourceName, m_public_key_file, m_private_key_file );
}

void EC2Resource::PublishResourceAd( ClassAd *resource_ad )
{
	BaseResource::PublishResourceAd( resource_ad );

	resource_ad->Assign( ATTR_EC2_ACCESS_KEY_ID, m_public_key_file );
	resource_ad->Assign( ATTR_EC2_SECRET_ACCESS_KEY, m_private_key_file );
}

// we will use ec2 command "status_all" to do the Ping work
void EC2Resource::DoPing( time_t& ping_delay, bool& ping_complete, bool& ping_succeeded )
{
	// Since EC2 doesn't use proxy, we should use Startup() to replace isInitialized()
	if ( gahp->isStarted() == false ) {
		dprintf( D_ALWAYS,"gahp server not up yet, delaying ping\n" );
		ping_delay = 5;
		return;
	}

	ping_delay = 0;

	std::string error_code;
	int rc = gahp->ec2_vm_server_type( resourceName, m_public_key_file, m_private_key_file, m_serverType, error_code );

	if ( rc == GAHPCLIENT_COMMAND_PENDING ) {
		ping_complete = false;
	}
	else if ( rc != 0 ) {
		ping_complete = true;

		// If the service returns an authorization failure, that means
		// the service is up, so return true.  Individual jobs with
		// invalid authentication tokens will then go on hold, which is
		// what we want (rather than saying idle).
		if( error_code != "" ) {
			if( strstr( error_code.c_str(), "(401)" ) != NULL ) {
				ping_succeeded = true;
				m_hadAuthFailure = true;
				formatstr( authFailureMessage, "(%s): '%s'", error_code.c_str(), gahp->getErrorString() );
			}
		} else {
		    ping_succeeded = false;
		}
	}
	else {
		ping_complete = true;
		ping_succeeded = true;
	}

	return;
}

EC2Resource::BatchStatusResult EC2Resource::StartBatchStatus() {
    ASSERT( status_gahp );

    // m_checkSpotNext starts out false
    if( ! m_checkSpotNext ) {
        StringList returnStatus;
        std::string errorCode;
        int rc = status_gahp->ec2_vm_status_all( resourceName,
                    m_public_key_file, m_private_key_file,
                    returnStatus, errorCode );

        if( rc == GAHPCLIENT_COMMAND_PENDING ) { return BSR_PENDING; }

        if( rc != 0 ) {
            std::string errorString = status_gahp->getErrorString();
            dprintf( D_ALWAYS, "Error doing batched EC2 status query: %s: %s.\n",
                     errorCode.c_str(), errorString.c_str() );
            return BSR_ERROR;
        }

        //
        // We have to let a job know if we can't find a status report for it.
        //
        List<EC2Job> myJobs;
        EC2Job * nextJob = NULL;
		BaseJob *nextBaseJob = NULL;
		registeredJobs.Rewind();
		while ( (nextBaseJob = registeredJobs.Next()) ) {
			nextJob = dynamic_cast< EC2Job * >( nextBaseJob );
			ASSERT( nextJob );
			if ( !nextJob->m_client_token.empty() ) {
				myJobs.Append( nextJob );
			}
		}

        returnStatus.rewind();
        ASSERT( returnStatus.number() % 6 == 0 );
        for( int i = 0; i < returnStatus.number(); i += 6 ) {
            std::string instanceID = returnStatus.next();
            std::string status = returnStatus.next();
            std::string clientToken = returnStatus.next();
            std::string keyName = returnStatus.next();
            std::string stateReasonCode = returnStatus.next();
            std::string publicDNSName = returnStatus.next();

            // Efficiency suggests we look via the instance ID first,
            // and then try to look things up via the client token
            // (or, for GT #3682, via the keypair ID).

            // We can't use BaseJob::JobsByRemoteId because OpenStack doesn't
            // include the client token in its status responses, and therefore
            // we can't always fully reconstruct the remoteJobID used as the key.
            EC2Job * job = NULL;
            rc = jobsByInstanceID.lookup( HashKey( instanceID.c_str() ), job );
            if( rc == 0 ) {
                ASSERT( job );

                dprintf( D_FULLDEBUG, "Found job object for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
                job->StatusUpdate( instanceID.c_str(), status.c_str(),
                                   stateReasonCode.c_str(), publicDNSName.c_str() );
                myJobs.Delete( job );
                continue;
            }

            // If we got a client token, use that to look up the job.  We
            // don't use the instance ID because we may discover it in
            // this function.  Since we need instance ID -based dispatch
            // code for OpenStack anyway, we'll just use it, rather than
            // trying the remoteJobID with the instance ID if we don't
            // find it using only the client token.
            if( ! clientToken.empty() && clientToken != "NULL" ) {
                std::string remoteJobID;
                formatstr( remoteJobID, "ec2 %s %s", resourceName, clientToken.c_str() );

                BaseJob * tmp = NULL;
                rc = BaseJob::JobsByRemoteId.lookup( HashKey( remoteJobID.c_str() ), tmp );

                if( rc == 0 ) {
                    ASSERT( tmp );
                    EC2Job * job = dynamic_cast< EC2Job * >( tmp );
                    if( job == NULL ) {
                        EXCEPT( "Found non-EC2Job identified by '%s'.", remoteJobID.c_str() );
                    }

                    dprintf( D_FULLDEBUG, "Found job object via client token for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
                    job->StatusUpdate( instanceID.c_str(), status.c_str(),
                                       stateReasonCode.c_str(), publicDNSName.c_str() );
                    myJobs.Delete( job );
                    continue;
                }
            }

			// Some servers (OpenStack, Eucalyptus) silently ignore client
			// tokens. So we need to use the ssh keypair to find jobs that
			// were submitted but which we don't have an instance ID for.
			//
			// TODO This code should be made more efficient. We can
			//   do something better than a linear scan through all
			//   jobs for each status result. Ideally, we'd parse the
			//   ssh keypair name and if it looks like one we generated,
			//   pluck out the job id.
			if ( !ClientTokenWorks() && !keyName.empty() && keyName != "NULL" ) {
				myJobs.Rewind();
				while ( ( job = myJobs.Next() ) ) {
					if ( job->m_key_pair == keyName ) {
						dprintf( D_FULLDEBUG, "Found job object via ssh keypair for '%s', updating status ('%s').\n", instanceID.c_str(), status.c_str() );
						job->StatusUpdate( instanceID.c_str(), status.c_str(),
										   stateReasonCode.c_str(),
										   publicDNSName.c_str() );
						myJobs.Delete( job );
						continue;
					}
				}
			}

            dprintf( D_FULLDEBUG, "Found unknown instance '%s'; skipping.\n", instanceID.c_str() );
            continue;
        }

        myJobs.Rewind();
        while( ( nextJob = myJobs.Next() ) ) {
            dprintf( D_FULLDEBUG, "Informing job %p it got no status.\n", nextJob );
            nextJob->StatusUpdate( NULL, NULL, NULL, NULL );
        }

        // Don't ask for spot results unless we know about a spot job.  This
        // should prevent us from breaking OpenStack.
        if( spotJobsByRequestID.getNumElements() == 0 ) {
            m_checkSpotNext = false;
            return BSR_DONE;
        } else {
            m_checkSpotNext = true;
        }
    }

    if( m_checkSpotNext ) {
        StringList spotReturnStatus;
        std::string spotErrorCode;
        int spotRC = status_gahp->ec2_spot_status_all( resourceName,
                        m_public_key_file, m_private_key_file,
                        spotReturnStatus, spotErrorCode );

        if( spotRC == GAHPCLIENT_COMMAND_PENDING ) { return BSR_PENDING; }

        if( spotRC != 0 ) {
            std::string errorString = status_gahp->getErrorString();
            dprintf( D_ALWAYS, "Error doing batched EC2 spot status query: %s: %s.\n",
                     spotErrorCode.c_str(), errorString.c_str() );
            return BSR_ERROR;
        }

        List<EC2Job> mySpotJobs;
        EC2Job * nextSpotJob = NULL;
        spotJobsByRequestID.startIterations();
        while( spotJobsByRequestID.iterate( nextSpotJob ) ) {
            mySpotJobs.Append( nextSpotJob );
        }

        spotReturnStatus.rewind();
        ASSERT( spotReturnStatus.number() % 5 == 0 );
        for( int i = 0; i < spotReturnStatus.number(); i += 5 ) {
            std::string requestID = spotReturnStatus.next();
            std::string state = spotReturnStatus.next();
            /* std::string launchGroup = */ spotReturnStatus.next();
            /* std::string instanceID = */ spotReturnStatus.next();
            std::string statusCode = spotReturnStatus.next();

            EC2Job * spotJob = NULL;
            spotRC = spotJobsByRequestID.lookup( HashKey( requestID.c_str() ), spotJob );
            if( spotRC != 0 ) {
                dprintf( D_FULLDEBUG, "Found unknown spot request '%s'; skipping.\n", requestID.c_str() );
                continue;
            }
            ASSERT( spotJob );

            if( ! statusCode.empty() ) { state = statusCode; }

            dprintf( D_FULLDEBUG, "Found spot job object for '%s', updating status ('%s').\n", requestID.c_str(), state.c_str() );
            spotJob->StatusUpdate( NULL, state.c_str(), NULL, NULL );
            mySpotJobs.Delete( spotJob );
        }

        mySpotJobs.Rewind();
        while( ( nextSpotJob = mySpotJobs.Next() ) ) {
            dprintf( D_FULLDEBUG, "Informing spot job %p it got no status.\n", nextSpotJob );
            nextSpotJob->StatusUpdate( NULL, NULL, NULL, NULL );
        }

        m_checkSpotNext = false;
        return BSR_DONE;
    }

    // This should never happen (but the compiler hates you).
    return BSR_ERROR;
}

EC2Resource::BatchStatusResult EC2Resource::FinishBatchStatus() {
    return StartBatchStatus();
}

bool EC2Resource::ServerTypeQueried( EC2Job *job ) {
	if ( !m_serverType.empty() ) {
		return true;
	}
	std::string type;
	if ( job && job->jobAd->LookupString( ATTR_EC2_SERVER_TYPE, type ) ) {
		return true;
	}
	return false;
}

bool EC2Resource::ClientTokenWorks( EC2Job *job )
{
	if ( m_serverType == "Amazon" || m_serverType == "Nimbus" ) {
		return true;
	}
	std::string type;
	if ( m_serverType.empty() && job &&
		 job->jobAd->LookupString( ATTR_EC2_SERVER_TYPE, type ) ) {
		if ( type == "Amazon" || type == "Nimbus" ) {
			return true;
		}
	}
	return false;
}
<|endoftext|>


<commit_before>#include <cstring>

#include "zlib.h"
#include "MathUtils.h"
#include "ZipCompressor.h"

namespace crown
{

ZipCompressor::ZipCompressor(Allocator& allocator) :
	Compressor(allocator)
{

}

ZipCompressor::~ZipCompressor()
{

}

uint8_t* ZipCompressor::compress(const void* data, size_t in_size, size_t& out_size)
{
	out_size = in_size + in_size * 0.1f + 12;

 	uint8_t* dest = (uint8_t*)m_allocator->allocate(out_size);

	int32_t ret = ::compress((Bytef*)dest, (uLongf*)&out_size, (const Bytef*)data, (uLongf)in_size);

	assert(ret == Z_OK);

	return dest;
}

uint8_t* ZipCompressor::uncompress(const void* data, size_t in_size, size_t& out_size)
{
	out_size = in_size + in_size * 0.1f + 12;

 	uint8_t* dest = (uint8_t*)m_allocator->allocate(out_size);

	int32_t ret = ::uncompress((Bytef*)dest, (uLongf*)&out_size, (const Bytef*)data, (uLongf)in_size);

	assert(ret == Z_OK);

	return dest;
}

} // namespace crown

<commit_msg>Remove unused header<commit_after>#include <cstring>

#include "zlib.h"
#include "ZipCompressor.h"

namespace crown
{

ZipCompressor::ZipCompressor(Allocator& allocator) :
	Compressor(allocator)
{

}

ZipCompressor::~ZipCompressor()
{

}

uint8_t* ZipCompressor::compress(const void* data, size_t in_size, size_t& out_size)
{
	out_size = in_size + in_size * 0.1f + 12;

 	uint8_t* dest = (uint8_t*)m_allocator->allocate(out_size);

	int32_t ret = ::compress((Bytef*)dest, (uLongf*)&out_size, (const Bytef*)data, (uLongf)in_size);

	assert(ret == Z_OK);

	return dest;
}

uint8_t* ZipCompressor::uncompress(const void* data, size_t in_size, size_t& out_size)
{
	out_size = in_size + in_size * 0.1f + 12;

 	uint8_t* dest = (uint8_t*)m_allocator->allocate(out_size);

	int32_t ret = ::uncompress((Bytef*)dest, (uLongf*)&out_size, (const Bytef*)data, (uLongf)in_size);

	assert(ret == Z_OK);

	return dest;
}

} // namespace crown

<|endoftext|>


<commit_before>#include "NumHeldDownKeys.hpp"
#include "Config.hpp"
#include "RemapUtil.hpp"

namespace org_pqrs_KeyRemap4MacBook {
  namespace NumHeldDownKeys {
    int num = 0;

    static void
    log_(void)
    {
      if (config.debug_devel) {
        printf("KeyRemap4MacBook NumHeldDownKeys = %d\n", num);
      }
    }

    void
    set(const RemapParams &remapParams)
    {
      if (RemapUtil::isKeyDown(remapParams, (remapParams.params)->key)) {
        ++num;
      } else {
        --num;
      }
      log_();
    }

    void set(const RemapConsumerParams &remapParams)
    {
      if ((remapParams.params)->eventType == KeyEvent::DOWN) {
        ++num;
      } else if ((remapParams.params)->eventType == KeyEvent::UP) {
        --num;
      }
      log_();
    }

    void
    reset(void)
    {
      num = 0;
    }

    bool
    iszero(void)
    {
      return num <= 0;
    }
  }
}
<commit_msg>update kext/util/NumHeldDownKeys<commit_after>#include "NumHeldDownKeys.hpp"
#include "Config.hpp"
#include "RemapUtil.hpp"

namespace org_pqrs_KeyRemap4MacBook {
  namespace NumHeldDownKeys {
    int num = 0;

    static void
    log_(void)
    {
      if (config.debug_devel) {
        printf("KeyRemap4MacBook NumHeldDownKeys = %d\n", num);
      }
    }

    void
    set(const RemapParams &remapParams)
    {
      if (RemapUtil::isKeyDown(remapParams, (remapParams.params)->key)) {
        ++num;
      } else {
        --num;
      }
      log_();
    }

    void set(const RemapConsumerParams &remapParams)
    {
      if ((remapParams.params)->eventType == KeyEvent::DOWN) {
        ++num;
      } else if ((remapParams.params)->eventType == KeyEvent::UP) {
        --num;
      }
      log_();
    }

    void
    reset(void)
    {
      if (config.debug_devel) {
        printf("KeyRemap4MacBook NumHeldDownKeys::reset\n");
      }
      num = 0;
    }

    bool
    iszero(void)
    {
      return num <= 0;
    }
  }
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "minputmethodstate.h"
#include "minputmethodstate_p.h"

#include "qapplication.h"
#include "qinputcontext.h"

#include <MDebug>

#include <QTimer>
#include <QKeyEvent>

namespace {
    const char * const ToolbarExtension("/toolbar");
}

MInputMethodStatePrivate::MInputMethodStatePrivate()
    : orientationAngle(M::Angle0),
      rotationInProgress(false),
      q_ptr(NULL)
{
}

MInputMethodStatePrivate::~MInputMethodStatePrivate()
{
    Q_Q(MInputMethodState);

    foreach (int id, attributeExtensions.keys()) {
        emit q->attributeExtensionUnregistered(id);
        delete attributeExtensions[id];
    }
}

void MInputMethodStatePrivate::init()
{
}

MInputMethodState::MInputMethodState()
    : d_ptr(new MInputMethodStatePrivate)
{
    Q_D(MInputMethodState);

    d->q_ptr = this;
    d->init();
    connect(this, SIGNAL(attributeExtensionRegistered(int, QString)),
            this, SIGNAL(toolbarRegistered(int,QString)));
    connect(this, SIGNAL(attributeExtensionUnregistered(int)),
            this, SIGNAL(toolbarUnregistered(int)));
}

MInputMethodState::~MInputMethodState()
{
    delete d_ptr;
}

MInputMethodState *MInputMethodState::instance()
{
    static MInputMethodState singleton;

    return &singleton;
}

void MInputMethodState::setInputMethodArea(const QRect &newRegion)
{
    Q_D(MInputMethodState);

    if (d->region != newRegion) {
        d->region = newRegion;
        emit inputMethodAreaChanged(d->region);
    }
}

QRect MInputMethodState::inputMethodArea() const
{
    Q_D(const MInputMethodState);

    return d->region;
}

void MInputMethodState::startActiveWindowOrientationAngleChange(M::OrientationAngle newOrientationAngle)
{
    Q_D(MInputMethodState);

    if (d->orientationAngle != newOrientationAngle) {
        d->orientationAngle = newOrientationAngle;
        d->rotationInProgress = true;
        emit activeWindowOrientationAngleAboutToChange(newOrientationAngle);
    }
}

void MInputMethodState::setActiveWindowOrientationAngle(M::OrientationAngle newOrientationAngle)
{
    Q_D(MInputMethodState);

    if (d->orientationAngle != newOrientationAngle) {
        d->orientationAngle = newOrientationAngle;
        d->rotationInProgress = true;
    }
    if (d->rotationInProgress) {
        d->rotationInProgress = false;
        emit activeWindowOrientationAngleChanged(newOrientationAngle);
    }
}

M::OrientationAngle MInputMethodState::activeWindowOrientationAngle() const
{
    Q_D(const MInputMethodState);

    return d->orientationAngle;
}

void MInputMethodState::requestSoftwareInputPanel()
{
    QInputContext *inputContext = qApp->inputContext();

    if (!inputContext) {
        return;
    }

    QEvent request(QEvent::RequestSoftwareInputPanel);
    inputContext->filterEvent(&request);
}

void MInputMethodState::closeSoftwareInputPanel()
{
    QInputContext *inputContext = qApp->inputContext();

    if (!inputContext) {
        return;
    }

    QEvent close(QEvent::CloseSoftwareInputPanel);
    inputContext->filterEvent(&close);
    inputContext->reset();
}

void MInputMethodState::emitKeyPress(const QKeyEvent &event)
{
    emit keyPress(event);
}

void MInputMethodState::emitKeyRelease(const QKeyEvent &event)
{
    emit keyRelease(event);
}

QList<int> MInputMethodState::toolbarIds() const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use attributeExtensionIds() instead";
    return attributeExtensionIds();
}

MInputMethodState::ItemAttributeMap MInputMethodState::toolbarState(int id) const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use extendedAttributes() instead";
    Q_D(const MInputMethodState);
    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    return (attributeExtension ? attributeExtension->extendedAttributes.value(ToolbarExtension) : ItemAttributeMap());
}

int MInputMethodState::registerToolbar(const QString &fileName)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use registerAttributeExtension() instead";
    return registerAttributeExtension(fileName);
}

void MInputMethodState::unregisterToolbar(int id)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use unregisterAttributeExtension() instead";
    return unregisterAttributeExtension(id);
}

void MInputMethodState::setToolbarItemAttribute(int id, const QString &item,
                                                const QString &attribute, const QVariant &value)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use setExtendedAttribute() instead";
    Q_D(MInputMethodState);

    if (!d->attributeExtensions.contains(id)) {
        return;
    }

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions[id];
    bool changed = (value != attributeExtension->extendedAttributes[ToolbarExtension][item][attribute]);

    if (changed) {
        attributeExtension->extendedAttributes[ToolbarExtension][item][attribute] = value;
        emit toolbarItemAttributeChanged(id, item, attribute, value);
    }
}

QString MInputMethodState::toolbar(int id) const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use attributeExtensionFile() instead";
    return attributeExtensionFile(id);
}

QList<int> MInputMethodState::attributeExtensionIds() const
{
    Q_D(const MInputMethodState);
    return d->attributeExtensions.keys();
}

MInputMethodState::ExtendedAttributeMap MInputMethodState::extendedAttributes(int id) const
{
    Q_D(const MInputMethodState);
    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    return (attributeExtension ? attributeExtension->extendedAttributes : ExtendedAttributeMap());
}

int MInputMethodState::registerAttributeExtension(const QString &fileName)
{
    Q_D(MInputMethodState);
    static int idCounter = 0;
    // generate an application local unique identifier for the toolbar.
    int newId = idCounter;
    idCounter++;
    d->attributeExtensions.insert(newId, new AttributeExtensionInfo(fileName));
    emit attributeExtensionRegistered(newId, fileName);
    return newId;
}

void MInputMethodState::unregisterAttributeExtension(int id)
{
    Q_D(MInputMethodState);
    delete d->attributeExtensions[id];
    d->attributeExtensions.remove(id);
    emit attributeExtensionUnregistered(id);
}

void MInputMethodState::setExtendedAttribute(int id, const QString &target, const QString &targetItem,
                                             const QString &attribute, const QVariant &value)
{
    Q_D(MInputMethodState);

    if (!d->attributeExtensions.contains(id)) {
        return;
    }

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions[id];
    bool changed = (value != attributeExtension->extendedAttributes[target][targetItem][attribute]);

    if (changed) {
        attributeExtension->extendedAttributes[target][targetItem][attribute] = value;
        emit extendedAttributeChanged(id, target, targetItem, attribute, value);
    }
}

QString MInputMethodState::attributeExtensionFile(int id) const
{
    Q_D(const MInputMethodState);

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    if (attributeExtension) {
        return attributeExtension->fileName;
    } else {
        return QString();
    }
}

#include "moc_minputmethodstate.cpp"
<commit_msg>Changes: Use proper include tags.<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "minputmethodstate.h"
#include "minputmethodstate_p.h"

#include <MDebug>

#include <QApplication>
#include <QInputContext>
#include <QTimer>
#include <QKeyEvent>

namespace {
    const char * const ToolbarExtension("/toolbar");
}

MInputMethodStatePrivate::MInputMethodStatePrivate()
    : orientationAngle(M::Angle0),
      rotationInProgress(false),
      q_ptr(NULL)
{
}

MInputMethodStatePrivate::~MInputMethodStatePrivate()
{
    Q_Q(MInputMethodState);

    foreach (int id, attributeExtensions.keys()) {
        emit q->attributeExtensionUnregistered(id);
        delete attributeExtensions[id];
    }
}

void MInputMethodStatePrivate::init()
{
}

MInputMethodState::MInputMethodState()
    : d_ptr(new MInputMethodStatePrivate)
{
    Q_D(MInputMethodState);

    d->q_ptr = this;
    d->init();
    connect(this, SIGNAL(attributeExtensionRegistered(int, QString)),
            this, SIGNAL(toolbarRegistered(int,QString)));
    connect(this, SIGNAL(attributeExtensionUnregistered(int)),
            this, SIGNAL(toolbarUnregistered(int)));
}

MInputMethodState::~MInputMethodState()
{
    delete d_ptr;
}

MInputMethodState *MInputMethodState::instance()
{
    static MInputMethodState singleton;

    return &singleton;
}

void MInputMethodState::setInputMethodArea(const QRect &newRegion)
{
    Q_D(MInputMethodState);

    if (d->region != newRegion) {
        d->region = newRegion;
        emit inputMethodAreaChanged(d->region);
    }
}

QRect MInputMethodState::inputMethodArea() const
{
    Q_D(const MInputMethodState);

    return d->region;
}

void MInputMethodState::startActiveWindowOrientationAngleChange(M::OrientationAngle newOrientationAngle)
{
    Q_D(MInputMethodState);

    if (d->orientationAngle != newOrientationAngle) {
        d->orientationAngle = newOrientationAngle;
        d->rotationInProgress = true;
        emit activeWindowOrientationAngleAboutToChange(newOrientationAngle);
    }
}

void MInputMethodState::setActiveWindowOrientationAngle(M::OrientationAngle newOrientationAngle)
{
    Q_D(MInputMethodState);

    if (d->orientationAngle != newOrientationAngle) {
        d->orientationAngle = newOrientationAngle;
        d->rotationInProgress = true;
    }
    if (d->rotationInProgress) {
        d->rotationInProgress = false;
        emit activeWindowOrientationAngleChanged(newOrientationAngle);
    }
}

M::OrientationAngle MInputMethodState::activeWindowOrientationAngle() const
{
    Q_D(const MInputMethodState);

    return d->orientationAngle;
}

void MInputMethodState::requestSoftwareInputPanel()
{
    QInputContext *inputContext = qApp->inputContext();

    if (!inputContext) {
        return;
    }

    QEvent request(QEvent::RequestSoftwareInputPanel);
    inputContext->filterEvent(&request);
}

void MInputMethodState::closeSoftwareInputPanel()
{
    QInputContext *inputContext = qApp->inputContext();

    if (!inputContext) {
        return;
    }

    QEvent close(QEvent::CloseSoftwareInputPanel);
    inputContext->filterEvent(&close);
    inputContext->reset();
}

void MInputMethodState::emitKeyPress(const QKeyEvent &event)
{
    emit keyPress(event);
}

void MInputMethodState::emitKeyRelease(const QKeyEvent &event)
{
    emit keyRelease(event);
}

QList<int> MInputMethodState::toolbarIds() const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use attributeExtensionIds() instead";
    return attributeExtensionIds();
}

MInputMethodState::ItemAttributeMap MInputMethodState::toolbarState(int id) const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use extendedAttributes() instead";
    Q_D(const MInputMethodState);
    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    return (attributeExtension ? attributeExtension->extendedAttributes.value(ToolbarExtension) : ItemAttributeMap());
}

int MInputMethodState::registerToolbar(const QString &fileName)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use registerAttributeExtension() instead";
    return registerAttributeExtension(fileName);
}

void MInputMethodState::unregisterToolbar(int id)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use unregisterAttributeExtension() instead";
    return unregisterAttributeExtension(id);
}

void MInputMethodState::setToolbarItemAttribute(int id, const QString &item,
                                                const QString &attribute, const QVariant &value)
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use setExtendedAttribute() instead";
    Q_D(MInputMethodState);

    if (!d->attributeExtensions.contains(id)) {
        return;
    }

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions[id];
    bool changed = (value != attributeExtension->extendedAttributes[ToolbarExtension][item][attribute]);

    if (changed) {
        attributeExtension->extendedAttributes[ToolbarExtension][item][attribute] = value;
        emit toolbarItemAttributeChanged(id, item, attribute, value);
    }
}

QString MInputMethodState::toolbar(int id) const
{
    mWarning("MInputMethodState") << Q_FUNC_INFO << "is deprecated. Use attributeExtensionFile() instead";
    return attributeExtensionFile(id);
}

QList<int> MInputMethodState::attributeExtensionIds() const
{
    Q_D(const MInputMethodState);
    return d->attributeExtensions.keys();
}

MInputMethodState::ExtendedAttributeMap MInputMethodState::extendedAttributes(int id) const
{
    Q_D(const MInputMethodState);
    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    return (attributeExtension ? attributeExtension->extendedAttributes : ExtendedAttributeMap());
}

int MInputMethodState::registerAttributeExtension(const QString &fileName)
{
    Q_D(MInputMethodState);
    static int idCounter = 0;
    // generate an application local unique identifier for the toolbar.
    int newId = idCounter;
    idCounter++;
    d->attributeExtensions.insert(newId, new AttributeExtensionInfo(fileName));
    emit attributeExtensionRegistered(newId, fileName);
    return newId;
}

void MInputMethodState::unregisterAttributeExtension(int id)
{
    Q_D(MInputMethodState);
    delete d->attributeExtensions[id];
    d->attributeExtensions.remove(id);
    emit attributeExtensionUnregistered(id);
}

void MInputMethodState::setExtendedAttribute(int id, const QString &target, const QString &targetItem,
                                             const QString &attribute, const QVariant &value)
{
    Q_D(MInputMethodState);

    if (!d->attributeExtensions.contains(id)) {
        return;
    }

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions[id];
    bool changed = (value != attributeExtension->extendedAttributes[target][targetItem][attribute]);

    if (changed) {
        attributeExtension->extendedAttributes[target][targetItem][attribute] = value;
        emit extendedAttributeChanged(id, target, targetItem, attribute, value);
    }
}

QString MInputMethodState::attributeExtensionFile(int id) const
{
    Q_D(const MInputMethodState);

    AttributeExtensionInfo *attributeExtension = d->attributeExtensions.value(id);

    if (attributeExtension) {
        return attributeExtension->fileName;
    } else {
        return QString();
    }
}

#include "moc_minputmethodstate.cpp"
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2009 Soeren Sonnenburg
 * Written (W) 2016 Soumyajit De
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/features/Features.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CEuclideanDistance::CEuclideanDistance() : CDistance()
{
	register_params();
}

CEuclideanDistance::CEuclideanDistance(CDotFeatures* l, CDotFeatures* r) : CDistance()
{
	register_params();
	init(l, r);
}

CEuclideanDistance::~CEuclideanDistance()
{
	cleanup();
}

bool CEuclideanDistance::init(CFeatures* l, CFeatures* r)
{
	cleanup();

	CDistance::init(l, r);
	REQUIRE(l->has_property(FP_DOT), "Left hand side features must support dot property!\n");
	REQUIRE(r->has_property(FP_DOT), "Right hand side features must support dot property!\n");

	CDotFeatures* casted_l=static_cast<CDotFeatures*>(l);
	CDotFeatures* casted_r=static_cast<CDotFeatures*>(r);

	REQUIRE(casted_l->get_dim_feature_space()==casted_r->get_dim_feature_space(),
		"Number of dimension mismatch (l:%d vs. r:%d)!\n",
		casted_l->get_dim_feature_space(),casted_r->get_dim_feature_space());

	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();

	return true;
}

void CEuclideanDistance::cleanup()
{
	reset_precompute();
}

float64_t CEuclideanDistance::compute(int32_t idx_a, int32_t idx_b)
{
	float64_t result=0;
	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);

	if (lhs->get_feature_class()==rhs->get_feature_class() || lhs->support_compatible_class())
		result=casted_lhs->dot(idx_a, casted_rhs, idx_b);
	else
		result=casted_rhs->dot(idx_b, casted_lhs, idx_a);

	SG_DEBUG("distance=(%f)+(%f)-2*(%f)\n", m_lhs_squared_norms[idx_a], m_rhs_squared_norms[idx_a], result);

	result=m_lhs_squared_norms[idx_a]+m_rhs_squared_norms[idx_b]-2*result;
	if (disable_sqrt)
		return result;
	return CMath::sqrt(result);
}

void CEuclideanDistance::precompute_lhs()
{
	REQUIRE(lhs, "Left hand side feature cannot be NULL!\n");
	const index_t num_vec=lhs->get_num_vectors();

	if (m_lhs_squared_norms.vlen!=num_vec)
		m_lhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_lhs_squared_norms[i]=casted_lhs->dot(i, casted_lhs, i);
}

void CEuclideanDistance::precompute_rhs()
{
	REQUIRE(rhs, "Right hand side feature cannot be NULL!\n");
	const index_t num_vec=rhs->get_num_vectors();

	if (m_rhs_squared_norms.vlen!=num_vec)
		m_rhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_rhs_squared_norms[i]=casted_rhs->dot(i, casted_rhs, i);
}

void CEuclideanDistance::reset_precompute()
{
	m_lhs_squared_norms=SGVector<float64_t>();
	m_rhs_squared_norms=SGVector<float64_t>();
}

CFeatures* CEuclideanDistance::replace_lhs(CFeatures* l)
{
	CFeatures* previous_lhs=CDistance::replace_lhs(l);
	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	return previous_lhs;
}

CFeatures* CEuclideanDistance::replace_rhs(CFeatures* r)
{
	CFeatures* previous_rhs=CDistance::replace_rhs(r);
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();
	return previous_rhs;
}

void CEuclideanDistance::register_params()
{
	disable_sqrt=false;
	reset_precompute();
	SG_ADD(&disable_sqrt, "disable_sqrt", "If sqrt shall not be applied.", MS_NOT_AVAILABLE);
	SG_ADD(&m_rhs_squared_norms, "m_rhs_squared_norms", "Squared norms from features of right hand side", MS_NOT_AVAILABLE);
	SG_ADD(&m_lhs_squared_norms, "m_lhs_squared_norms", "Squared norms from features of left hand side", MS_NOT_AVAILABLE);
}

float64_t CEuclideanDistance::distance_upper_bounded(int32_t idx_a, int32_t idx_b, float64_t upper_bound)
{
	REQUIRE(lhs->get_feature_class()==C_DENSE,
		"Left hand side (was %s) has to be CDenseFeatures instance!\n", lhs->get_name());
	REQUIRE(rhs->get_feature_class()==C_DENSE,
		"Right hand side (was %s) has to be CDenseFeatures instance!\n", rhs->get_name());

	REQUIRE(lhs->get_feature_type()==F_DREAL,
		"Left hand side (was %s) has to be of double type!\n", lhs->get_name());
	REQUIRE(rhs->get_feature_type()==F_DREAL,
		"Right hand side (was %s) has to be double type!\n", rhs->get_name());

	CDenseFeatures<float64_t>* casted_lhs=static_cast<CDenseFeatures<float64_t>*>(lhs);
	CDenseFeatures<float64_t>* casted_rhs=static_cast<CDenseFeatures<float64_t>*>(rhs);

	upper_bound*=upper_bound;

	SGVector<float64_t> avec=casted_lhs->get_feature_vector(idx_a);
	SGVector<float64_t> bvec=casted_rhs->get_feature_vector(idx_b);

	REQUIRE(avec.vlen==bvec.vlen, "The vector lengths are not equal (%d vs %d)!\n", avec.vlen, bvec.vlen);

	float64_t result=0;
	for (int32_t i=0; i<avec.vlen; i++)
	{
		result+=CMath::sq(avec[i]-bvec[i]);
		if (result>upper_bound)
			break;
	}

	if (!disable_sqrt)
		result=CMath::sqrt(result);

	return result;
}
<commit_msg>removed debug msg from euclidean distance<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2007-2009 Soeren Sonnenburg
 * Written (W) 2016 Soumyajit De
 * Copyright (C) 2007-2009 Fraunhofer Institute FIRST and Max-Planck-Society
 */

#include <shogun/lib/common.h>
#include <shogun/distance/EuclideanDistance.h>
#include <shogun/features/Features.h>
#include <shogun/features/DotFeatures.h>
#include <shogun/features/DenseFeatures.h>
#include <shogun/mathematics/Math.h>

using namespace shogun;

CEuclideanDistance::CEuclideanDistance() : CDistance()
{
	register_params();
}

CEuclideanDistance::CEuclideanDistance(CDotFeatures* l, CDotFeatures* r) : CDistance()
{
	register_params();
	init(l, r);
}

CEuclideanDistance::~CEuclideanDistance()
{
	cleanup();
}

bool CEuclideanDistance::init(CFeatures* l, CFeatures* r)
{
	cleanup();

	CDistance::init(l, r);
	REQUIRE(l->has_property(FP_DOT), "Left hand side features must support dot property!\n");
	REQUIRE(r->has_property(FP_DOT), "Right hand side features must support dot property!\n");

	CDotFeatures* casted_l=static_cast<CDotFeatures*>(l);
	CDotFeatures* casted_r=static_cast<CDotFeatures*>(r);

	REQUIRE(casted_l->get_dim_feature_space()==casted_r->get_dim_feature_space(),
		"Number of dimension mismatch (l:%d vs. r:%d)!\n",
		casted_l->get_dim_feature_space(),casted_r->get_dim_feature_space());

	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();

	return true;
}

void CEuclideanDistance::cleanup()
{
	reset_precompute();
}

float64_t CEuclideanDistance::compute(int32_t idx_a, int32_t idx_b)
{
	float64_t result=0;
	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);

	if (lhs->get_feature_class()==rhs->get_feature_class() || lhs->support_compatible_class())
		result=casted_lhs->dot(idx_a, casted_rhs, idx_b);
	else
		result=casted_rhs->dot(idx_b, casted_lhs, idx_a);

	result=m_lhs_squared_norms[idx_a]+m_rhs_squared_norms[idx_b]-2*result;
	if (disable_sqrt)
		return result;
	return CMath::sqrt(result);
}

void CEuclideanDistance::precompute_lhs()
{
	REQUIRE(lhs, "Left hand side feature cannot be NULL!\n");
	const index_t num_vec=lhs->get_num_vectors();

	if (m_lhs_squared_norms.vlen!=num_vec)
		m_lhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_lhs=static_cast<CDotFeatures*>(lhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_lhs_squared_norms[i]=casted_lhs->dot(i, casted_lhs, i);
}

void CEuclideanDistance::precompute_rhs()
{
	REQUIRE(rhs, "Right hand side feature cannot be NULL!\n");
	const index_t num_vec=rhs->get_num_vectors();

	if (m_rhs_squared_norms.vlen!=num_vec)
		m_rhs_squared_norms=SGVector<float64_t>(num_vec);

	CDotFeatures* casted_rhs=static_cast<CDotFeatures*>(rhs);
#pragma omp parallel for
	for(index_t i =0; i<num_vec; ++i)
		m_rhs_squared_norms[i]=casted_rhs->dot(i, casted_rhs, i);
}

void CEuclideanDistance::reset_precompute()
{
	m_lhs_squared_norms=SGVector<float64_t>();
	m_rhs_squared_norms=SGVector<float64_t>();
}

CFeatures* CEuclideanDistance::replace_lhs(CFeatures* l)
{
	CFeatures* previous_lhs=CDistance::replace_lhs(l);
	precompute_lhs();
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	return previous_lhs;
}

CFeatures* CEuclideanDistance::replace_rhs(CFeatures* r)
{
	CFeatures* previous_rhs=CDistance::replace_rhs(r);
	if (lhs==rhs)
		m_rhs_squared_norms=m_lhs_squared_norms;
	else
		precompute_rhs();
	return previous_rhs;
}

void CEuclideanDistance::register_params()
{
	disable_sqrt=false;
	reset_precompute();
	SG_ADD(&disable_sqrt, "disable_sqrt", "If sqrt shall not be applied.", MS_NOT_AVAILABLE);
	SG_ADD(&m_rhs_squared_norms, "m_rhs_squared_norms", "Squared norms from features of right hand side", MS_NOT_AVAILABLE);
	SG_ADD(&m_lhs_squared_norms, "m_lhs_squared_norms", "Squared norms from features of left hand side", MS_NOT_AVAILABLE);
}

float64_t CEuclideanDistance::distance_upper_bounded(int32_t idx_a, int32_t idx_b, float64_t upper_bound)
{
	REQUIRE(lhs->get_feature_class()==C_DENSE,
		"Left hand side (was %s) has to be CDenseFeatures instance!\n", lhs->get_name());
	REQUIRE(rhs->get_feature_class()==C_DENSE,
		"Right hand side (was %s) has to be CDenseFeatures instance!\n", rhs->get_name());

	REQUIRE(lhs->get_feature_type()==F_DREAL,
		"Left hand side (was %s) has to be of double type!\n", lhs->get_name());
	REQUIRE(rhs->get_feature_type()==F_DREAL,
		"Right hand side (was %s) has to be double type!\n", rhs->get_name());

	CDenseFeatures<float64_t>* casted_lhs=static_cast<CDenseFeatures<float64_t>*>(lhs);
	CDenseFeatures<float64_t>* casted_rhs=static_cast<CDenseFeatures<float64_t>*>(rhs);

	upper_bound*=upper_bound;

	SGVector<float64_t> avec=casted_lhs->get_feature_vector(idx_a);
	SGVector<float64_t> bvec=casted_rhs->get_feature_vector(idx_b);

	REQUIRE(avec.vlen==bvec.vlen, "The vector lengths are not equal (%d vs %d)!\n", avec.vlen, bvec.vlen);

	float64_t result=0;
	for (int32_t i=0; i<avec.vlen; i++)
	{
		result+=CMath::sq(avec[i]-bvec[i]);
		if (result>upper_bound)
			break;
	}

	if (!disable_sqrt)
		result=CMath::sqrt(result);

	return result;
}
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbasiclistitem.h"
#include "mbasiclistitem_p.h"

#include <MLabel>
#include <MImageWidget>

#include <MWidgetStyle>

#include <QGraphicsGridLayout>
#include <QGraphicsWidget>

MBasicListItemPrivate::MBasicListItemPrivate(MBasicListItem::ItemStyle style)
    : q_ptr(NULL),
    layoutGrid(NULL),
    image(NULL),
    titleLabel(NULL),
    subtitleLabel(NULL),
    isLayoutInitialized(false),
    listItemStyle(style)
{
}

MBasicListItemPrivate::~MBasicListItemPrivate()
{
}

void MBasicListItemPrivate::createLayout()
{
    Q_Q(MBasicListItem);

    layoutGrid = new QGraphicsGridLayout(q);
    layoutGrid->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
    layoutGrid->setContentsMargins(0, 0, 0, 0);
    layoutGrid->setSpacing(0);

    switch (listItemStyle) {
    case MBasicListItem::SingleTitle: {
            q->titleLabelWidget()->setObjectName("CommonSingleTitle");
            layout()->addItem(q->titleLabelWidget(), 0, 0);
            break;
        }
    case MBasicListItem::TitleWithSubtitle: {
            q->titleLabelWidget()->setObjectName("CommonTitle");
            layout()->addItem(q->titleLabelWidget(), 0, 0);
            layout()->addItem(q->subtitleLabelWidget(), 1, 0);
            layout()->addItem(new QGraphicsWidget(q), 2, 0);
            break;
        }
    case MBasicListItem::IconWithTitle: {
            q->titleLabelWidget()->setObjectName("CommonSingleTitle");
            layout()->addItem(q->imageWidget(), 0, 0);
            layout()->addItem(q->titleLabelWidget(), 0, 1);
            break;
        }
    case MBasicListItem::IconWithTitleAndSubtitle: {
            q->titleLabelWidget()->setObjectName("CommonTitle");
            layout()->addItem(q->imageWidget(), 0, 0, 3, 1);
            layout()->addItem(q->titleLabelWidget(), 0, 1);
            layout()->addItem(q->subtitleLabelWidget(), 1, 1);
            layout()->addItem(new QGraphicsWidget(q), 2, 1);
            break;
        }
    default:
        break;
    }
}

void MBasicListItemPrivate::clearLayout()
{
    if (layout()) {
        for (int i = 0; i < layout()->count(); i++) {
            QGraphicsLayoutItem *item = layout()->itemAt(0);
            layout()->removeAt(0);
            delete item;
        }
        image = NULL;
        titleLabel = NULL;
        subtitleLabel = NULL;
    }
}

QGraphicsGridLayout *MBasicListItemPrivate::layout()
{
    return layoutGrid;
}

MBasicListItem::MBasicListItem(MBasicListItem::ItemStyle style, QGraphicsItem *parent)
    : MListItem(parent), d_ptr(new MBasicListItemPrivate(style))
{
    Q_D(MBasicListItem);
    d->q_ptr = this;

    setItemStyle(style);
    setObjectName("CommonPanel");
}

MBasicListItem::~MBasicListItem()
{
    delete d_ptr;
}

void MBasicListItem::initLayout()
{
    Q_D(MBasicListItem);

    if (d->isLayoutInitialized)
        return;

    setLayout(createLayout());
    d->isLayoutInitialized = true;
}

QGraphicsLayout *MBasicListItem::createLayout()
{
    Q_D(MBasicListItem);

    clearLayout();
    d->createLayout();

    return d->layout();
}

void MBasicListItem::clearLayout()
{
    Q_D(MBasicListItem);

    d->clearLayout();
}

void MBasicListItem::setItemStyle(ItemStyle itemStyle)
{
    Q_D(MBasicListItem);

    if (itemStyle == d->listItemStyle)
        return;

    d->listItemStyle = itemStyle;
    d->isLayoutInitialized = false;
    initLayout();
}

MBasicListItem::ItemStyle MBasicListItem::itemStyle() const
{
    Q_D(const MBasicListItem);

    return d->listItemStyle;
}

void MBasicListItem::setImageWidget(MImageWidget *imageWidget)
{
    Q_D(MBasicListItem);

    if (d->image) {
        for (int i = 0; i < d->layout()->count(); i++) {
            if (d->layout()->itemAt(i) == d->image) {
                d->layout()->removeAt(i);
                delete d->image;
                d->image = NULL;
                break;
            }
        }
    }

    if (imageWidget) {
        d->image = imageWidget;
        if (d->listItemStyle == MBasicListItem::IconWithTitle)
            d->layout()->addItem(d->image, 0, 0);
        else if (d->listItemStyle == MBasicListItem::IconWithTitleAndSubtitle)
            d->layout()->addItem(d->image, 0, 0, 3, 1);
    }
}

MImageWidget *MBasicListItem::imageWidget()
{
    Q_D(MBasicListItem);

    if (!d->image) {
        d->image = new MImageWidget(this);
        d->image->setObjectName("CommonMainIcon");
    }
    return d->image;
}

MLabel *MBasicListItem::titleLabelWidget()
{
    Q_D(MBasicListItem);

    if (!d->titleLabel) {
        d->titleLabel = new MLabel(this);
        d->titleLabel->setTextElide(true);
        d->titleLabel->setObjectName("CommonTitle");
    }

    return d->titleLabel;
}

MLabel *MBasicListItem::subtitleLabelWidget()
{
    Q_D(MBasicListItem);

    if (!d->subtitleLabel) {
        d->subtitleLabel = new MLabel(this);
        d->subtitleLabel->setObjectName("CommonSubTitle");
    }

    return d->subtitleLabel;
}

void MBasicListItem::setTitle(const QString &title)
{
    titleLabelWidget()->setText(title);
}

QString MBasicListItem::title()
{
    return titleLabelWidget()->text();
}

void MBasicListItem::setSubtitle(const QString &subtitle)
{
    subtitleLabelWidget()->setText(subtitle);
}

QString MBasicListItem::subtitle()
{
    return subtitleLabelWidget()->text();
}

void MBasicListItem::resizeEvent(QGraphicsSceneResizeEvent *event)
{
    MListItem::resizeEvent(event);
    initLayout();
}

<commit_msg>Fixes: NB#188127 -  MBasicListItem crashes when setting ImageWidget into it<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include "mbasiclistitem.h"
#include "mbasiclistitem_p.h"

#include <MLabel>
#include <MImageWidget>

#include <MWidgetStyle>

#include <QGraphicsGridLayout>
#include <QGraphicsWidget>

MBasicListItemPrivate::MBasicListItemPrivate(MBasicListItem::ItemStyle style)
    : q_ptr(NULL),
    layoutGrid(NULL),
    image(NULL),
    titleLabel(NULL),
    subtitleLabel(NULL),
    isLayoutInitialized(false),
    listItemStyle(style)
{
}

MBasicListItemPrivate::~MBasicListItemPrivate()
{
}

void MBasicListItemPrivate::createLayout()
{
    Q_Q(MBasicListItem);

    layoutGrid = new QGraphicsGridLayout(q);
    layoutGrid->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
    layoutGrid->setContentsMargins(0, 0, 0, 0);
    layoutGrid->setSpacing(0);

    switch (listItemStyle) {
    case MBasicListItem::SingleTitle: {
            q->titleLabelWidget()->setObjectName("CommonSingleTitle");
            layout()->addItem(q->titleLabelWidget(), 0, 0);
            break;
        }
    case MBasicListItem::TitleWithSubtitle: {
            q->titleLabelWidget()->setObjectName("CommonTitle");
            layout()->addItem(q->titleLabelWidget(), 0, 0);
            layout()->addItem(q->subtitleLabelWidget(), 1, 0);
            layout()->addItem(new QGraphicsWidget(q), 2, 0);
            break;
        }
    case MBasicListItem::IconWithTitle: {
            q->titleLabelWidget()->setObjectName("CommonSingleTitle");
            layout()->addItem(q->imageWidget(), 0, 0);
            layout()->addItem(q->titleLabelWidget(), 0, 1);
            break;
        }
    case MBasicListItem::IconWithTitleAndSubtitle: {
            q->titleLabelWidget()->setObjectName("CommonTitle");
            layout()->addItem(q->imageWidget(), 0, 0, 3, 1);
            layout()->addItem(q->titleLabelWidget(), 0, 1);
            layout()->addItem(q->subtitleLabelWidget(), 1, 1);
            layout()->addItem(new QGraphicsWidget(q), 2, 1);
            break;
        }
    default:
        break;
    }
}

void MBasicListItemPrivate::clearLayout()
{
    if (layout()) {
        for (int i = 0; i < layout()->count(); i++) {
            QGraphicsLayoutItem *item = layout()->itemAt(0);
            layout()->removeAt(0);
            delete item;
        }
        image = NULL;
        titleLabel = NULL;
        subtitleLabel = NULL;
    }
}

QGraphicsGridLayout *MBasicListItemPrivate::layout()
{
    return layoutGrid;
}

MBasicListItem::MBasicListItem(MBasicListItem::ItemStyle style, QGraphicsItem *parent)
    : MListItem(parent), d_ptr(new MBasicListItemPrivate(style))
{
    Q_D(MBasicListItem);
    d->q_ptr = this;

    setItemStyle(style);
    setObjectName("CommonPanel");
}

MBasicListItem::~MBasicListItem()
{
    delete d_ptr;
}

void MBasicListItem::initLayout()
{
    Q_D(MBasicListItem);

    if (d->isLayoutInitialized)
        return;

    setLayout(createLayout());
    d->isLayoutInitialized = true;
}

QGraphicsLayout *MBasicListItem::createLayout()
{
    Q_D(MBasicListItem);

    clearLayout();
    d->createLayout();

    return d->layout();
}

void MBasicListItem::clearLayout()
{
    Q_D(MBasicListItem);

    d->clearLayout();
}

void MBasicListItem::setItemStyle(ItemStyle itemStyle)
{
    Q_D(MBasicListItem);

    if (itemStyle == d->listItemStyle)
        return;

    d->listItemStyle = itemStyle;
    d->isLayoutInitialized = false;
    initLayout();
}

MBasicListItem::ItemStyle MBasicListItem::itemStyle() const
{
    Q_D(const MBasicListItem);

    return d->listItemStyle;
}

void MBasicListItem::setImageWidget(MImageWidget *imageWidget)
{
    Q_D(MBasicListItem);

    if (d->layout() && d->image) {
        for (int i = 0; i < d->layout()->count(); i++) {
            if (d->layout()->itemAt(i) == d->image) {
                d->layout()->removeAt(i);
                delete d->image;
                d->image = NULL;
                break;
            }
        }
    }

    if (imageWidget) {
        d->image = imageWidget;
        if (d->layout()) {
            if (d->listItemStyle == MBasicListItem::IconWithTitle)
                d->layout()->addItem(d->image, 0, 0);
            else if (d->listItemStyle == MBasicListItem::IconWithTitleAndSubtitle)
                d->layout()->addItem(d->image, 0, 0, 3, 1);
        }
    }
}

MImageWidget *MBasicListItem::imageWidget()
{
    Q_D(MBasicListItem);

    if (!d->image) {
        d->image = new MImageWidget(this);
        d->image->setObjectName("CommonMainIcon");
    }
    return d->image;
}

MLabel *MBasicListItem::titleLabelWidget()
{
    Q_D(MBasicListItem);

    if (!d->titleLabel) {
        d->titleLabel = new MLabel(this);
        d->titleLabel->setTextElide(true);
        d->titleLabel->setObjectName("CommonTitle");
    }

    return d->titleLabel;
}

MLabel *MBasicListItem::subtitleLabelWidget()
{
    Q_D(MBasicListItem);

    if (!d->subtitleLabel) {
        d->subtitleLabel = new MLabel(this);
        d->subtitleLabel->setObjectName("CommonSubTitle");
    }

    return d->subtitleLabel;
}

void MBasicListItem::setTitle(const QString &title)
{
    titleLabelWidget()->setText(title);
}

QString MBasicListItem::title()
{
    return titleLabelWidget()->text();
}

void MBasicListItem::setSubtitle(const QString &subtitle)
{
    subtitleLabelWidget()->setText(subtitle);
}

QString MBasicListItem::subtitle()
{
    return subtitleLabelWidget()->text();
}

void MBasicListItem::resizeEvent(QGraphicsSceneResizeEvent *event)
{
    MListItem::resizeEvent(event);
    initLayout();
}

<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011-2012 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/evaluation/CrossValidation.h>
#include <shogun/machine/Machine.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/base/Parameter.h>
#include <shogun/mathematics/Statistics.h>
#include <shogun/evaluation/CrossValidationOutput.h>
#include <shogun/lib/List.h>

using namespace shogun;

CCrossValidation::CCrossValidation() : CMachineEvaluation()
{
	init();
}

CCrossValidation::CCrossValidation(CMachine* machine, CFeatures* features,
		CLabels* labels, CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterion, bool autolock) :
		CMachineEvaluation(machine, features, labels, splitting_strategy,
		evaluation_criterion, autolock)
{
	init();
}

CCrossValidation::CCrossValidation(CMachine* machine, CLabels* labels,
		CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterion, bool autolock) :
		CMachineEvaluation(machine, labels, splitting_strategy, evaluation_criterion,
		autolock)
{
	init();
}

CCrossValidation::~CCrossValidation()
{
	SG_UNREF(m_xval_outputs);
}

void CCrossValidation::init()
{
	m_num_runs=1;

	/* do reference counting for output objects */
	m_xval_outputs=new CList(true);

	SG_ADD(&m_num_runs, "num_runs", "Number of repetitions",
			MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_xval_outputs, "m_xval_outputs", "List of output "
			"classes for intermediade cross-validation results",
			MS_NOT_AVAILABLE);
}

CEvaluationResult* CCrossValidation::evaluate()
{
	SG_DEBUG("entering %s::evaluate()\n", get_name())

	REQUIRE(m_machine, "%s::evaluate() is only possible if a machine is "
			"attached\n", get_name());

	REQUIRE(m_features, "%s::evaluate() is only possible if features are "
			"attached\n", get_name());

	REQUIRE(m_labels, "%s::evaluate() is only possible if labels are "
			"attached\n", get_name());

	/* if for some reason the do_unlock_frag is set, unlock */
	if (m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock=false;
	}

	/* set labels in any case (no locking needs this) */
	m_machine->set_labels(m_labels);

	if (m_autolock)
	{
		/* if machine supports locking try to do so */
		if (m_machine->supports_locking())
		{
			/* only lock if machine is not yet locked */
			if (!m_machine->is_data_locked())
			{
				m_machine->data_lock(m_labels, m_features);
				m_do_unlock=true;
			}
		}
		else
		{
			SG_WARNING("%s does not support locking. Autolocking is skipped. "
					"Set autolock flag to false to get rid of warning.\n",
					m_machine->get_name());
		}
	}

	SGVector<float64_t> results(m_num_runs);

	/* evtl. update xvalidation output class */
	CCrossValidationOutput* current=(CCrossValidationOutput*)
			m_xval_outputs->get_first_element();
	while (current)
	{
		current->init_num_runs(m_num_runs);
		current->init_num_folds(m_splitting_strategy->get_num_subsets());
		current->init_expose_labels(m_labels);
		current->post_init();
		SG_UNREF(current);
		current=(CCrossValidationOutput*)
				m_xval_outputs->get_next_element();
	}

	/* perform all the x-val runs */
	SG_DEBUG("starting %d runs of cross-validation\n", m_num_runs)
	for (index_t i=0; i <m_num_runs; ++i)
	{

		/* evtl. update xvalidation output class */
		current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
		while (current)
		{
			current->update_run_index(i);
			SG_UNREF(current);
			current=(CCrossValidationOutput*)
					m_xval_outputs->get_next_element();
		}

		SG_DEBUG("entering cross-validation run %d \n", i)
		results[i]=evaluate_one_run();
		SG_DEBUG("result of cross-validation run %d is %f\n", i, results[i])
	}

	/* construct evaluation result */
	CCrossValidationResult* result = new CCrossValidationResult();
	result->mean=CStatistics::mean(results);
	result->std_dev=CStatistics::std_deviation(results);

	/* unlock machine if it was locked in this method */
	if (m_machine->is_data_locked() && m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock=false;
	}

	SG_DEBUG("leaving %s::evaluate()\n", get_name())

	SG_REF(result);
	return result;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs <1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs)

	m_num_runs=num_runs;
}

float64_t CCrossValidation::evaluate_one_run()
{
	SG_DEBUG("entering %s::evaluate_one_run()\n", get_name())
	index_t num_subsets=m_splitting_strategy->get_num_subsets();

	SG_DEBUG("building index sets for %d-fold cross-validation\n", num_subsets)

	/* build index sets */
	m_splitting_strategy->build_subsets();

	/* results array */
	SGVector<float64_t> results(num_subsets);

	/* different behavior whether data is locked or not */
	if (m_machine->is_data_locked())
	{
		SG_DEBUG("starting locked evaluation\n", get_name())
		/* do actual cross-validation */
		for (index_t i=0; i <num_subsets; ++i)
		{
			/* evtl. update xvalidation output class */
			CCrossValidationOutput* current=(CCrossValidationOutput*)
					m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_fold_index(i);
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* index subset for training, will be freed below */
			SGVector<index_t> inverse_subset_indices =
					m_splitting_strategy->generate_subset_inverse(i);

			/* train machine on training features */
			m_machine->train_locked(inverse_subset_indices);

			/* feature subset for testing */
			SGVector<index_t> subset_indices =
					m_splitting_strategy->generate_subset_indices(i);

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_train_indices(inverse_subset_indices, "\t");
				current->update_trained_machine(m_machine, "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* produce output for desired indices */
			CLabels* result_labels=m_machine->apply_locked(subset_indices);
			SG_REF(result_labels);

			/* set subset for testing labels */
			m_labels->add_subset(subset_indices);

			/* evaluate against own labels */
			m_evaluation_criterion->set_indices(subset_indices);
			results[i]=m_evaluation_criterion->evaluate(result_labels, m_labels);

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_test_indices(subset_indices, "\t");
				current->update_test_result(result_labels, "\t");
				current->update_test_true_result(m_labels, "\t");
				current->post_update_results();
				current->update_evaluation_result(results[i], "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* remove subset to prevent side effects */
			m_labels->remove_subset();

			/* clean up */
			SG_UNREF(result_labels);

			SG_DEBUG("done locked evaluation\n", get_name())
		}
	}
	else
	{
		SG_DEBUG("starting unlocked evaluation\n", get_name())
		/* tell machine to store model internally
		 * (otherwise changing subset of features will kaboom the classifier) */
		m_machine->set_store_model_features(true);

		/* do actual cross-validation */
		for (index_t i=0; i <num_subsets; ++i)
		{
			/* evtl. update xvalidation output class */
			CCrossValidationOutput* current=(CCrossValidationOutput*)
					m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_fold_index(i);
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* set feature subset for training */
			SGVector<index_t> inverse_subset_indices=
					m_splitting_strategy->generate_subset_inverse(i);
			m_features->add_subset(inverse_subset_indices);
			for (index_t p=0; p<m_features->get_num_preprocessors(); p++)
			{
				CPreprocessor* preprocessor = m_features->get_preprocessor(p);
				preprocessor->init(m_features);
				SG_UNREF(preprocessor);
			}

			/* set label subset for training */
			m_labels->add_subset(inverse_subset_indices);

			SG_DEBUG("training set %d:\n", i)
			if (io->get_loglevel()==MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(inverse_subset_indices.vector,
						inverse_subset_indices.vlen, "training indices");
			}

			/* train machine on training features and remove subset */
			SG_DEBUG("starting training\n")
			m_machine->train(m_features);
			SG_DEBUG("finished training\n")

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_train_indices(inverse_subset_indices, "\t");
				current->update_trained_machine(m_machine, "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			m_features->remove_subset();
			m_labels->remove_subset();

			/* set feature subset for testing (subset method that stores pointer) */
			SGVector<index_t> subset_indices =
					m_splitting_strategy->generate_subset_indices(i);
			m_features->add_subset(subset_indices);

			/* set label subset for testing */
			m_labels->add_subset(subset_indices);

			SG_DEBUG("test set %d:\n", i)
			if (io->get_loglevel()==MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(subset_indices.vector,
						subset_indices.vlen, "test indices");
			}

			/* apply machine to test features and remove subset */
			SG_DEBUG("starting evaluation\n")
			SG_DEBUG("%p\n", m_features)
			CLabels* result_labels=m_machine->apply(m_features);
			SG_DEBUG("finished evaluation\n")
			m_features->remove_subset();
			SG_REF(result_labels);

			/* evaluate */
			results[i]=m_evaluation_criterion->evaluate(result_labels, m_labels);
			SG_DEBUG("result on fold %d is %f\n", i, results[i])

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_test_indices(subset_indices, "\t");
				current->update_test_result(result_labels, "\t");
				current->update_test_true_result(m_labels, "\t");
				current->post_update_results();
				current->update_evaluation_result(results[i], "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* clean up, remove subsets */
			SG_UNREF(result_labels);
			m_labels->remove_subset();
		}

		SG_DEBUG("done unlocked evaluation\n", get_name())
	}

	/* build arithmetic mean of results */
	float64_t mean=CStatistics::mean(results);

	SG_DEBUG("leaving %s::evaluate_one_run()\n", get_name())
	return mean;
}

void CCrossValidation::add_cross_validation_output(
			CCrossValidationOutput* cross_validation_output)
{
	m_xval_outputs->append_element(cross_validation_output);
}
<commit_msg>consider case where variance is not defined<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2011-2012 Heiko Strathmann
 * Copyright (C) 2011 Berlin Institute of Technology and Max-Planck-Society
 */

#include <shogun/evaluation/CrossValidation.h>
#include <shogun/machine/Machine.h>
#include <shogun/evaluation/Evaluation.h>
#include <shogun/evaluation/SplittingStrategy.h>
#include <shogun/base/Parameter.h>
#include <shogun/mathematics/Statistics.h>
#include <shogun/evaluation/CrossValidationOutput.h>
#include <shogun/lib/List.h>

using namespace shogun;

CCrossValidation::CCrossValidation() : CMachineEvaluation()
{
	init();
}

CCrossValidation::CCrossValidation(CMachine* machine, CFeatures* features,
		CLabels* labels, CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterion, bool autolock) :
		CMachineEvaluation(machine, features, labels, splitting_strategy,
		evaluation_criterion, autolock)
{
	init();
}

CCrossValidation::CCrossValidation(CMachine* machine, CLabels* labels,
		CSplittingStrategy* splitting_strategy,
		CEvaluation* evaluation_criterion, bool autolock) :
		CMachineEvaluation(machine, labels, splitting_strategy, evaluation_criterion,
		autolock)
{
	init();
}

CCrossValidation::~CCrossValidation()
{
	SG_UNREF(m_xval_outputs);
}

void CCrossValidation::init()
{
	m_num_runs=1;

	/* do reference counting for output objects */
	m_xval_outputs=new CList(true);

	SG_ADD(&m_num_runs, "num_runs", "Number of repetitions",
			MS_NOT_AVAILABLE);
	SG_ADD((CSGObject**)&m_xval_outputs, "m_xval_outputs", "List of output "
			"classes for intermediade cross-validation results",
			MS_NOT_AVAILABLE);
}

CEvaluationResult* CCrossValidation::evaluate()
{
	SG_DEBUG("entering %s::evaluate()\n", get_name())

	REQUIRE(m_machine, "%s::evaluate() is only possible if a machine is "
			"attached\n", get_name());

	REQUIRE(m_features, "%s::evaluate() is only possible if features are "
			"attached\n", get_name());

	REQUIRE(m_labels, "%s::evaluate() is only possible if labels are "
			"attached\n", get_name());

	/* if for some reason the do_unlock_frag is set, unlock */
	if (m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock=false;
	}

	/* set labels in any case (no locking needs this) */
	m_machine->set_labels(m_labels);

	if (m_autolock)
	{
		/* if machine supports locking try to do so */
		if (m_machine->supports_locking())
		{
			/* only lock if machine is not yet locked */
			if (!m_machine->is_data_locked())
			{
				m_machine->data_lock(m_labels, m_features);
				m_do_unlock=true;
			}
		}
		else
		{
			SG_WARNING("%s does not support locking. Autolocking is skipped. "
					"Set autolock flag to false to get rid of warning.\n",
					m_machine->get_name());
		}
	}

	SGVector<float64_t> results(m_num_runs);

	/* evtl. update xvalidation output class */
	CCrossValidationOutput* current=(CCrossValidationOutput*)
			m_xval_outputs->get_first_element();
	while (current)
	{
		current->init_num_runs(m_num_runs);
		current->init_num_folds(m_splitting_strategy->get_num_subsets());
		current->init_expose_labels(m_labels);
		current->post_init();
		SG_UNREF(current);
		current=(CCrossValidationOutput*)
				m_xval_outputs->get_next_element();
	}

	/* perform all the x-val runs */
	SG_DEBUG("starting %d runs of cross-validation\n", m_num_runs)
	for (index_t i=0; i <m_num_runs; ++i)
	{

		/* evtl. update xvalidation output class */
		current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
		while (current)
		{
			current->update_run_index(i);
			SG_UNREF(current);
			current=(CCrossValidationOutput*)
					m_xval_outputs->get_next_element();
		}

		SG_DEBUG("entering cross-validation run %d \n", i)
		results[i]=evaluate_one_run();
		SG_DEBUG("result of cross-validation run %d is %f\n", i, results[i])
	}

	/* construct evaluation result */
	CCrossValidationResult* result = new CCrossValidationResult();
	result->mean=CStatistics::mean(results);
	if (m_num_runs>1)
		result->std_dev=CStatistics::std_deviation(results);
	else
		result->std_dev=0;

	/* unlock machine if it was locked in this method */
	if (m_machine->is_data_locked() && m_do_unlock)
	{
		m_machine->data_unlock();
		m_do_unlock=false;
	}

	SG_DEBUG("leaving %s::evaluate()\n", get_name())

	SG_REF(result);
	return result;
}

void CCrossValidation::set_num_runs(int32_t num_runs)
{
	if (num_runs <1)
		SG_ERROR("%d is an illegal number of repetitions\n", num_runs)

	m_num_runs=num_runs;
}

float64_t CCrossValidation::evaluate_one_run()
{
	SG_DEBUG("entering %s::evaluate_one_run()\n", get_name())
	index_t num_subsets=m_splitting_strategy->get_num_subsets();

	SG_DEBUG("building index sets for %d-fold cross-validation\n", num_subsets)

	/* build index sets */
	m_splitting_strategy->build_subsets();

	/* results array */
	SGVector<float64_t> results(num_subsets);

	/* different behavior whether data is locked or not */
	if (m_machine->is_data_locked())
	{
		SG_DEBUG("starting locked evaluation\n", get_name())
		/* do actual cross-validation */
		for (index_t i=0; i <num_subsets; ++i)
		{
			/* evtl. update xvalidation output class */
			CCrossValidationOutput* current=(CCrossValidationOutput*)
					m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_fold_index(i);
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* index subset for training, will be freed below */
			SGVector<index_t> inverse_subset_indices =
					m_splitting_strategy->generate_subset_inverse(i);

			/* train machine on training features */
			m_machine->train_locked(inverse_subset_indices);

			/* feature subset for testing */
			SGVector<index_t> subset_indices =
					m_splitting_strategy->generate_subset_indices(i);

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_train_indices(inverse_subset_indices, "\t");
				current->update_trained_machine(m_machine, "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* produce output for desired indices */
			CLabels* result_labels=m_machine->apply_locked(subset_indices);
			SG_REF(result_labels);

			/* set subset for testing labels */
			m_labels->add_subset(subset_indices);

			/* evaluate against own labels */
			m_evaluation_criterion->set_indices(subset_indices);
			results[i]=m_evaluation_criterion->evaluate(result_labels, m_labels);

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_test_indices(subset_indices, "\t");
				current->update_test_result(result_labels, "\t");
				current->update_test_true_result(m_labels, "\t");
				current->post_update_results();
				current->update_evaluation_result(results[i], "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* remove subset to prevent side effects */
			m_labels->remove_subset();

			/* clean up */
			SG_UNREF(result_labels);

			SG_DEBUG("done locked evaluation\n", get_name())
		}
	}
	else
	{
		SG_DEBUG("starting unlocked evaluation\n", get_name())
		/* tell machine to store model internally
		 * (otherwise changing subset of features will kaboom the classifier) */
		m_machine->set_store_model_features(true);

		/* do actual cross-validation */
		for (index_t i=0; i <num_subsets; ++i)
		{
			/* evtl. update xvalidation output class */
			CCrossValidationOutput* current=(CCrossValidationOutput*)
					m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_fold_index(i);
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* set feature subset for training */
			SGVector<index_t> inverse_subset_indices=
					m_splitting_strategy->generate_subset_inverse(i);
			m_features->add_subset(inverse_subset_indices);
			for (index_t p=0; p<m_features->get_num_preprocessors(); p++)
			{
				CPreprocessor* preprocessor = m_features->get_preprocessor(p);
				preprocessor->init(m_features);
				SG_UNREF(preprocessor);
			}

			/* set label subset for training */
			m_labels->add_subset(inverse_subset_indices);

			SG_DEBUG("training set %d:\n", i)
			if (io->get_loglevel()==MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(inverse_subset_indices.vector,
						inverse_subset_indices.vlen, "training indices");
			}

			/* train machine on training features and remove subset */
			SG_DEBUG("starting training\n")
			m_machine->train(m_features);
			SG_DEBUG("finished training\n")

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_train_indices(inverse_subset_indices, "\t");
				current->update_trained_machine(m_machine, "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			m_features->remove_subset();
			m_labels->remove_subset();

			/* set feature subset for testing (subset method that stores pointer) */
			SGVector<index_t> subset_indices =
					m_splitting_strategy->generate_subset_indices(i);
			m_features->add_subset(subset_indices);

			/* set label subset for testing */
			m_labels->add_subset(subset_indices);

			SG_DEBUG("test set %d:\n", i)
			if (io->get_loglevel()==MSG_DEBUG)
			{
				SGVector<index_t>::display_vector(subset_indices.vector,
						subset_indices.vlen, "test indices");
			}

			/* apply machine to test features and remove subset */
			SG_DEBUG("starting evaluation\n")
			SG_DEBUG("%p\n", m_features)
			CLabels* result_labels=m_machine->apply(m_features);
			SG_DEBUG("finished evaluation\n")
			m_features->remove_subset();
			SG_REF(result_labels);

			/* evaluate */
			results[i]=m_evaluation_criterion->evaluate(result_labels, m_labels);
			SG_DEBUG("result on fold %d is %f\n", i, results[i])

			/* evtl. update xvalidation output class */
			current=(CCrossValidationOutput*)m_xval_outputs->get_first_element();
			while (current)
			{
				current->update_test_indices(subset_indices, "\t");
				current->update_test_result(result_labels, "\t");
				current->update_test_true_result(m_labels, "\t");
				current->post_update_results();
				current->update_evaluation_result(results[i], "\t");
				SG_UNREF(current);
				current=(CCrossValidationOutput*)
						m_xval_outputs->get_next_element();
			}

			/* clean up, remove subsets */
			SG_UNREF(result_labels);
			m_labels->remove_subset();
		}

		SG_DEBUG("done unlocked evaluation\n", get_name())
	}

	/* build arithmetic mean of results */
	float64_t mean=CStatistics::mean(results);

	SG_DEBUG("leaving %s::evaluate_one_run()\n", get_name())
	return mean;
}

void CCrossValidation::add_cross_validation_output(
			CCrossValidationOutput* cross_validation_output)
{
	m_xval_outputs->append_element(cross_validation_output);
}
<|endoftext|>