<commit_before>
#include <cmath>
#include "ofxPS3EyeGrabber.h"
#include "beamCamera.h"
#include "settings.h"

BeamCamera::BeamCamera(int deviceID, const string name) : cam_name(name)
{
    grabber.setGrabber(std::make_shared<ofxPS3EyeGrabber>());
    grabber.setDeviceID(deviceID);

    grabber.setPixelFormat(OF_PIXELS_RGB);
    grabber.setDesiredFrameRate(FRAMERATE);
    grabber.setup(WIDTH, HEIGHT);

    //PS3 Eye specific settings
    grabber.getGrabber<ofxPS3EyeGrabber>()->setAutogain(false);
    grabber.getGrabber<ofxPS3EyeGrabber>()->setAutoWhiteBalance(false);

    //allocate our working surfaces
    raw.allocate(WIDTH, HEIGHT);
    grey_bg.allocate(WIDTH, HEIGHT);
    grey_working.allocate(WIDTH, HEIGHT);
    grey_beam_working.allocate(WIDTH, HEIGHT);

    threshold = INIT_THRESHOLD;
    learning = NOT_LEARNING;

    load_data();
}

BeamCamera::~BeamCamera()
{
    //release our surfaces
    raw.clear();
    grey_bg.clear();
    grey_working.clear();
    grey_beam_working.clear();

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
            delete beam;
    }
}

void BeamCamera::load_data()
{
    ofDirectory dir(cam_name);
    if(!dir.exists())
    {
        dir.create();
        return;
    }

    dir.allowExt(IMAGE_FORMAT);
    dir.listDir();

    for(ofFile file : dir)
    {
        ofImage img;

        if(file.getBaseName() == BACKGROUND_FILE)
        {
            img.load(file);
            grey_bg = img;
        }
        else
        {
            int beam = ofToInt(file.getBaseName());

            if(beam < 0)
                continue;

            img.load(file);
            //make sure our mask array has a spot for this beam
            if(beam >= (int) beams.size())
                beams.resize(beam + 1, NULL);

            beams[beam] = new BeamDescriptor(img);
        }
    }
}

void BeamCamera::update()
{
    grabber.update();

    if(grabber.isFrameNew())
    {
        raw.setFromPixels(grabber.getPixels());

        //perform background subtraction
        grey_working = raw;
        cvSub(grey_working.getCvImage(),
              grey_bg.getCvImage(),
              grey_working.getCvImage());
        grey_working.flagImageChanged();

        //apply our intensity threshold
        grey_working.threshold(threshold);

        if(is_learning() && beams[learning] != NULL)
        {
            beams[learning]->add_to_mask(grey_working);
        }
    }
}

void BeamCamera::draw_raw(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    raw.draw(x, y);
}

void BeamCamera::draw_working(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    grey_working.draw(x, y);
}

void BeamCamera::draw_masks(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    cvZero(grey_beam_working.getCvImage());

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
        {
            cvOr(beam->mask.getCvImage(),
                 grey_beam_working.getCvImage(),
                 grey_beam_working.getCvImage());
        }
    }

    grey_beam_working.flagImageChanged();
    grey_beam_working.draw(x, y);

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
        {
            ofPushStyle();
            beam->blob.draw(x, y);
            ofSetHexColor(0xFF0000);
            ofDrawCircle(beam->top.x, beam->top.y, 3);
            ofSetHexColor(0x0000FF);
            ofDrawCircle(beam->bottom.x, beam->bottom.y, 3);
            ofPopStyle();
        }
    }
}

int BeamCamera::get_threshold()
{
    return threshold;
}

void BeamCamera::adjust_threshold(int delta)
{
    //clamp to [0, 255]
    int new_thresh = threshold + delta;
    if(new_thresh < 0) new_thresh = 0;
    else if(new_thresh > 255) new_thresh = 255;
    threshold = new_thresh;
}

void BeamCamera::learn_background()
{
    grey_bg = raw;

    //save the background to a file
    ofImage background;
    background.setFromPixels(grey_bg.getPixels());
    background.setImageType(OF_IMAGE_GRAYSCALE);

    stringstream filename;
    filename << cam_name << "/" << BACKGROUND_FILE << "." << IMAGE_FORMAT;
    background.save(filename.str());
}

bool BeamCamera::is_learning()
{
    return learning != NOT_LEARNING;
}

void BeamCamera::start_learning_beam(int beam)
{
    //if we were learning before, stop, before moving on
    if(learning != NOT_LEARNING)
        stop_learning_beam();

    ofLog() << cam_name << " started learning beam " << beam;
    new_beam(beam);
    learning = beam;
}

void BeamCamera::stop_learning_beam()
{
    //can't stop a stopped learning
    if(learning == NOT_LEARNING)
        return;

    //compute and save the minimum area rect
    BeamDescriptor* beam = beams[learning];
    beam->learn();

    //save the mask to a file
    ofImage mask;
    mask.setFromPixels(beam->mask.getPixels());
    mask.setImageType(OF_IMAGE_GRAYSCALE);

    stringstream filename;
    filename << cam_name << "/" << learning << "." << IMAGE_FORMAT;
    mask.save(filename.str());

    ofLog() << cam_name << " stopped learning beam " << learning;
    learning = NOT_LEARNING;
}

vector<Hand> BeamCamera::hands_for_beam(int beam)
{
    vector<Hand> all_hands;
    vector<Hand> hands_with_velocity;

    //return empty array if this camera doesn't handle a beam
    if(!mask_exists(beam))
        return vector<Hand>();

    //apply the mask that corresponds to this beam
    cvAnd(grey_working.getCvImage(),
          beams[beam]->mask.getCvImage(),
          grey_beam_working.getCvImage());
    grey_beam_working.flagImageChanged();

    //find our hand blobs
    contourFinder.findContours(grey_beam_working,
                               BLOB_AREA_MIN,
                               BLOB_AREA_MAX,
                               N_BLOBS,
                               false); //find holes

    //contourFinder.blobs is now populated

    for(ofxCvBlob blob : contourFinder.blobs)
    {
        Hand hand = beams[beam]->blob_to_hand(blob);

        //figure out where this hand was in the past
        for(Hand& old_hand : beams[beam]->old_hands)
        {
            if(hand.same_hand_as(old_hand))
            {
                hand.compute_velocity(old_hand);
                hands_with_velocity.push_back(hand);
                break;
            }
        }

        all_hands.push_back(hand);
    }

    beams[beam]->old_hands = all_hands;

    return hands_with_velocity;
}

bool BeamCamera::mask_exists(int beam)
{
    return (beam < (int)beams.size()) && (beams[beam] != NULL);
}

bool BeamCamera::handles_beam(int beam)
{
    return mask_exists(beam) && beams[beam]->found_beam();
}

void BeamCamera::new_beam(int beam)
{
    //make sure our mask array has a spot for this beam
    if(beam >= (int) beams.size())
        beams.resize(beam + 1, NULL);

    if(mask_exists(beam))
        beams[beam]->zero();
    else
        beams[beam] = new BeamDescriptor();
}
<commit_msg>blur the incoming image, and don't wait for velocities<commit_after>
#include <cmath>
#include "ofxPS3EyeGrabber.h"
#include "beamCamera.h"
#include "settings.h"

BeamCamera::BeamCamera(int deviceID, const string name) : cam_name(name)
{
    grabber.setGrabber(std::make_shared<ofxPS3EyeGrabber>());
    grabber.setDeviceID(deviceID);

    grabber.setPixelFormat(OF_PIXELS_RGB);
    grabber.setDesiredFrameRate(FRAMERATE);
    grabber.setup(WIDTH, HEIGHT);

    //PS3 Eye specific settings
    grabber.getGrabber<ofxPS3EyeGrabber>()->setAutogain(false);
    grabber.getGrabber<ofxPS3EyeGrabber>()->setAutoWhiteBalance(false);

    //allocate our working surfaces
    raw.allocate(WIDTH, HEIGHT);
    grey_bg.allocate(WIDTH, HEIGHT);
    grey_working.allocate(WIDTH, HEIGHT);
    grey_beam_working.allocate(WIDTH, HEIGHT);

    threshold = INIT_THRESHOLD;
    learning = NOT_LEARNING;

    load_data();
}

BeamCamera::~BeamCamera()
{
    //release our surfaces
    raw.clear();
    grey_bg.clear();
    grey_working.clear();
    grey_beam_working.clear();

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
            delete beam;
    }
}

void BeamCamera::load_data()
{
    ofDirectory dir(cam_name);
    if(!dir.exists())
    {
        dir.create();
        return;
    }

    dir.allowExt(IMAGE_FORMAT);
    dir.listDir();

    for(ofFile file : dir)
    {
        ofImage img;

        if(file.getBaseName() == BACKGROUND_FILE)
        {
            img.load(file);
            grey_bg = img;
        }
        else
        {
            int beam = ofToInt(file.getBaseName());

            if(beam < 0)
                continue;

            img.load(file);
            //make sure our mask array has a spot for this beam
            if(beam >= (int) beams.size())
                beams.resize(beam + 1, NULL);

            beams[beam] = new BeamDescriptor(img);
        }
    }
}

void BeamCamera::update()
{
    grabber.update();

    if(grabber.isFrameNew())
    {
        raw.setFromPixels(grabber.getPixels());

        //perform background subtraction
        grey_working = raw;
        cvSub(grey_working.getCvImage(),
              grey_bg.getCvImage(),
              grey_working.getCvImage());
        grey_working.flagImageChanged();
        grey_working.blur(5);
        //apply our intensity threshold
        grey_working.threshold(threshold);
        grey_working.dilate();

        if(is_learning() && beams[learning] != NULL)
        {
            beams[learning]->add_to_mask(grey_working);
        }
    }
}

void BeamCamera::draw_raw(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    raw.draw(x, y);
}

void BeamCamera::draw_working(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    grey_working.draw(x, y);
}

void BeamCamera::draw_masks(int x, int y)
{
    ofSetHexColor(0xFFFFFF);
    cvZero(grey_beam_working.getCvImage());

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
        {
            cvOr(beam->mask.getCvImage(),
                 grey_beam_working.getCvImage(),
                 grey_beam_working.getCvImage());
        }
    }

    grey_beam_working.flagImageChanged();
    grey_beam_working.draw(x, y);

    for(BeamDescriptor* beam : beams)
    {
        if(beam != NULL)
        {
            ofPushStyle();
            beam->blob.draw(x, y);
            ofSetHexColor(0xFF0000);
            ofDrawCircle(beam->top.x, beam->top.y, 3);
            ofSetHexColor(0x0000FF);
            ofDrawCircle(beam->bottom.x, beam->bottom.y, 3);
            ofPopStyle();
        }
    }
}

int BeamCamera::get_threshold()
{
    return threshold;
}

void BeamCamera::adjust_threshold(int delta)
{
    //clamp to [0, 255]
    int new_thresh = threshold + delta;
    if(new_thresh < 0) new_thresh = 0;
    else if(new_thresh > 255) new_thresh = 255;
    threshold = new_thresh;
}

void BeamCamera::learn_background()
{
    grey_bg = raw;

    //save the background to a file
    ofImage background;
    background.setFromPixels(grey_bg.getPixels());
    background.setImageType(OF_IMAGE_GRAYSCALE);

    stringstream filename;
    filename << cam_name << "/" << BACKGROUND_FILE << "." << IMAGE_FORMAT;
    background.save(filename.str());
}

bool BeamCamera::is_learning()
{
    return learning != NOT_LEARNING;
}

void BeamCamera::start_learning_beam(int beam)
{
    //if we were learning before, stop, before moving on
    if(learning != NOT_LEARNING)
        stop_learning_beam();

    ofLog() << cam_name << " started learning beam " << beam;
    new_beam(beam);
    learning = beam;
}

void BeamCamera::stop_learning_beam()
{
    //can't stop a stopped learning
    if(learning == NOT_LEARNING)
        return;

    //compute and save the minimum area rect
    BeamDescriptor* beam = beams[learning];
    beam->learn();

    //save the mask to a file
    ofImage mask;
    mask.setFromPixels(beam->mask.getPixels());
    mask.setImageType(OF_IMAGE_GRAYSCALE);

    stringstream filename;
    filename << cam_name << "/" << learning << "." << IMAGE_FORMAT;
    mask.save(filename.str());

    ofLog() << cam_name << " stopped learning beam " << learning;
    learning = NOT_LEARNING;
}

vector<Hand> BeamCamera::hands_for_beam(int beam)
{
    vector<Hand> all_hands;
    vector<Hand> hands_with_velocity;

    //return empty array if this camera doesn't handle a beam
    if(!mask_exists(beam))
        return vector<Hand>();

    //apply the mask that corresponds to this beam
    cvAnd(grey_working.getCvImage(),
          beams[beam]->mask.getCvImage(),
          grey_beam_working.getCvImage());
    grey_beam_working.flagImageChanged();

    //find our hand blobs
    contourFinder.findContours(grey_beam_working,
                               BLOB_AREA_MIN,
                               BLOB_AREA_MAX,
                               N_BLOBS,
                               false); //find holes

    //contourFinder.blobs is now populated

    for(ofxCvBlob blob : contourFinder.blobs)
    {
        Hand hand = beams[beam]->blob_to_hand(blob);

        //figure out where this hand was in the past
        for(Hand& old_hand : beams[beam]->old_hands)
        {
            if(hand.same_hand_as(old_hand))
            {
                hand.compute_velocity(old_hand);
                hands_with_velocity.push_back(hand);
                break;
            }
        }

        all_hands.push_back(hand);
    }

    beams[beam]->old_hands = all_hands;

    //return hands_with_velocity;
    return all_hands;
}

bool BeamCamera::mask_exists(int beam)
{
    return (beam < (int)beams.size()) && (beams[beam] != NULL);
}

bool BeamCamera::handles_beam(int beam)
{
    return mask_exists(beam) && beams[beam]->found_beam();
}

void BeamCamera::new_beam(int beam)
{
    //make sure our mask array has a spot for this beam
    if(beam >= (int) beams.size())
        beams.resize(beam + 1, NULL);

    if(mask_exists(beam))
        beams[beam]->zero();
    else
        beams[beam] = new BeamDescriptor();
}
<|endoftext|>


<commit_before>/*--------------------------------------------------------------------------
Copyright (c) 2014, The Linux Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of The Linux Foundation nor
      the names of its contributors may be used to endorse or promote
      products derived from this software without specific prior written
      permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include "CompassSensor.h"
#include "sensors.h"

#define FETCH_FULL_EVENT_BEFORE_RETURN	1
#define IGNORE_EVENT_TIME				10000000

#define EVENT_TYPE_MAG_X		ABS_X
#define EVENT_TYPE_MAG_Y		ABS_Y
#define EVENT_TYPE_MAG_Z		ABS_Z
#define EVENT_TYPE_MAG_STATUS	ABS_MISC

#define EVENT_TYPE_YAW			ABS_X
#define EVENT_TYPE_PITCH		ABS_Y
#define EVENT_TYPE_ROLL			ABS_Z

// conversion of magnetic data to uT units
#define CONVERT_MAG				(1.0f/16.0f)
#define CALIBRATE_ERROR_MAGIC		0.000314

/*****************************************************************************/
CompassSensor::CompassSensor(struct SensorContext *context)
	: SensorBase(NULL, NULL, context),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  mEnabledTime(0),
	  res(CONVERT_MAG)
{
	int handle = -1;

	res = context->sensor->resolution;

	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = context->sensor->handle;
	mPendingEvent.type = SENSOR_TYPE_MAGNETIC_FIELD;
	mPendingEvent.magnetic.status = SENSOR_STATUS_UNRELIABLE;

	data_fd = context->data_fd;
	strlcpy(input_sysfs_path, context->enable_path, sizeof(input_sysfs_path));
	input_sysfs_path_len = strlen(input_sysfs_path);

	enable(0, 1);
}

CompassSensor::~CompassSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int CompassSensor::enable(int32_t, int en) {
	int flags = en ? 1 : 0;
	compass_algo_args arg;
	arg.common.enable = flags;
	char propBuf[PROPERTY_VALUE_MAX];

	property_get("sensors.compass.loopback", propBuf, "0");
	if (strcmp(propBuf, "1") == 0) {
		ALOGE("sensors.compass.loopback is set");
		mEnabled = flags;
		mEnabledTime = 0;
		return 0;
	}

	if (flags != mEnabled) {
		int fd;

		if ((algo != NULL) && (algo->methods->config != NULL)) {
			if (algo->methods->config(CMD_ENABLE, (sensor_algo_args*)&arg)) {
				ALOGW("Calling enable config failed for compass");
			}
		}

		strlcpy(&input_sysfs_path[input_sysfs_path_len],
				SYSFS_ENABLE, SYSFS_MAXLEN);
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
				mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			return 0;
		}
		ALOGE("CompassSensor: failed to open %s", input_sysfs_path);
		return -1;
	}
	return 0;
}

bool CompassSensor::hasPendingEvents() const {
	return mHasPendingEvent || mHasPendingMetadata;
}

int CompassSensor::setDelay(int32_t, int64_t delay_ns)
{
	int fd;
	int delay_ms = delay_ns / 1000000;
	compass_algo_args arg;
	arg.common.delay_ms = delay_ms;
	char propBuf[PROPERTY_VALUE_MAX];
	property_get("sensors.compass.loopback", propBuf, "0");
	if (strcmp(propBuf, "1") == 0) {
		ALOGE("sensors.compass.loopback is set");
		return 0;
	}

	if ((algo != NULL) && (algo->methods->config != NULL)) {
		if (algo->methods->config(CMD_DELAY, (sensor_algo_args*)&arg)) {
			ALOGW("Calling delay config failed for compass");
		}
	}

	strlcpy(&input_sysfs_path[input_sysfs_path_len],
			SYSFS_POLL_DELAY, SYSFS_MAXLEN);
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		snprintf(buf, sizeof(buf), "%d", delay_ms);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int CompassSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	if (mHasPendingMetadata) {
		mHasPendingMetadata--;
		meta_data.timestamp = getTimestamp();
		*data = meta_data;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;
	sensors_event_t raw, result;

#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			float value = event->value;
			if (event->code == EVENT_TYPE_MAG_X) {
				mPendingEvent.magnetic.x = value * res;
			} else if (event->code == EVENT_TYPE_MAG_Y) {
				mPendingEvent.magnetic.y = value * res;
			} else if (event->code == EVENT_TYPE_MAG_Z) {
				mPendingEvent.magnetic.z = value * res;
			}
		} else if (type == EV_SYN) {
			switch (event->code) {
				case SYN_TIME_SEC:
					mUseAbsTimeStamp = true;
					report_time = event->value*1000000000LL;
					break;
				case SYN_TIME_NSEC:
					mUseAbsTimeStamp = true;
					mPendingEvent.timestamp = report_time+event->value;
					break;
				case SYN_REPORT:
					if (mUseAbsTimeStamp != true) {
						mPendingEvent.timestamp = timevalToNano(event->time);
					}
					if (mEnabled) {
						raw = mPendingEvent;

						if (algo != NULL) {
							if (algo->methods->convert(&raw, &result, NULL)) {
								ALOGE("Calibration failed.");
								result.magnetic.x = CALIBRATE_ERROR_MAGIC;
								result.magnetic.y = CALIBRATE_ERROR_MAGIC;
								result.magnetic.z = CALIBRATE_ERROR_MAGIC;
								result.magnetic.status = 0;
							}
						} else {
							result = raw;
						}

						*data = result;
						data->version = sizeof(sensors_event_t);
						data->sensor = mPendingEvent.sensor;
						data->type = SENSOR_TYPE_MAGNETIC_FIELD;
						data->timestamp = mPendingEvent.timestamp;

						/* The raw data is stored inside sensors_event_t.data after
						 * sensors_event_t.magnetic. Notice that the raw data is
						 * required to composite the virtual sensor uncalibrated
						 * magnetic field sensor.
						 *
						 * data[0~2]: calibrated magnetic field data.
						 * data[3]: magnetic field data accuracy.
						 * data[4~6]: uncalibrated magnetic field data.
						 */
						data->data[4] = mPendingEvent.data[0];
						data->data[5] = mPendingEvent.data[1];
						data->data[6] = mPendingEvent.data[2];

						data++;
						numEventReceived++;
						count--;
					}
					break;
			}
		} else {
			ALOGE("CompassSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

#if FETCH_FULL_EVENT_BEFORE_RETURN
	/* if we didn't read a complete event, see if we can fill and
	   try again instead of returning with nothing and redoing poll. */
	if (numEventReceived == 0 && mEnabled == 1) {
		n = mInputReader.fill(data_fd);
		if (n)
			goto again;
	}
#endif

	return numEventReceived;
}

<commit_msg>don't report bogus mag values when uncalibrated<commit_after>/*--------------------------------------------------------------------------
Copyright (c) 2014, The Linux Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of The Linux Foundation nor
      the names of its contributors may be used to endorse or promote
      products derived from this software without specific prior written
      permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------*/

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include "CompassSensor.h"
#include "sensors.h"

#define FETCH_FULL_EVENT_BEFORE_RETURN	1
#define IGNORE_EVENT_TIME				10000000

#define EVENT_TYPE_MAG_X		ABS_X
#define EVENT_TYPE_MAG_Y		ABS_Y
#define EVENT_TYPE_MAG_Z		ABS_Z
#define EVENT_TYPE_MAG_STATUS	ABS_MISC

#define EVENT_TYPE_YAW			ABS_X
#define EVENT_TYPE_PITCH		ABS_Y
#define EVENT_TYPE_ROLL			ABS_Z

// conversion of magnetic data to uT units
#define CONVERT_MAG				(1.0f/16.0f)

/*****************************************************************************/
CompassSensor::CompassSensor(struct SensorContext *context)
	: SensorBase(NULL, NULL, context),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  mEnabledTime(0),
	  res(CONVERT_MAG)
{
	int handle = -1;

	res = context->sensor->resolution;

	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = context->sensor->handle;
	mPendingEvent.type = SENSOR_TYPE_MAGNETIC_FIELD;
	mPendingEvent.magnetic.status = SENSOR_STATUS_UNRELIABLE;

	data_fd = context->data_fd;
	strlcpy(input_sysfs_path, context->enable_path, sizeof(input_sysfs_path));
	input_sysfs_path_len = strlen(input_sysfs_path);

	enable(0, 1);
}

CompassSensor::~CompassSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int CompassSensor::enable(int32_t, int en) {
	int flags = en ? 1 : 0;
	compass_algo_args arg;
	arg.common.enable = flags;
	char propBuf[PROPERTY_VALUE_MAX];

	property_get("sensors.compass.loopback", propBuf, "0");
	if (strcmp(propBuf, "1") == 0) {
		ALOGE("sensors.compass.loopback is set");
		mEnabled = flags;
		mEnabledTime = 0;
		return 0;
	}

	if (flags != mEnabled) {
		int fd;

		if ((algo != NULL) && (algo->methods->config != NULL)) {
			if (algo->methods->config(CMD_ENABLE, (sensor_algo_args*)&arg)) {
				ALOGW("Calling enable config failed for compass");
			}
		}

		strlcpy(&input_sysfs_path[input_sysfs_path_len],
				SYSFS_ENABLE, SYSFS_MAXLEN);
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
				mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			return 0;
		}
		ALOGE("CompassSensor: failed to open %s", input_sysfs_path);
		return -1;
	}
	return 0;
}

bool CompassSensor::hasPendingEvents() const {
	return mHasPendingEvent || mHasPendingMetadata;
}

int CompassSensor::setDelay(int32_t, int64_t delay_ns)
{
	int fd;
	int delay_ms = delay_ns / 1000000;
	compass_algo_args arg;
	arg.common.delay_ms = delay_ms;
	char propBuf[PROPERTY_VALUE_MAX];
	property_get("sensors.compass.loopback", propBuf, "0");
	if (strcmp(propBuf, "1") == 0) {
		ALOGE("sensors.compass.loopback is set");
		return 0;
	}

	if ((algo != NULL) && (algo->methods->config != NULL)) {
		if (algo->methods->config(CMD_DELAY, (sensor_algo_args*)&arg)) {
			ALOGW("Calling delay config failed for compass");
		}
	}

	strlcpy(&input_sysfs_path[input_sysfs_path_len],
			SYSFS_POLL_DELAY, SYSFS_MAXLEN);
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		snprintf(buf, sizeof(buf), "%d", delay_ms);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int CompassSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	if (mHasPendingMetadata) {
		mHasPendingMetadata--;
		meta_data.timestamp = getTimestamp();
		*data = meta_data;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;
	sensors_event_t raw, result;

#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			float value = event->value;
			if (event->code == EVENT_TYPE_MAG_X) {
				mPendingEvent.magnetic.x = value * res;
			} else if (event->code == EVENT_TYPE_MAG_Y) {
				mPendingEvent.magnetic.y = value * res;
			} else if (event->code == EVENT_TYPE_MAG_Z) {
				mPendingEvent.magnetic.z = value * res;
			}
		} else if (type == EV_SYN) {
			switch (event->code) {
				case SYN_TIME_SEC:
					mUseAbsTimeStamp = true;
					report_time = event->value*1000000000LL;
					break;
				case SYN_TIME_NSEC:
					mUseAbsTimeStamp = true;
					mPendingEvent.timestamp = report_time+event->value;
					break;
				case SYN_REPORT:
					if (mUseAbsTimeStamp != true) {
						mPendingEvent.timestamp = timevalToNano(event->time);
					}
					if (mEnabled) {
						raw = mPendingEvent;

						if (algo != NULL) {
							if (algo->methods->convert(&raw, &result, NULL)) {
								ALOGW("Calibration in progress...");
								result = raw;
								result.magnetic.status = SENSOR_STATUS_UNRELIABLE;
							}
						} else {
							result = raw;
						}

						*data = result;
						data->version = sizeof(sensors_event_t);
						data->sensor = mPendingEvent.sensor;
						data->type = SENSOR_TYPE_MAGNETIC_FIELD;
						data->timestamp = mPendingEvent.timestamp;

						/* The raw data is stored inside sensors_event_t.data after
						 * sensors_event_t.magnetic. Notice that the raw data is
						 * required to composite the virtual sensor uncalibrated
						 * magnetic field sensor.
						 *
						 * data[0~2]: calibrated magnetic field data.
						 * data[3]: magnetic field data accuracy.
						 * data[4~6]: uncalibrated magnetic field data.
						 */
						data->data[4] = mPendingEvent.data[0];
						data->data[5] = mPendingEvent.data[1];
						data->data[6] = mPendingEvent.data[2];

						data++;
						numEventReceived++;
						count--;
					}
					break;
			}
		} else {
			ALOGE("CompassSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

#if FETCH_FULL_EVENT_BEFORE_RETURN
	/* if we didn't read a complete event, see if we can fill and
	   try again instead of returning with nothing and redoing poll. */
	if (numEventReceived == 0 && mEnabled == 1) {
		n = mInputReader.fill(data_fd);
		if (n)
			goto again;
	}
#endif

	return numEventReceived;
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cassert>

#include "base/trace.hh"
#include "debug/RubyNetwork.hh"
#include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/BasicLink.hh"
#include "mem/ruby/network/Topology.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"

using namespace std;

const int INFINITE_LATENCY = 10000; // Yes, this is a big hack

// Note: In this file, we use the first 2*m_nodes SwitchIDs to
// represent the input and output endpoint links.  These really are
// not 'switches', as they will not have a Switch object allocated for
// them. The first m_nodes SwitchIDs are the links into the network,
// the second m_nodes set of SwitchIDs represent the the output queues
// of the network.

// Helper functions based on chapter 29 of Cormen et al.
void extend_shortest_path(Matrix& current_dist, Matrix& latencies,
    Matrix& inter_switches);
Matrix shortest_path(const Matrix& weights, Matrix& latencies,
    Matrix& inter_switches);
bool link_is_shortest_path_to_node(SwitchID src, SwitchID next,
    SwitchID final, const Matrix& weights, const Matrix& dist);
NetDest shortest_path_to_node(SwitchID src, SwitchID next,
    const Matrix& weights, const Matrix& dist);

Topology::Topology(uint32_t num_routers, vector<BasicExtLink *> ext_links,
                   vector<BasicIntLink *> int_links)
    : m_number_of_switches(num_routers)
{

    // initialize component latencies record
    m_component_latencies.resize(0);
    m_component_inter_switches.resize(0);

    // Total nodes/controllers in network
    // Must make sure this is called after the State Machine constructors
    m_nodes = MachineType_base_number(MachineType_NUM);
    assert(m_nodes > 1);

    if (m_nodes != ext_links.size()) {
        fatal("m_nodes (%d) != ext_links vector length (%d)\n",
              m_nodes, ext_links.size());
    }

    // analyze both the internal and external links, create data structures
    // Note that the python created links are bi-directional, but that the
    // topology and networks utilize uni-directional links.  Thus each
    // BasicLink is converted to two calls to add link, on for each direction
    for (vector<BasicExtLink*>::const_iterator i = ext_links.begin();
         i != ext_links.end(); ++i) {
        BasicExtLink *ext_link = (*i);
        AbstractController *abs_cntrl = ext_link->params()->ext_node;
        BasicRouter *router = ext_link->params()->int_node;

        // Store the ExtLink pointers for later
        m_ext_link_vector.push_back(ext_link);

        int ext_idx1 = abs_cntrl->params()->cntrl_id;
        int ext_idx2 = ext_idx1 + m_nodes;
        int int_idx = router->params()->router_id + 2*m_nodes;

        // create the internal uni-directional links in both directions
        //   the first direction is marked: In
        addLink(ext_idx1, int_idx, ext_link, LinkDirection_In);
        //   the first direction is marked: Out
        addLink(int_idx, ext_idx2, ext_link, LinkDirection_Out);
    }

    for (vector<BasicIntLink*>::const_iterator i = int_links.begin();
         i != int_links.end(); ++i) {
        BasicIntLink *int_link = (*i);
        BasicRouter *router_a = int_link->params()->node_a;
        BasicRouter *router_b = int_link->params()->node_b;

        // Store the IntLink pointers for later
        m_int_link_vector.push_back(int_link);

        int a = router_a->params()->router_id + 2*m_nodes;
        int b = router_b->params()->router_id + 2*m_nodes;

        // create the internal uni-directional links in both directions
        //   the first direction is marked: In
        addLink(a, b, int_link, LinkDirection_In);
        //   the second direction is marked: Out
        addLink(b, a, int_link, LinkDirection_Out);
    }
}

void
Topology::createLinks(Network *net)
{
    // Find maximum switchID
    SwitchID max_switch_id = 0;
    for (LinkMap::const_iterator i = m_link_map.begin();
         i != m_link_map.end(); ++i) {
        std::pair<int, int> src_dest = (*i).first;
        max_switch_id = max(max_switch_id, src_dest.first);
        max_switch_id = max(max_switch_id, src_dest.second);
    }

    // Initialize weight, latency, and inter switched vectors
    Matrix topology_weights;
    int num_switches = max_switch_id+1;
    topology_weights.resize(num_switches);
    m_component_latencies.resize(num_switches);
    m_component_inter_switches.resize(num_switches);

    for (int i = 0; i < topology_weights.size(); i++) {
        topology_weights[i].resize(num_switches);
        m_component_latencies[i].resize(num_switches);
        m_component_inter_switches[i].resize(num_switches);

        for (int j = 0; j < topology_weights[i].size(); j++) {
            topology_weights[i][j] = INFINITE_LATENCY;

            // initialize to invalid values
            m_component_latencies[i][j] = -1;

            // initially assume direct connections / no intermediate
            // switches between components
            m_component_inter_switches[i][j] = 0;
        }
    }

    // Set identity weights to zero
    for (int i = 0; i < topology_weights.size(); i++) {
        topology_weights[i][i] = 0;
    }

    // Fill in the topology weights and bandwidth multipliers
    for (LinkMap::const_iterator i = m_link_map.begin();
         i != m_link_map.end(); ++i) {
        std::pair<int, int> src_dest = (*i).first;
        BasicLink* link = (*i).second.link;
        int src = src_dest.first;
        int dst = src_dest.second;
        m_component_latencies[src][dst] = link->m_latency;
        topology_weights[src][dst] = link->m_weight;
    }

    // Walk topology and hookup the links
    Matrix dist = shortest_path(topology_weights, m_component_latencies,
        m_component_inter_switches);
    for (int i = 0; i < topology_weights.size(); i++) {
        for (int j = 0; j < topology_weights[i].size(); j++) {
            int weight = topology_weights[i][j];
            if (weight > 0 && weight != INFINITE_LATENCY) {
                NetDest destination_set =
                        shortest_path_to_node(i, j, topology_weights, dist);
                makeLink(net, i, j, destination_set);
            }
        }
    }
}

void
Topology::addLink(SwitchID src, SwitchID dest, BasicLink* link,
                  LinkDirection dir)
{
    assert(src <= m_number_of_switches+m_nodes+m_nodes);
    assert(dest <= m_number_of_switches+m_nodes+m_nodes);

    std::pair<int, int> src_dest_pair;
    LinkEntry link_entry;

    src_dest_pair.first = src;
    src_dest_pair.second = dest;
    link_entry.direction = dir;
    link_entry.link = link;
    m_link_map[src_dest_pair] = link_entry;
}

void
Topology::makeLink(Network *net, SwitchID src, SwitchID dest,
                   const NetDest& routing_table_entry)
{
    // Make sure we're not trying to connect two end-point nodes
    // directly together
    assert(src >= 2 * m_nodes || dest >= 2 * m_nodes);

    std::pair<int, int> src_dest;
    LinkEntry link_entry;

    if (src < m_nodes) {
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeInLink(src, dest - (2 * m_nodes), link_entry.link,
                        link_entry.direction, routing_table_entry);
    } else if (dest < 2*m_nodes) {
        assert(dest >= m_nodes);
        NodeID node = dest - m_nodes;
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeOutLink(src - (2 * m_nodes), node, link_entry.link,
                         link_entry.direction, routing_table_entry);
    } else {
        assert((src >= 2 * m_nodes) && (dest >= 2 * m_nodes));
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeInternalLink(src - (2 * m_nodes), dest - (2 * m_nodes),
                              link_entry.link, link_entry.direction,
                              routing_table_entry);
    }
}

// The following all-pairs shortest path algorithm is based on the
// discussion from Cormen et al., Chapter 26.1.
void
extend_shortest_path(Matrix& current_dist, Matrix& latencies,
    Matrix& inter_switches)
{
    bool change = true;
    int nodes = current_dist.size();

    while (change) {
        change = false;
        for (int i = 0; i < nodes; i++) {
            for (int j = 0; j < nodes; j++) {
                int minimum = current_dist[i][j];
                int previous_minimum = minimum;
                int intermediate_switch = -1;
                for (int k = 0; k < nodes; k++) {
                    minimum = min(minimum,
                        current_dist[i][k] + current_dist[k][j]);
                    if (previous_minimum != minimum) {
                        intermediate_switch = k;
                        inter_switches[i][j] =
                            inter_switches[i][k] +
                            inter_switches[k][j] + 1;
                    }
                    previous_minimum = minimum;
                }
                if (current_dist[i][j] != minimum) {
                    change = true;
                    current_dist[i][j] = minimum;
                    assert(intermediate_switch >= 0);
                    assert(intermediate_switch < latencies[i].size());
                    latencies[i][j] = latencies[i][intermediate_switch] +
                        latencies[intermediate_switch][j];
                }
            }
        }
    }
}

Matrix
shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches)
{
    Matrix dist = weights;
    extend_shortest_path(dist, latencies, inter_switches);
    return dist;
}

bool
link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final,
    const Matrix& weights, const Matrix& dist)
{
    return weights[src][next] + dist[next][final] == dist[src][final];
}

NetDest
shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights,
    const Matrix& dist)
{
    NetDest result;
    int d = 0;
    int machines;
    int max_machines;

    machines = MachineType_NUM;
    max_machines = MachineType_base_number(MachineType_NUM);

    for (int m = 0; m < machines; m++) {
        for (int i = 0; i < MachineType_base_count((MachineType)m); i++) {
            // we use "d+max_machines" below since the "destination"
            // switches for the machines are numbered
            // [MachineType_base_number(MachineType_NUM)...
            //  2*MachineType_base_number(MachineType_NUM)-1] for the
            // component network
            if (link_is_shortest_path_to_node(src, next, d + max_machines,
                    weights, dist)) {
                MachineID mach = {(MachineType)m, i};
                result.add(mach);
            }
            d++;
        }
    }

    DPRINTF(RubyNetwork, "Returning shortest path\n"
            "(src-(2*max_machines)): %d, (next-(2*max_machines)): %d, "
            "src: %d, next: %d, result: %s\n",
            (src-(2*max_machines)), (next-(2*max_machines)),
            src, next, result);

    return result;
}
<commit_msg>ruby: Fix Topology throttle connections<commit_after>/*
 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <cassert>

#include "base/trace.hh"
#include "debug/RubyNetwork.hh"
#include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/BasicLink.hh"
#include "mem/ruby/network/Topology.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"

using namespace std;

const int INFINITE_LATENCY = 10000; // Yes, this is a big hack

// Note: In this file, we use the first 2*m_nodes SwitchIDs to
// represent the input and output endpoint links.  These really are
// not 'switches', as they will not have a Switch object allocated for
// them. The first m_nodes SwitchIDs are the links into the network,
// the second m_nodes set of SwitchIDs represent the the output queues
// of the network.

// Helper functions based on chapter 29 of Cormen et al.
void extend_shortest_path(Matrix& current_dist, Matrix& latencies,
    Matrix& inter_switches);
Matrix shortest_path(const Matrix& weights, Matrix& latencies,
    Matrix& inter_switches);
bool link_is_shortest_path_to_node(SwitchID src, SwitchID next,
    SwitchID final, const Matrix& weights, const Matrix& dist);
NetDest shortest_path_to_node(SwitchID src, SwitchID next,
    const Matrix& weights, const Matrix& dist);

Topology::Topology(uint32_t num_routers, vector<BasicExtLink *> ext_links,
                   vector<BasicIntLink *> int_links)
    : m_number_of_switches(num_routers)
{

    // initialize component latencies record
    m_component_latencies.resize(0);
    m_component_inter_switches.resize(0);

    // Total nodes/controllers in network
    // Must make sure this is called after the State Machine constructors
    m_nodes = MachineType_base_number(MachineType_NUM);
    assert(m_nodes > 1);

    if (m_nodes != ext_links.size()) {
        fatal("m_nodes (%d) != ext_links vector length (%d)\n",
              m_nodes, ext_links.size());
    }

    // analyze both the internal and external links, create data structures
    // Note that the python created links are bi-directional, but that the
    // topology and networks utilize uni-directional links.  Thus each
    // BasicLink is converted to two calls to add link, on for each direction
    for (vector<BasicExtLink*>::const_iterator i = ext_links.begin();
         i != ext_links.end(); ++i) {
        BasicExtLink *ext_link = (*i);
        AbstractController *abs_cntrl = ext_link->params()->ext_node;
        BasicRouter *router = ext_link->params()->int_node;

        // Store the ExtLink pointers for later
        m_ext_link_vector.push_back(ext_link);

        int machine_base_idx = MachineType_base_number(
                string_to_MachineType(abs_cntrl->getName()));
        int ext_idx1 = machine_base_idx + abs_cntrl->getVersion();
        int ext_idx2 = ext_idx1 + m_nodes;
        int int_idx = router->params()->router_id + 2*m_nodes;

        // create the internal uni-directional links in both directions
        //   the first direction is marked: In
        addLink(ext_idx1, int_idx, ext_link, LinkDirection_In);
        //   the first direction is marked: Out
        addLink(int_idx, ext_idx2, ext_link, LinkDirection_Out);
    }

    for (vector<BasicIntLink*>::const_iterator i = int_links.begin();
         i != int_links.end(); ++i) {
        BasicIntLink *int_link = (*i);
        BasicRouter *router_a = int_link->params()->node_a;
        BasicRouter *router_b = int_link->params()->node_b;

        // Store the IntLink pointers for later
        m_int_link_vector.push_back(int_link);

        int a = router_a->params()->router_id + 2*m_nodes;
        int b = router_b->params()->router_id + 2*m_nodes;

        // create the internal uni-directional links in both directions
        //   the first direction is marked: In
        addLink(a, b, int_link, LinkDirection_In);
        //   the second direction is marked: Out
        addLink(b, a, int_link, LinkDirection_Out);
    }
}

void
Topology::createLinks(Network *net)
{
    // Find maximum switchID
    SwitchID max_switch_id = 0;
    for (LinkMap::const_iterator i = m_link_map.begin();
         i != m_link_map.end(); ++i) {
        std::pair<int, int> src_dest = (*i).first;
        max_switch_id = max(max_switch_id, src_dest.first);
        max_switch_id = max(max_switch_id, src_dest.second);
    }

    // Initialize weight, latency, and inter switched vectors
    Matrix topology_weights;
    int num_switches = max_switch_id+1;
    topology_weights.resize(num_switches);
    m_component_latencies.resize(num_switches);
    m_component_inter_switches.resize(num_switches);

    for (int i = 0; i < topology_weights.size(); i++) {
        topology_weights[i].resize(num_switches);
        m_component_latencies[i].resize(num_switches);
        m_component_inter_switches[i].resize(num_switches);

        for (int j = 0; j < topology_weights[i].size(); j++) {
            topology_weights[i][j] = INFINITE_LATENCY;

            // initialize to invalid values
            m_component_latencies[i][j] = -1;

            // initially assume direct connections / no intermediate
            // switches between components
            m_component_inter_switches[i][j] = 0;
        }
    }

    // Set identity weights to zero
    for (int i = 0; i < topology_weights.size(); i++) {
        topology_weights[i][i] = 0;
    }

    // Fill in the topology weights and bandwidth multipliers
    for (LinkMap::const_iterator i = m_link_map.begin();
         i != m_link_map.end(); ++i) {
        std::pair<int, int> src_dest = (*i).first;
        BasicLink* link = (*i).second.link;
        int src = src_dest.first;
        int dst = src_dest.second;
        m_component_latencies[src][dst] = link->m_latency;
        topology_weights[src][dst] = link->m_weight;
    }

    // Walk topology and hookup the links
    Matrix dist = shortest_path(topology_weights, m_component_latencies,
        m_component_inter_switches);
    for (int i = 0; i < topology_weights.size(); i++) {
        for (int j = 0; j < topology_weights[i].size(); j++) {
            int weight = topology_weights[i][j];
            if (weight > 0 && weight != INFINITE_LATENCY) {
                NetDest destination_set =
                        shortest_path_to_node(i, j, topology_weights, dist);
                makeLink(net, i, j, destination_set);
            }
        }
    }
}

void
Topology::addLink(SwitchID src, SwitchID dest, BasicLink* link,
                  LinkDirection dir)
{
    assert(src <= m_number_of_switches+m_nodes+m_nodes);
    assert(dest <= m_number_of_switches+m_nodes+m_nodes);

    std::pair<int, int> src_dest_pair;
    LinkEntry link_entry;

    src_dest_pair.first = src;
    src_dest_pair.second = dest;
    link_entry.direction = dir;
    link_entry.link = link;
    m_link_map[src_dest_pair] = link_entry;
}

void
Topology::makeLink(Network *net, SwitchID src, SwitchID dest,
                   const NetDest& routing_table_entry)
{
    // Make sure we're not trying to connect two end-point nodes
    // directly together
    assert(src >= 2 * m_nodes || dest >= 2 * m_nodes);

    std::pair<int, int> src_dest;
    LinkEntry link_entry;

    if (src < m_nodes) {
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeInLink(src, dest - (2 * m_nodes), link_entry.link,
                        link_entry.direction, routing_table_entry);
    } else if (dest < 2*m_nodes) {
        assert(dest >= m_nodes);
        NodeID node = dest - m_nodes;
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeOutLink(src - (2 * m_nodes), node, link_entry.link,
                         link_entry.direction, routing_table_entry);
    } else {
        assert((src >= 2 * m_nodes) && (dest >= 2 * m_nodes));
        src_dest.first = src;
        src_dest.second = dest;
        link_entry = m_link_map[src_dest];
        net->makeInternalLink(src - (2 * m_nodes), dest - (2 * m_nodes),
                              link_entry.link, link_entry.direction,
                              routing_table_entry);
    }
}

// The following all-pairs shortest path algorithm is based on the
// discussion from Cormen et al., Chapter 26.1.
void
extend_shortest_path(Matrix& current_dist, Matrix& latencies,
    Matrix& inter_switches)
{
    bool change = true;
    int nodes = current_dist.size();

    while (change) {
        change = false;
        for (int i = 0; i < nodes; i++) {
            for (int j = 0; j < nodes; j++) {
                int minimum = current_dist[i][j];
                int previous_minimum = minimum;
                int intermediate_switch = -1;
                for (int k = 0; k < nodes; k++) {
                    minimum = min(minimum,
                        current_dist[i][k] + current_dist[k][j]);
                    if (previous_minimum != minimum) {
                        intermediate_switch = k;
                        inter_switches[i][j] =
                            inter_switches[i][k] +
                            inter_switches[k][j] + 1;
                    }
                    previous_minimum = minimum;
                }
                if (current_dist[i][j] != minimum) {
                    change = true;
                    current_dist[i][j] = minimum;
                    assert(intermediate_switch >= 0);
                    assert(intermediate_switch < latencies[i].size());
                    latencies[i][j] = latencies[i][intermediate_switch] +
                        latencies[intermediate_switch][j];
                }
            }
        }
    }
}

Matrix
shortest_path(const Matrix& weights, Matrix& latencies, Matrix& inter_switches)
{
    Matrix dist = weights;
    extend_shortest_path(dist, latencies, inter_switches);
    return dist;
}

bool
link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final,
    const Matrix& weights, const Matrix& dist)
{
    return weights[src][next] + dist[next][final] == dist[src][final];
}

NetDest
shortest_path_to_node(SwitchID src, SwitchID next, const Matrix& weights,
    const Matrix& dist)
{
    NetDest result;
    int d = 0;
    int machines;
    int max_machines;

    machines = MachineType_NUM;
    max_machines = MachineType_base_number(MachineType_NUM);

    for (int m = 0; m < machines; m++) {
        for (int i = 0; i < MachineType_base_count((MachineType)m); i++) {
            // we use "d+max_machines" below since the "destination"
            // switches for the machines are numbered
            // [MachineType_base_number(MachineType_NUM)...
            //  2*MachineType_base_number(MachineType_NUM)-1] for the
            // component network
            if (link_is_shortest_path_to_node(src, next, d + max_machines,
                    weights, dist)) {
                MachineID mach = {(MachineType)m, i};
                result.add(mach);
            }
            d++;
        }
    }

    DPRINTF(RubyNetwork, "Returning shortest path\n"
            "(src-(2*max_machines)): %d, (next-(2*max_machines)): %d, "
            "src: %d, next: %d, result: %s\n",
            (src-(2*max_machines)), (next-(2*max_machines)),
            src, next, result);

    return result;
}
<|endoftext|>


<commit_before>#ifndef _SD_ANIMATIONS_HXX_
#define _SD_ANIMATIONS_HXX_

namespace sd
{

/** stores the link between an after effect node and its master for later insertion
    into the timing hierarchie
*/
struct AfterEffectNode
{
    ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > mxNode;
    ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > mxMaster;
    sal_Int32 mnMasterRel;

    AfterEffectNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode, const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xMaster, sal_Int32 nMasterRel )
        : mxNode( xNode ), mxMaster( xMaster ), mnMasterRel( nMasterRel ) {}
};

typedef std::list< AfterEffectNode > AfterEffectNodeList;

/** inserts the animation node in the given AfterEffectNode at the correct position
    in the timing hierarchie of its master */
void stl_process_after_effect_node_func(AfterEffectNode& rNode);

}; // namespace sd;

#endif
<commit_msg>INTEGRATION: CWS impress49 (1.2.172); FILE MERGED 2005/06/10 15:51:07 cl 1.2.172.1: #i41546# reworked after effects<commit_after>#ifndef _SD_ANIMATIONS_HXX_
#define _SD_ANIMATIONS_HXX_

namespace sd
{

/** stores the link between an after effect node and its master for later insertion
    into the timing hierarchie
*/
struct AfterEffectNode
{
    ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > mxNode;
    ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode > mxMaster;
    bool mbOnNextEffect;

    AfterEffectNode( const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xNode, const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xMaster, bool bOnNextEffect )
        : mxNode( xNode ), mxMaster( xMaster ), mbOnNextEffect( bOnNextEffect ) {}
};

typedef std::list< AfterEffectNode > AfterEffectNodeList;

/** inserts the animation node in the given AfterEffectNode at the correct position
    in the timing hierarchie of its master */
void stl_process_after_effect_node_func(AfterEffectNode& rNode);

}; // namespace sd;

#endif
<|endoftext|>


<commit_before>#ifndef _SDD_HOM_EVALUATION_HH_
#define _SDD_HOM_EVALUATION_HH_

#include <cassert>
#include <iosfwd>

#include "sdd/hom/context_fwd.hh"
#include "sdd/mem/interrupt.hh"
#include "sdd/order/order.hh"

namespace sdd { namespace hom {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Evaluate an homomorphism.
template <typename C>
struct evaluation
{
  /// @brief Used by util::variant.
  using result_type = SDD<C>;

  /// @brief Terminal |0| case.
  ///
  /// It shall never be called as the |0| case is handled by the evaluation of
  /// homomorphism::operator().
  template <typename H>
  SDD<C>
  operator()( const H&, const zero_terminal<C>&
            , const homomorphism<C>&, const SDD<C>&
            , context<C>&, const order<C>&)
  const noexcept
  {
    assert(false);
    __builtin_unreachable();
  }

  /// @brief Terminal |1| case.
  template <typename H>
  SDD<C>
  operator()( const H& h, const one_terminal<C>&
            , const homomorphism<C>&, const SDD<C>& x
            , context<C>& cxt, const order<C>& o)
  const
  {
    return h(cxt, o, x);
  }

  /// @brief Dispatch evaluation to the concrete homomorphism.
  ///
  /// Implement a part of the automatic saturation: evaluation is propagated on successors
  /// whenever possible.
  template <typename H, typename Node>
  SDD<C>
  operator()( const H& h, const Node& node
            , const homomorphism<C>& hom, const SDD<C>& x
            , context<C>& cxt, const order<C>& o)
  const
  {
    assert(not o.empty() && "Empty order.");
    assert(o.variable() == node.variable() && "Different variables in order and SDD.");

    if (h.skip(o))
    {
      // The evaluated homomorphism skips the current level. We can thus forward its application
      // to the following levels.
      dd::square_union<C, typename Node::valuation_type> su;
      su.reserve(node.size());
      for (const auto& arc : node)
      {
        try
        {
          SDD<C> new_successor = hom(cxt, o.next(), arc.successor());
          if (not new_successor.empty())
          {
            su.add(new_successor, arc.valuation());
          }
        }
        catch (interrupt<SDD<C>>& i)
        {
          su.add(i.result(), arc.valuation());
          i.result() = {node.variable(), su(cxt.sdd_context())};
          throw;
        }
      }
      return {node.variable(), su(cxt.sdd_context())};
    }
    else
    {
      try
      {
        return h(cxt, o, x);
      }
      catch (interrupt<SDD<C>>& i)
      {
        throw;
      }
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Default traits for homomorphisms.
template <typename T>
struct homomorphism_traits
{
  static constexpr bool should_cache = true;
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief The evaluation of an homomorphism in the cache.
template <typename C>
struct cached_homomorphism
{
  /// @brief Needed by the cache.
  using result_type = SDD<C>;

  /// @brief The current order position.
  const order<C> ord;

  /// @brief The homomorphism to evaluate.
  const homomorphism<C> hom;

  /// @brief The homomorphism's operand.
  const SDD<C> sdd;

  /// @brief Constructor.
  cached_homomorphism(const order<C>& o, const homomorphism<C>& h, const SDD<C>& s)
    : ord(o), hom(h), sdd(s)
  {}

  /// @brief Launch the evaluation.
  ///
  /// Called by the cache.
  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    return binary_visit_self(evaluation<C>(), hom, sdd, cxt, ord);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @related cached_homomorphism
/// We don't need to compare orders as the SDD operands bring the same information.
template <typename C>
inline
bool
operator==(const cached_homomorphism<C>& lhs, const cached_homomorphism<C>& rhs)
noexcept
{
  return lhs.hom == rhs.hom and lhs.sdd == rhs.sdd;
}

/// @internal
/// @related cached_homomorphism
template <typename C>
std::ostream&
operator<<(std::ostream& os, const cached_homomorphism<C>& ch)
{
  return os << ch.hom;
}

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Used by the cache as a filter to know if an homomorphism should be cached.
template <typename C>
struct should_cache
{
  /// @brief Needed by mem::variant.
  using result_type = bool;

  /// @brief Dispatch to each homomorphism's trait.
  template <typename T>
  constexpr bool
  operator()(const T&)
  const noexcept
  {
    return homomorphism_traits<T>::should_cache;
  }

  /// @brief Application of should_cache.
  bool
  operator()(const cached_homomorphism<C>& ch)
  const noexcept
  {
    return visit(*this, ch.hom);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Used by the cache as a filter to know if an homomorphism should be cached.
template <typename C>
struct one_terminal_evaluation
{
  /// @brief Needed by me::variant.
  using result_type = bool;

  /// @brief Application of should_cache.
  bool
  operator()(const cached_homomorphism<C>& ch)
  const noexcept
  {
    return ch.sdd != one<C>();
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::hom

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::hom::cached_homomorphism
///
/// We don't need to hash order as the SDD operand brings the same information.
template <typename C>
struct hash<sdd::hom::cached_homomorphism<C>>
{
  std::size_t
  operator()(const sdd::hom::cached_homomorphism<C>& ch)
  const
  {
    std::size_t seed = sdd::util::hash(ch.hom);
    sdd::util::hash_combine(seed, ch.sdd);
    return seed;
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _SDD_HOM_EVALUATION_HH_
<commit_msg>Remove useless try/catch.<commit_after>#ifndef _SDD_HOM_EVALUATION_HH_
#define _SDD_HOM_EVALUATION_HH_

#include <cassert>
#include <iosfwd>

#include "sdd/hom/context_fwd.hh"
#include "sdd/mem/interrupt.hh"
#include "sdd/order/order.hh"

namespace sdd { namespace hom {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Evaluate an homomorphism.
template <typename C>
struct evaluation
{
  /// @brief Used by util::variant.
  using result_type = SDD<C>;

  /// @brief Terminal |0| case.
  ///
  /// It shall never be called as the |0| case is handled by the evaluation of
  /// homomorphism::operator().
  template <typename H>
  SDD<C>
  operator()( const H&, const zero_terminal<C>&
            , const homomorphism<C>&, const SDD<C>&
            , context<C>&, const order<C>&)
  const noexcept
  {
    assert(false);
    __builtin_unreachable();
  }

  /// @brief Terminal |1| case.
  template <typename H>
  SDD<C>
  operator()( const H& h, const one_terminal<C>&
            , const homomorphism<C>&, const SDD<C>& x
            , context<C>& cxt, const order<C>& o)
  const
  {
    return h(cxt, o, x);
  }

  /// @brief Dispatch evaluation to the concrete homomorphism.
  ///
  /// Implement a part of the automatic saturation: evaluation is propagated on successors
  /// whenever possible.
  template <typename H, typename Node>
  SDD<C>
  operator()( const H& h, const Node& node
            , const homomorphism<C>& hom, const SDD<C>& x
            , context<C>& cxt, const order<C>& o)
  const
  {
    assert(not o.empty() && "Empty order.");
    assert(o.variable() == node.variable() && "Different variables in order and SDD.");

    if (h.skip(o))
    {
      // The evaluated homomorphism skips the current level. We can thus forward its application
      // to the following levels.
      dd::square_union<C, typename Node::valuation_type> su;
      su.reserve(node.size());
      for (const auto& arc : node)
      {
        try
        {
          SDD<C> new_successor = hom(cxt, o.next(), arc.successor());
          if (not new_successor.empty())
          {
            su.add(new_successor, arc.valuation());
          }
        }
        catch (interrupt<SDD<C>>& i)
        {
          su.add(i.result(), arc.valuation());
          i.result() = {node.variable(), su(cxt.sdd_context())};
          throw;
        }
      }
      return {node.variable(), su(cxt.sdd_context())};
    }
    else
    {
      return h(cxt, o, x);
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Default traits for homomorphisms.
template <typename T>
struct homomorphism_traits
{
  static constexpr bool should_cache = true;
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief The evaluation of an homomorphism in the cache.
template <typename C>
struct cached_homomorphism
{
  /// @brief Needed by the cache.
  using result_type = SDD<C>;

  /// @brief The current order position.
  const order<C> ord;

  /// @brief The homomorphism to evaluate.
  const homomorphism<C> hom;

  /// @brief The homomorphism's operand.
  const SDD<C> sdd;

  /// @brief Constructor.
  cached_homomorphism(const order<C>& o, const homomorphism<C>& h, const SDD<C>& s)
    : ord(o), hom(h), sdd(s)
  {}

  /// @brief Launch the evaluation.
  ///
  /// Called by the cache.
  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    return binary_visit_self(evaluation<C>(), hom, sdd, cxt, ord);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @related cached_homomorphism
/// We don't need to compare orders as the SDD operands bring the same information.
template <typename C>
inline
bool
operator==(const cached_homomorphism<C>& lhs, const cached_homomorphism<C>& rhs)
noexcept
{
  return lhs.hom == rhs.hom and lhs.sdd == rhs.sdd;
}

/// @internal
/// @related cached_homomorphism
template <typename C>
std::ostream&
operator<<(std::ostream& os, const cached_homomorphism<C>& ch)
{
  return os << ch.hom;
}

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Used by the cache as a filter to know if an homomorphism should be cached.
template <typename C>
struct should_cache
{
  /// @brief Needed by mem::variant.
  using result_type = bool;

  /// @brief Dispatch to each homomorphism's trait.
  template <typename T>
  constexpr bool
  operator()(const T&)
  const noexcept
  {
    return homomorphism_traits<T>::should_cache;
  }

  /// @brief Application of should_cache.
  bool
  operator()(const cached_homomorphism<C>& ch)
  const noexcept
  {
    return visit(*this, ch.hom);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Used by the cache as a filter to know if an homomorphism should be cached.
template <typename C>
struct one_terminal_evaluation
{
  /// @brief Needed by me::variant.
  using result_type = bool;

  /// @brief Application of should_cache.
  bool
  operator()(const cached_homomorphism<C>& ch)
  const noexcept
  {
    return ch.sdd != one<C>();
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::hom

namespace std {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Hash specialization for sdd::hom::cached_homomorphism
///
/// We don't need to hash order as the SDD operand brings the same information.
template <typename C>
struct hash<sdd::hom::cached_homomorphism<C>>
{
  std::size_t
  operator()(const sdd::hom::cached_homomorphism<C>& ch)
  const
  {
    std::size_t seed = sdd::util::hash(ch.hom);
    sdd::util::hash_combine(seed, ch.sdd);
    return seed;
  }
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _SDD_HOM_EVALUATION_HH_
<|endoftext|>


<commit_before>#include <mapnik/util/file_io.hpp>
#include "vector_tile.pb.h"
#include "vector_tile_compression.hpp"

#include <iostream>
#include <fstream>

#include <protozero/pbf_reader.hpp>

int main(int argc, char** argv)
{
    try
    {
        if (argc < 2)
        {
            std::clog << "usage: vtile-edit /path/to/tile.vector.mvt [--set-version version]" << std::endl;
            return -1;
        }
        std::string vtile(argv[1]);
        mapnik::util::file input(vtile);
        if (!input.open())
        {
            std::clog << std::string("failed to open ") + vtile << "\n";
            return -1;
        }

        unsigned version = 1;
        std::string flag = argv[2];
        if (flag == "--set-version")
        {
            version = std::stoi(argv[3]);
        }

        std::string message(input.data().get(), input.size());

        bool is_zlib = mapnik::vector_tile_impl::is_zlib_compressed(message);
        bool is_gzip = mapnik::vector_tile_impl::is_gzip_compressed(message);
        if (is_zlib || is_gzip)
        {
            if (is_zlib)
            {
                std::cout << "message: zlib compressed\n";
            }
            else if (is_gzip)
            {
                std::cout << "message: gzip compressed\n";
            }
            std::string uncompressed;
            mapnik::vector_tile_impl::zlib_decompress(message,uncompressed);
            message = uncompressed;
        }

        vector_tile::Tile tile;
        tile.ParseFromString(message);

        for (int j=0;j<tile.layers_size(); ++j)
        {
            auto layer = tile.mutable_layers(j);
            std::clog << "layer: " << layer->name() << std::endl;
            std::clog << "old version: " << layer->version() << std::endl;
            if (version != layer->version())
            {
                layer->set_version(version);
            }
            std::clog << "new version: " << layer->version() << std::endl;
        }

        // Serialize
        std::string output;
        tile.SerializeToString(&output);

        // Recompress
        bool gzip = true;
        if (is_zlib || is_gzip)
        {
            if (is_zlib)
            {
                gzip = false;
                std::cout << "message: zlib compressing\n";
            }
            else if (is_gzip)
            {
                gzip = true;
                std::cout << "message: gzip compressing\n";
            }
            std::string compressed;
            mapnik::vector_tile_impl::zlib_compress(output,compressed,gzip);
            output = compressed;
        }

        std::ofstream file(vtile);
        file << output;

        std::clog << "wrote to: " << vtile << std::endl;
    }
    catch (std::exception const& ex)
    {
        std::clog << "error: " << ex.what() << "\n";
        return -1;
    }
    return 0;
}
<commit_msg>Updated vtile-edit<commit_after>#include <mapnik/util/file_io.hpp>
#include "vector_tile.pb.h"
#include "vector_tile_compression.hpp"

#include <iostream>
#include <fstream>

#include <protozero/pbf_reader.hpp>

int main(int argc, char** argv)
{
    try
    {
        if (argc < 2)
        {
            std::clog << "usage: vtile-edit /path/to/tile.vector.mvt [--set-version version]" << std::endl;
            return -1;
        }
        std::string vtile(argv[1]);
        mapnik::util::file input(vtile);
        if (!input.open())
        {
            std::clog << std::string("failed to open ") + vtile << "\n";
            return -1;
        }

        unsigned version = 0;
        bool clean_empty = false;
        if (argc > 2)
        {
            for (int i = 2; i < argc; i++)
            {
                std::string flag = argv[i];
                if (flag == "--set-version")
                {
                    version = std::stoi(argv[i + 1]);
                }
                if (flag == "--clean-empty")
                {
                    clean_empty = true;
                }
            }
        }

        std::string message(input.data().get(), input.size());

        bool is_zlib = mapnik::vector_tile_impl::is_zlib_compressed(message);
        bool is_gzip = mapnik::vector_tile_impl::is_gzip_compressed(message);
        if (is_zlib || is_gzip)
        {
            if (is_zlib)
            {
                std::cout << "message: zlib compressed\n";
            }
            else if (is_gzip)
            {
                std::cout << "message: gzip compressed\n";
            }
            std::string uncompressed;
            mapnik::vector_tile_impl::zlib_decompress(message,uncompressed);
            message = uncompressed;
        }

        vector_tile::Tile tile;
        tile.ParseFromString(message);

        for (int j=0;j<tile.layers_size(); ++j)
        {
            auto layer = tile.mutable_layers(j);
            std::clog << "layer: " << layer->name() << std::endl;
            if (version != 0)
            {
                std::clog << "old version: " << layer->version() << std::endl;
                if (version != layer->version())
                {
                    layer->set_version(version);
                }
                std::clog << "new version: " << layer->version() << std::endl;
            }
            if (clean_empty)
            {
                std::clog << "Cleaning empty features" << std::endl;
                for (int i = 0; i < layer->features_size(); ++i)
                {
                    auto feature = layer->mutable_features(i);
                    if (feature->geometry_size() == 0 && !feature->has_raster())
                    {
                        layer->mutable_features()->DeleteSubrange(i,1);
                        --i;
                    }
                }
                if (layer->features_size() == 0)
                {
                    tile.mutable_layers()->DeleteSubrange(j,1);
                    --j;
                }
            }
        }

        // Serialize
        std::string output;
        tile.SerializeToString(&output);

        // Recompress
        bool gzip = true;
        if (is_zlib || is_gzip)
        {
            if (is_zlib)
            {
                gzip = false;
                std::cout << "message: zlib compressing\n";
            }
            else if (is_gzip)
            {
                gzip = true;
                std::cout << "message: gzip compressing\n";
            }
            std::string compressed;
            mapnik::vector_tile_impl::zlib_compress(output,compressed,gzip);
            output = compressed;
        }

        std::ofstream file(vtile);
        file << output;

        std::clog << "wrote to: " << vtile << std::endl;
    }
    catch (std::exception const& ex)
    {
        std::clog << "error: " << ex.what() << "\n";
        return -1;
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Core/Common.h"
#include <sys/stat.h>
#include "Assembler.h"
#include "Commands/CAssemblerLabel.h"
#include "Util/Util.h"
#include "Core/FileManager.h"

FileManager fileManager;
FileManager* g_fileManager = &fileManager;

tGlobal Global;
CArchitecture* Arch;

std::wstring getFolderNameFromPath(const std::wstring& src)
{
	size_t s = src.rfind('\\');
	if (s == std::wstring::npos)
	{
		s = src.rfind('/');
		if (s == std::wstring::npos)
			return L".";
	}

	return src.substr(0,s);
}

std::wstring getFullPathName(const std::wstring& path)
{
	if (Global.relativeInclude == true)
	{
		if (isAbsolutePath(path))
		{
			return path;
		} else {
			std::wstring source = Global.FileInfo.FileList[Global.FileInfo.FileNum];
			return getFolderNameFromPath(source) + L"/" + path;
		}
	} else {
		return path;
	}
}

bool checkLabelDefined(const std::wstring& labelName, int section)
{
	Label* label = Global.symbolTable.getLabel(labelName,Global.FileInfo.FileNum,section);
	return label->isDefined();
}

bool checkValidLabelName(const std::wstring& labelName)
{
	return Global.symbolTable.isValidSymbolName(labelName);
}

bool isPowerOfTwo(u64 n)
{
	if (n == 0) return false;
	return !(n & (n - 1));
}
<commit_msg>Fix getFolderNameFromPath function<commit_after>#include "stdafx.h"
#include "Core/Common.h"
#include <sys/stat.h>
#include "Assembler.h"
#include "Commands/CAssemblerLabel.h"
#include "Util/Util.h"
#include "Core/FileManager.h"

FileManager fileManager;
FileManager* g_fileManager = &fileManager;

tGlobal Global;
CArchitecture* Arch;

std::wstring getFolderNameFromPath(const std::wstring& src)
{
#ifdef _WIN32
	size_t s = src.find_last_of(L"\\/");
#else
	size_t s = src.rfind(L"/");
#endif
	if (s == std::wstring::npos)
	{
		return L".";
	}

	return src.substr(0,s);
}

std::wstring getFullPathName(const std::wstring& path)
{
	if (Global.relativeInclude == true)
	{
		if (isAbsolutePath(path))
		{
			return path;
		} else {
			std::wstring source = Global.FileInfo.FileList[Global.FileInfo.FileNum];
			return getFolderNameFromPath(source) + L"/" + path;
		}
	} else {
		return path;
	}
}

bool checkLabelDefined(const std::wstring& labelName, int section)
{
	Label* label = Global.symbolTable.getLabel(labelName,Global.FileInfo.FileNum,section);
	return label->isDefined();
}

bool checkValidLabelName(const std::wstring& labelName)
{
	return Global.symbolTable.isValidSymbolName(labelName);
}

bool isPowerOfTwo(u64 n)
{
	if (n == 0) return false;
	return !(n & (n - 1));
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "ui_addplugindialog.h"
#include "addplugindialog.h"
#include "plugin.h"
#include "../lxqtpanelapplication.h"

#include <LXQt/HtmlDelegate>
#include <XdgIcon>
#include <XdgDirs>

#include <QString>
#include <QLineEdit>
#include <QListWidgetItem>
#include <QIcon>

#define SEARCH_ROLE  Qt::UserRole
#define INDEX_ROLE   SEARCH_ROLE+1

AddPluginDialog::AddPluginDialog(QWidget *parent):
    QDialog(parent),
    ui(new Ui::AddPluginDialog)
{
    ui->setupUi(this);

    QStringList desktopFilesDirs;
    desktopFilesDirs << QString(getenv("LXQT_PANEL_PLUGINS_DIR")).split(':', QString::SkipEmptyParts);
    desktopFilesDirs << QString("%1/%2").arg(XdgDirs::dataHome(), "/lxqt/lxqt-panel");
    desktopFilesDirs << PLUGIN_DESKTOPS_DIR;

    mPlugins = LXQt::PluginInfo::search(desktopFilesDirs, QStringLiteral("LXQtPanel/Plugin"), QStringLiteral("*"));
    std::sort(mPlugins.begin(), mPlugins.end(), [](const LXQt::PluginInfo &p1, const LXQt::PluginInfo &p2) {
        return p1.name() < p2.name() || (p1.name() == p2.name() && p1.comment() < p2.comment());
    });

    ui->pluginList->setItemDelegate(new LXQt::HtmlDelegate(QSize(32, 32), ui->pluginList));
    ui->pluginList->setContextMenuPolicy(Qt::CustomContextMenu);

    filter();

    // search
    mSearchTimer.setInterval(300);
    mSearchTimer.setSingleShot(true);
    connect(ui->searchEdit, &QLineEdit::textEdited,
            &mSearchTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
    connect(&mSearchTimer, &QTimer::timeout, this, &AddPluginDialog::filter);
    connect(ui->pluginList, &QListWidget::doubleClicked, this, &AddPluginDialog::emitPluginSelected);
    connect(ui->addButton, &QPushButton::clicked, this, &AddPluginDialog::emitPluginSelected);

    connect(dynamic_cast<LXQtPanelApplication *>(qApp), &LXQtPanelApplication::pluginAdded
            , this, &AddPluginDialog::filter);
    connect(dynamic_cast<LXQtPanelApplication *>(qApp), &LXQtPanelApplication::pluginRemoved
            , this, &AddPluginDialog::filter);
}

AddPluginDialog::~AddPluginDialog()
{
    delete ui;
}

void AddPluginDialog::filter()
{
    QListWidget* pluginList = ui->pluginList;

    const int curr_item = 0 < pluginList->count() ? pluginList->currentRow() : 0;
    pluginList->clear();

    static QIcon fallIco = XdgIcon::fromTheme("preferences-plugin");

    int pluginCount = mPlugins.length();
    for (int i = 0; i < pluginCount; ++i)
    {
        const LXQt::PluginInfo &plugin = mPlugins.at(i);

        QString s = QStringLiteral("%1 %2 %3 %4").arg(plugin.name(),
                                               plugin.comment(),
                                               plugin.value("Name").toString(),
                                               plugin.value("Comment").toString());
        if (!s.contains(ui->searchEdit->text(), Qt::CaseInsensitive))
            continue;

        QListWidgetItem* item = new QListWidgetItem(ui->pluginList);
        // disable single-instances plugins already in use
        if (dynamic_cast<LXQtPanelApplication const *>(qApp)->isPluginSingletonAndRunnig(plugin.id()))
        {
            item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
            item->setBackground(palette().brush(QPalette::Disabled, QPalette::Text));
            item->setText(QStringLiteral("%1
%2
%3")
                    .arg(plugin.name(), plugin.comment(), tr("(only one instance can run at a time)")));
        } else
            item->setText(QStringLiteral("%1
%2").arg(plugin.name(), plugin.comment()));
        item->setIcon(plugin.icon(fallIco));
        item->setData(INDEX_ROLE, i);
    }

    if (pluginCount > 0)
        ui->pluginList->setCurrentRow(curr_item < pluginCount ? curr_item : pluginCount - 1);
}

void AddPluginDialog::emitPluginSelected()
{
    QListWidget* pluginList = ui->pluginList;
    if (pluginList->currentItem() && pluginList->currentItem()->isSelected())
    {
        LXQt::PluginInfo plugin = mPlugins.at(pluginList->currentItem()->data(INDEX_ROLE).toInt());
        emit pluginSelected(plugin);
    }
}

<commit_msg>addplugindialog: show also the plugin ID (desktop file name)<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2010-2011 Razor team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include "ui_addplugindialog.h"
#include "addplugindialog.h"
#include "plugin.h"
#include "../lxqtpanelapplication.h"

#include <LXQt/HtmlDelegate>
#include <XdgIcon>
#include <XdgDirs>

#include <QString>
#include <QLineEdit>
#include <QListWidgetItem>
#include <QIcon>

#define SEARCH_ROLE  Qt::UserRole
#define INDEX_ROLE   SEARCH_ROLE+1

AddPluginDialog::AddPluginDialog(QWidget *parent):
    QDialog(parent),
    ui(new Ui::AddPluginDialog)
{
    ui->setupUi(this);

    QStringList desktopFilesDirs;
    desktopFilesDirs << QString(getenv("LXQT_PANEL_PLUGINS_DIR")).split(':', QString::SkipEmptyParts);
    desktopFilesDirs << QString("%1/%2").arg(XdgDirs::dataHome(), "/lxqt/lxqt-panel");
    desktopFilesDirs << PLUGIN_DESKTOPS_DIR;

    mPlugins = LXQt::PluginInfo::search(desktopFilesDirs, QStringLiteral("LXQtPanel/Plugin"), QStringLiteral("*"));
    std::sort(mPlugins.begin(), mPlugins.end(), [](const LXQt::PluginInfo &p1, const LXQt::PluginInfo &p2) {
        return p1.name() < p2.name() || (p1.name() == p2.name() && p1.comment() < p2.comment());
    });

    ui->pluginList->setItemDelegate(new LXQt::HtmlDelegate(QSize(32, 32), ui->pluginList));
    ui->pluginList->setContextMenuPolicy(Qt::CustomContextMenu);

    filter();

    // search
    mSearchTimer.setInterval(300);
    mSearchTimer.setSingleShot(true);
    connect(ui->searchEdit, &QLineEdit::textEdited,
            &mSearchTimer, static_cast<void (QTimer::*)()>(&QTimer::start));
    connect(&mSearchTimer, &QTimer::timeout, this, &AddPluginDialog::filter);
    connect(ui->pluginList, &QListWidget::doubleClicked, this, &AddPluginDialog::emitPluginSelected);
    connect(ui->addButton, &QPushButton::clicked, this, &AddPluginDialog::emitPluginSelected);

    connect(dynamic_cast<LXQtPanelApplication *>(qApp), &LXQtPanelApplication::pluginAdded
            , this, &AddPluginDialog::filter);
    connect(dynamic_cast<LXQtPanelApplication *>(qApp), &LXQtPanelApplication::pluginRemoved
            , this, &AddPluginDialog::filter);
}

AddPluginDialog::~AddPluginDialog()
{
    delete ui;
}

void AddPluginDialog::filter()
{
    QListWidget* pluginList = ui->pluginList;

    const int curr_item = 0 < pluginList->count() ? pluginList->currentRow() : 0;
    pluginList->clear();

    static QIcon fallIco = XdgIcon::fromTheme("preferences-plugin");

    int pluginCount = mPlugins.length();
    for (int i = 0; i < pluginCount; ++i)
    {
        const LXQt::PluginInfo &plugin = mPlugins.at(i);

        QString s = QStringLiteral("%1 %2 %3 %4 %5").arg(plugin.name(),
                                               plugin.comment(),
                                               plugin.value("Name").toString(),
                                               plugin.value("Comment").toString(),
                                               plugin.id());
        if (!s.contains(ui->searchEdit->text(), Qt::CaseInsensitive))
            continue;

        QListWidgetItem* item = new QListWidgetItem(ui->pluginList);
        // disable single-instances plugins already in use
        if (dynamic_cast<LXQtPanelApplication const *>(qApp)->isPluginSingletonAndRunnig(plugin.id()))
        {
            item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
            item->setBackground(palette().brush(QPalette::Disabled, QPalette::Text));
            item->setText(QStringLiteral("%1 (%2)
%3
%4")
                    .arg(plugin.name(), plugin.id(), plugin.comment(), tr("(only one instance can run at a time)")));
        } else
            item->setText(QStringLiteral("%1 (%2)
%3").arg(plugin.name(), plugin.id(), plugin.comment()));
        item->setIcon(plugin.icon(fallIco));
        item->setData(INDEX_ROLE, i);
    }

    if (pluginCount > 0)
        ui->pluginList->setCurrentRow(curr_item < pluginCount ? curr_item : pluginCount - 1);
}

void AddPluginDialog::emitPluginSelected()
{
    QListWidget* pluginList = ui->pluginList;
    if (pluginList->currentItem() && pluginList->currentItem()->isSelected())
    {
        LXQt::PluginInfo plugin = mPlugins.at(pluginList->currentItem()->data(INDEX_ROLE).toInt());
        emit pluginSelected(plugin);
    }
}

<|endoftext|>