<commit_before>//#define NO_IMPORT_ARRAY
//#define PY_ARRAY_UNIQUE_SYMBOL 23847
//#define NPY_ENABLE_SEPARATE_COMPILATION

#ifdef LINK_PYTHON_THREADS
#include "gil_release.h"
#endif

#include "boilerplate.h"
/*#include <infer_machine/distribution_map.h>
#include <infer_machine/hier_infer_machine.h>

//#include <dataset_2d/outdoor_2d.h>
#include <graph_segment/fh_segmenter.h>
#include <region_generic/region_data.h>
#include <region_2d/region_2d_level.h>

#include <v_regressor/v_random_forest.h>
#include <pclassifier/boosted_maxent.h>

#include "voc_felz_features.h"
*/
#include <mymex.h>

bool numpy_satisfy_properties(PyArrayObject *ao,
                              int nd,
                              int* dims,
                              int type_num,
                              bool yell)
{
    if (ao->base != NULL) {
        if (yell) {
            printf("OH NO! base was %p instead of NULL!\n",
                   ao->base);
            fflush(stdout);
        }
        return false;
    }

    if (!(ao->flags | NPY_C_CONTIGUOUS)) {
        if (yell) {
            printf("ON NO! NPY_C_CONTIGUOUS FALSE!\n");
            fflush(stdout);
        }
        return false;
    }
    if (!(ao->flags | NPY_OWNDATA)) {
        if (yell) {
            printf("ON NO! NPY_OWNDATA FALSE!\n");
            fflush(stdout);
        }
        return false;
    }
    if (!(ao->flags | NPY_ALIGNED)) {
        if (yell) {
            printf("ON NO! NPY_ALIGNED FALSE!\n");
            fflush(stdout);
        }
        return false;
    }

    if (nd >= 0) {
        if (ao->nd != nd) {
            if (yell) {
                printf("numpy_satisfy_properties OH NO! nd = %d and desired nd = %d!\n",
                       ao->nd, nd);
                fflush(stdout);
            }
            return false;
        }

        if (dims != NULL) {
            for (int i=0; i<nd; i++) {
                if (ao->dimensions[i] != dims[i]) {
                    if (yell) {
                        printf("OH NO! dims[%d] = %ld and desired %d!\n",
                               i, ao->dimensions[i], dims[i]);
                        fflush(stdout);
                    }
                    return false;
                }
            }
        }
    }

    if (ao->descr->type_num != type_num) {
        if (yell) {
            printf("OH NO! type_num is %d and desired %d!\n",
                   ao->descr->type_num, type_num);
            fflush(stdout);
        }
        return false;
    }
    return true;
}

struct mxArray_to_numpy_str {
    static PyObject *convert(const mxArray &m) {
        if (m.NDim == 2) {
            /* fucking column major bitches */
            npy_intp dims[] = {m.Dims[0], m.Dims[1]};

            PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
            for (int i=0; i<dims[0]; i++) {
                for (int j=0; j<dims[1]; j++) {
                    real fake;
                    ((real*)retval->data)[i*dims[1] + j] = m.get2D(i, j, fake);
                }
            }

            return (PyObject*)retval;
        }
        else if (m.NDim == 3) {
            npy_intp dims[] = {m.Dims[0], m.Dims[1], m.Dims[2]};

            PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
            for (int c=0; c<dims[2]; c++) {
                for (int col=0; col<dims[1]; col++) {
                    for (int row=0; row<dims[0]; row++) {
                        real fake;
                        ((real*)retval->data)[row*dims[1]*dims[2] + col*dims[2] + c] = \
                            m.get3D(row, col, c, fake);
                    }
                }
            }
            return (PyObject*)retval;
        }
        else {
            printf("OH NO! Tried to convert mxArray of nd %d to numpy!\n",
                   m.NDim);
        }
    }
};

struct mxArray_from_numpy_str {
    static void* convertible(PyObject *o)
    {
        PyArrayObject *ao = (PyArrayObject*)o;

        int cls = npy_real_type();
        if (!numpy_satisfy_properties(ao, 2, NULL, cls, true) &&
            !numpy_satisfy_properties(ao, 3, NULL, cls, true))
            return 0;

        return (void*)o;
    }

    static void construct(PyObject *o,
                          converter::rvalue_from_python_stage1_data* data)
    {

        void* storage = ((converter::rvalue_from_python_storage<mxArray>*)data)->storage.bytes;
        PyArrayObject *ao = (PyArrayObject*)o;

        new (storage) mxArray(ao->nd, (int*)ao->dimensions, mx_real_type(), mxREAL);
        mxArray* m = (mxArray*)storage;

        data->convertible = storage;

        if (ao->nd == 2) {
            for (int col=0; col < m->Dims[1]; col++) {
                for (int row=0; row < m->Dims[0]; row++) {
                    m->set2D(row, col, ((real*)ao->data)[row*m->Dims[1]* +
                                                           col]);
                }
            }
        }
        else if (ao->nd == 3) {
            for (int c=0; c < m->Dims[2]; c++) {
                for (int col=0; col < m->Dims[1]; col++) {
                    for (int row=0; row < m->Dims[0]; row++) {
                        m->set3D(row, col, c, ((real*)ao->data)[row*m->Dims[1]*m->Dims[2] +
                                                                  col*m->Dims[2] +
                                                                  c]);
                    }
                }
            }
        }
    }

    mxArray_from_numpy_str()
    {
        converter::registry::push_back(&convertible,
                                       &construct,
                                       type_id<mxArray>());
    }
};

// template <typename T, typename U>
// struct vec_vec_from_numpy_str {
//     static void *convertible (PyObject *)
//     {
// 	PyArrayObject *ao = (PyArrayObject*)o;
//         if (!numpy_satisfy_properties(ao, 2, NULL, U, true))
// 	    return 0;
//         return (void*)o;
//     }

//     static void construct(PyObject *o, converter::rvalue_from_python_stage1_data* data)
//     {
// 	void* storage = ((converter::rvalue_from_python_storage<vector<real> >*)data)->storage.bytes;
//         PyArrayObject *ao = (PyArrayObject*)o;

// 	new (storage) std::vector<std::vector<T> >(int(ao->dimensions[0]),
// 						   std::vector<T>(int(ao->dimensions[1]), 0));
// 	data->convertible = storage;
//     }
// }

struct vec_from_numpy_str {
    static void* convertible(PyObject *o)
    {
        PyArrayObject *ao = (PyArrayObject*)o;
        if (!numpy_satisfy_properties(ao, 1, NULL, npy_real_type(), true))
            return 0;

        return (void*)o;
    }

    static void construct(PyObject *o,
                          converter::rvalue_from_python_stage1_data* data)
    {
        void* storage = ((converter::rvalue_from_python_storage<vector<real> >*)data)->storage.bytes;
        PyArrayObject *ao = (PyArrayObject*)o;

        new (storage) vector<real>(ao->dimensions[0]);

        vector<real> *v = (vector<real>*)storage;

        data->convertible = storage;

        for (int i=0; i<ao->dimensions[0]; i++) {
            (*v)[i] = ((real*)ao->data)[i];
        }
    }

    vec_from_numpy_str()
    {
        converter::registry::push_back(&convertible,
                                       &construct,
                                       type_id<vector<real> >());
    }
};

struct vec_to_numpy_str {
    static PyObject *convert(const vector<real>& v)
    {
        npy_intp dims[] = {v.size()};
        PyArrayObject *ao = (PyArrayObject*)PyArray_SimpleNew(1, dims, npy_real_type());

        for (int i=0; i<v.size(); i++) {
            ((real*)ao->data)[i] = v[i];
        }

        return (PyObject*)ao;
    }
};

PyObject *vecvecvec_to_numpy(vector<vector<vector<real> > > v)
{
    npy_intp dims[] = {v.size(), v[0].size(), v[0][0].size()};

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    for (int k=0; k<dims[2]; k++) {
		((real*)retval->data)[i*dims[0]*dims[1] + j*dims[1] + k] = v[i][j][k];
	    }
	}
    }

    return (PyObject*)retval;
}

PyObject *vecvec_to_numpy(const vector<const vector<real> *> v)
{
    npy_intp dims[] = {v.size(), v[0]->size()};

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    ((real*)retval->data)[i*dims[1] + j] = (*v[i])[j];
	}
    }

    return (PyObject*)retval;
}

PyObject *vecvec_real_to_numpy(vector<vector<real> > v)
{
    npy_intp dims[] = {v.size(), v[0].size()};
    printf("dims[0]: %d, dims[1]: %d\n", dims[0], dims[1]);
    fflush(stdout);

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    ((real*)retval->data)[i*dims[1] + j] = v[i][j];
	}
    }

    return (PyObject*)retval;
}

PyObject* mxarray2d_to_numpy(mxArray* arr)
{
    /* fucking column major bitches */
    npy_intp dims[] = {arr->Dims[0], arr->Dims[1]};

    PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0]; i++) {
	for (int j=0; j<dims[1]; j++) {
	    real fake;
	    ((real*)retval->data)[i*dims[1] + j] = arr->get2D(i, j, fake);
	}
    }

    return (PyObject*)retval;
}

mxArray* numpy_to_mxarray3d(PyObject *o)
{
    PyArrayObject *ao = (PyArrayObject*)o;

    if (!numpy_satisfy_properties(ao, 3, NULL, npy_real_type(), true)) {
        return NULL;
    }

    int dims[] = {ao->dimensions[0], ao->dimensions[1], ao->dimensions[2]};

    mxArray* ret = mxCreateNumericArray(3, dims, mx_real_type(), mxREAL);
    for (int c=0; c<dims[2]; c++) {
	for (int col=0; col<dims[1]; col++) {
	    for (int row=0; row<dims[0]; row++) {
		ret->set3D(row, col, c, ((real*)ao->data)[row*dims[1]*dims[2] + col*dims[2] + c]);
	    }
	}
    }
    return ret;
}

PyObject* mxarray3d_to_numpy(mxArray* arr)
{
    npy_intp dims[] = {arr->Dims[0], arr->Dims[1], arr->Dims[2]};

    PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
    for (int c=0; c<dims[2]; c++) {
	for (int col=0; col<dims[1]; col++) {
	    for (int row=0; row<dims[0]; row++) {
		real fake;
		((real*)retval->data)[row*dims[1]*dims[2] + col*dims[2] + c] = \
                    arr->get3D(row, col, c, fake);
	    }
	}
    }
    return (PyObject*)retval;
}

vector<real> numpy_to_vec(PyObject *o)
{
    PyArrayObject *ao = (PyArrayObject*)o;
    if (!numpy_satisfy_properties(ao, 1, NULL, npy_real_type(), true)) {
        return vector<real>();
    }

    vector<real> ret(ao->dimensions[0]);
    for (int i=0; i<ao->dimensions[0]; i++) {
        ret[i] = ((real*)ao->data)[i];
    }
    return ret;
}

PyObject* vec_to_numpy(vector<real> v)
{
    npy_intp dims[] = {v.size()};
    PyArrayObject *ao = (PyArrayObject*)PyArray_SimpleNew(1, dims, npy_real_type());

    for (int i=0; i<v.size(); i++) {
        ((real*)ao->data)[i] = v[i];
    }

    return (PyObject*)ao;
}
<commit_msg>Removed annoying print<commit_after>//#define NO_IMPORT_ARRAY
//#define PY_ARRAY_UNIQUE_SYMBOL 23847
//#define NPY_ENABLE_SEPARATE_COMPILATION

#ifdef LINK_PYTHON_THREADS
#include "gil_release.h"
#endif

#include "boilerplate.h"
/*#include <infer_machine/distribution_map.h>
#include <infer_machine/hier_infer_machine.h>

//#include <dataset_2d/outdoor_2d.h>
#include <graph_segment/fh_segmenter.h>
#include <region_generic/region_data.h>
#include <region_2d/region_2d_level.h>

#include <v_regressor/v_random_forest.h>
#include <pclassifier/boosted_maxent.h>

#include "voc_felz_features.h"
*/
#include <mymex.h>

bool numpy_satisfy_properties(PyArrayObject *ao,
                              int nd,
                              int* dims,
                              int type_num,
                              bool yell)
{
    if (ao->base != NULL) {
        if (yell) {
            printf("OH NO! base was %p instead of NULL!\n",
                   ao->base);
            fflush(stdout);
        }
        return false;
    }

    if (!(ao->flags | NPY_C_CONTIGUOUS)) {
        if (yell) {
            printf("ON NO! NPY_C_CONTIGUOUS FALSE!\n");
            fflush(stdout);
        }
        return false;
    }
    if (!(ao->flags | NPY_OWNDATA)) {
        if (yell) {
            printf("ON NO! NPY_OWNDATA FALSE!\n");
            fflush(stdout);
        }
        return false;
    }
    if (!(ao->flags | NPY_ALIGNED)) {
        if (yell) {
            printf("ON NO! NPY_ALIGNED FALSE!\n");
            fflush(stdout);
        }
        return false;
    }

    if (nd >= 0) {
        if (ao->nd != nd) {
            if (yell) {
                printf("numpy_satisfy_properties OH NO! nd = %d and desired nd = %d!\n",
                       ao->nd, nd);
                fflush(stdout);
            }
            return false;
        }

        if (dims != NULL) {
            for (int i=0; i<nd; i++) {
                if (ao->dimensions[i] != dims[i]) {
                    if (yell) {
                        printf("OH NO! dims[%d] = %ld and desired %d!\n",
                               i, ao->dimensions[i], dims[i]);
                        fflush(stdout);
                    }
                    return false;
                }
            }
        }
    }

    if (ao->descr->type_num != type_num) {
        if (yell) {
            printf("OH NO! type_num is %d and desired %d!\n",
                   ao->descr->type_num, type_num);
            fflush(stdout);
        }
        return false;
    }
    return true;
}

struct mxArray_to_numpy_str {
    static PyObject *convert(const mxArray &m) {
        if (m.NDim == 2) {
            /* fucking column major bitches */
            npy_intp dims[] = {m.Dims[0], m.Dims[1]};

            PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
            for (int i=0; i<dims[0]; i++) {
                for (int j=0; j<dims[1]; j++) {
                    real fake;
                    ((real*)retval->data)[i*dims[1] + j] = m.get2D(i, j, fake);
                }
            }

            return (PyObject*)retval;
        }
        else if (m.NDim == 3) {
            npy_intp dims[] = {m.Dims[0], m.Dims[1], m.Dims[2]};

            PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
            for (int c=0; c<dims[2]; c++) {
                for (int col=0; col<dims[1]; col++) {
                    for (int row=0; row<dims[0]; row++) {
                        real fake;
                        ((real*)retval->data)[row*dims[1]*dims[2] + col*dims[2] + c] = \
                            m.get3D(row, col, c, fake);
                    }
                }
            }
            return (PyObject*)retval;
        }
        else {
            printf("OH NO! Tried to convert mxArray of nd %d to numpy!\n",
                   m.NDim);
        }
    }
};

struct mxArray_from_numpy_str {
    static void* convertible(PyObject *o)
    {
        PyArrayObject *ao = (PyArrayObject*)o;

        int cls = npy_real_type();
        if (!numpy_satisfy_properties(ao, 2, NULL, cls, true) &&
            !numpy_satisfy_properties(ao, 3, NULL, cls, true))
            return 0;

        return (void*)o;
    }

    static void construct(PyObject *o,
                          converter::rvalue_from_python_stage1_data* data)
    {

        void* storage = ((converter::rvalue_from_python_storage<mxArray>*)data)->storage.bytes;
        PyArrayObject *ao = (PyArrayObject*)o;

        new (storage) mxArray(ao->nd, (int*)ao->dimensions, mx_real_type(), mxREAL);
        mxArray* m = (mxArray*)storage;

        data->convertible = storage;

        if (ao->nd == 2) {
            for (int col=0; col < m->Dims[1]; col++) {
                for (int row=0; row < m->Dims[0]; row++) {
                    m->set2D(row, col, ((real*)ao->data)[row*m->Dims[1]* +
                                                           col]);
                }
            }
        }
        else if (ao->nd == 3) {
            for (int c=0; c < m->Dims[2]; c++) {
                for (int col=0; col < m->Dims[1]; col++) {
                    for (int row=0; row < m->Dims[0]; row++) {
                        m->set3D(row, col, c, ((real*)ao->data)[row*m->Dims[1]*m->Dims[2] +
                                                                  col*m->Dims[2] +
                                                                  c]);
                    }
                }
            }
        }
    }

    mxArray_from_numpy_str()
    {
        converter::registry::push_back(&convertible,
                                       &construct,
                                       type_id<mxArray>());
    }
};

// template <typename T, typename U>
// struct vec_vec_from_numpy_str {
//     static void *convertible (PyObject *)
//     {
// 	PyArrayObject *ao = (PyArrayObject*)o;
//         if (!numpy_satisfy_properties(ao, 2, NULL, U, true))
// 	    return 0;
//         return (void*)o;
//     }

//     static void construct(PyObject *o, converter::rvalue_from_python_stage1_data* data)
//     {
// 	void* storage = ((converter::rvalue_from_python_storage<vector<real> >*)data)->storage.bytes;
//         PyArrayObject *ao = (PyArrayObject*)o;

// 	new (storage) std::vector<std::vector<T> >(int(ao->dimensions[0]),
// 						   std::vector<T>(int(ao->dimensions[1]), 0));
// 	data->convertible = storage;
//     }
// }

struct vec_from_numpy_str {
    static void* convertible(PyObject *o)
    {
        PyArrayObject *ao = (PyArrayObject*)o;
        if (!numpy_satisfy_properties(ao, 1, NULL, npy_real_type(), true))
            return 0;

        return (void*)o;
    }

    static void construct(PyObject *o,
                          converter::rvalue_from_python_stage1_data* data)
    {
        void* storage = ((converter::rvalue_from_python_storage<vector<real> >*)data)->storage.bytes;
        PyArrayObject *ao = (PyArrayObject*)o;

        new (storage) vector<real>(ao->dimensions[0]);

        vector<real> *v = (vector<real>*)storage;

        data->convertible = storage;

        for (int i=0; i<ao->dimensions[0]; i++) {
            (*v)[i] = ((real*)ao->data)[i];
        }
    }

    vec_from_numpy_str()
    {
        converter::registry::push_back(&convertible,
                                       &construct,
                                       type_id<vector<real> >());
    }
};

struct vec_to_numpy_str {
    static PyObject *convert(const vector<real>& v)
    {
        npy_intp dims[] = {v.size()};
        PyArrayObject *ao = (PyArrayObject*)PyArray_SimpleNew(1, dims, npy_real_type());

        for (int i=0; i<v.size(); i++) {
            ((real*)ao->data)[i] = v[i];
        }

        return (PyObject*)ao;
    }
};

PyObject *vecvecvec_to_numpy(vector<vector<vector<real> > > v)
{
    npy_intp dims[] = {v.size(), v[0].size(), v[0][0].size()};

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    for (int k=0; k<dims[2]; k++) {
		((real*)retval->data)[i*dims[0]*dims[1] + j*dims[1] + k] = v[i][j][k];
	    }
	}
    }

    return (PyObject*)retval;
}

PyObject *vecvec_to_numpy(const vector<const vector<real> *> v)
{
    npy_intp dims[] = {v.size(), v[0]->size()};

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    ((real*)retval->data)[i*dims[1] + j] = (*v[i])[j];
	}
    }

    return (PyObject*)retval;
}

PyObject *vecvec_real_to_numpy(vector<vector<real> > v)
{
    npy_intp dims[] = {v.size(), v[0].size()};

    PyArrayObject *retval;
    retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0];i++) {
	for (int j=0; j<dims[1]; j++) {
	    ((real*)retval->data)[i*dims[1] + j] = v[i][j];
	}
    }

    return (PyObject*)retval;
}

PyObject* mxarray2d_to_numpy(mxArray* arr)
{
    /* fucking column major bitches */
    npy_intp dims[] = {arr->Dims[0], arr->Dims[1]};

    PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(2, dims, npy_real_type());
    for (int i=0; i<dims[0]; i++) {
	for (int j=0; j<dims[1]; j++) {
	    real fake;
	    ((real*)retval->data)[i*dims[1] + j] = arr->get2D(i, j, fake);
	}
    }

    return (PyObject*)retval;
}

mxArray* numpy_to_mxarray3d(PyObject *o)
{
    PyArrayObject *ao = (PyArrayObject*)o;

    if (!numpy_satisfy_properties(ao, 3, NULL, npy_real_type(), true)) {
        return NULL;
    }

    int dims[] = {ao->dimensions[0], ao->dimensions[1], ao->dimensions[2]};

    mxArray* ret = mxCreateNumericArray(3, dims, mx_real_type(), mxREAL);
    for (int c=0; c<dims[2]; c++) {
	for (int col=0; col<dims[1]; col++) {
	    for (int row=0; row<dims[0]; row++) {
		ret->set3D(row, col, c, ((real*)ao->data)[row*dims[1]*dims[2] + col*dims[2] + c]);
	    }
	}
    }
    return ret;
}

PyObject* mxarray3d_to_numpy(mxArray* arr)
{
    npy_intp dims[] = {arr->Dims[0], arr->Dims[1], arr->Dims[2]};

    PyArrayObject *retval = (PyArrayObject*)PyArray_SimpleNew(3, dims, npy_real_type());
    for (int c=0; c<dims[2]; c++) {
	for (int col=0; col<dims[1]; col++) {
	    for (int row=0; row<dims[0]; row++) {
		real fake;
		((real*)retval->data)[row*dims[1]*dims[2] + col*dims[2] + c] = \
                    arr->get3D(row, col, c, fake);
	    }
	}
    }
    return (PyObject*)retval;
}

vector<real> numpy_to_vec(PyObject *o)
{
    PyArrayObject *ao = (PyArrayObject*)o;
    if (!numpy_satisfy_properties(ao, 1, NULL, npy_real_type(), true)) {
        return vector<real>();
    }

    vector<real> ret(ao->dimensions[0]);
    for (int i=0; i<ao->dimensions[0]; i++) {
        ret[i] = ((real*)ao->data)[i];
    }
    return ret;
}

PyObject* vec_to_numpy(vector<real> v)
{
    npy_intp dims[] = {v.size()};
    PyArrayObject *ao = (PyArrayObject*)PyArray_SimpleNew(1, dims, npy_real_type());

    for (int i=0; i<v.size(); i++) {
        ((real*)ao->data)[i] = v[i];
    }

    return (PyObject*)ao;
}
<|endoftext|>


<commit_before><commit_msg>Fixed symlink<commit_after><|endoftext|>


<commit_before>/*
 * datasetfibers.cpp
 *
 *  Created on: Dec 12, 2012
 *      Author: Ralph Schurade
 */
#include "datasetfibers.h"

#include "../../gui/gl/fiberrenderer.h"

DatasetFibers::DatasetFibers( QString filename, QVector< QVector< float > > fibs, int numPoints, int numLines ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 )
{
    m_properties.set( Fn::Property::NUM_POINTS, numPoints );
    m_properties.set( Fn::Property::NUM_LINES, numLines );
    m_properties.set( Fn::Property::FIBER_COLORMODE, 0, 0, 2, true );
    m_properties.set( Fn::Property::FIBER_COLOR, QColor( 255, 0, 0 ), true );
}

DatasetFibers::DatasetFibers( QVector< QVector< float > > fibs ) :
    Dataset( QString("new fibers"), Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size();
    }
    m_properties.set( Fn::Property::NUM_POINTS, numPoints );
    m_properties.set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties.set( Fn::Property::FIBER_COLORMODE, 0, 0, 1, true );
    m_properties.set( Fn::Property::FIBER_COLOR, QColor( 255, 0, 0 ), true );
}

DatasetFibers::~DatasetFibers()
{
    m_fibs.clear();
}

QVector< QVector< float > > DatasetFibers::getFibs()
{
    return m_fibs;
}

QVector< QVector< float > > DatasetFibers::getSelectedFibs()
{
    if ( m_renderer == 0 )
    {
        return m_fibs;
    }
    else
    {
        QVector<bool>selected = m_renderer->getSelection();
        QVector<QVector<float> >out;
        for ( int i = 0; i < selected.size(); ++i )
        {
            if ( selected[i] )
            {
                out.push_back( m_fibs[i] );
            }
        }
        return out;
    }
}

void DatasetFibers::draw( QMatrix4x4 mvpMatrix, QMatrix4x4 mvMatrixInverse, QAbstractItemModel* globalModel, QAbstractItemModel* roiModel )
{
    if ( m_renderer == 0 )
    {
        m_renderer = new FiberRenderer( roiModel, m_fibs );
        m_renderer->setModel( globalModel );
        m_renderer->init();
        connect( m_properties.getProperty( Fn::Property::FIBER_COLOR ), SIGNAL( colorChanged( QColor ) ), m_renderer, SLOT( colorChanged( QColor ) ) );
    }
    m_renderer->setRenderParams( m_properties.get( Fn::Property::FIBER_COLORMODE ).toInt() );
    m_renderer->draw( mvpMatrix, mvMatrixInverse );
}

QString DatasetFibers::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}
<commit_msg>fix color mode selection for created fibers<commit_after>/*
 * datasetfibers.cpp
 *
 *  Created on: Dec 12, 2012
 *      Author: Ralph Schurade
 */
#include "datasetfibers.h"

#include "../../gui/gl/fiberrenderer.h"

DatasetFibers::DatasetFibers( QString filename, QVector< QVector< float > > fibs, int numPoints, int numLines ) :
    Dataset( filename, Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 )
{
    m_properties.set( Fn::Property::NUM_POINTS, numPoints );
    m_properties.set( Fn::Property::NUM_LINES, numLines );
    m_properties.set( Fn::Property::FIBER_COLORMODE, 0, 0, 2, true );
    m_properties.set( Fn::Property::FIBER_COLOR, QColor( 255, 0, 0 ), true );
}

DatasetFibers::DatasetFibers( QVector< QVector< float > > fibs ) :
    Dataset( QString("new fibers"), Fn::DatasetType::FIBERS ),
    m_fibs( fibs ),
    m_renderer( 0 )
{
    int numPoints = 0;
    for ( int i = 0; i < fibs.size(); ++i )
    {
        numPoints += fibs[i].size();
    }
    m_properties.set( Fn::Property::NUM_POINTS, numPoints );
    m_properties.set( Fn::Property::NUM_LINES, fibs.size() );
    m_properties.set( Fn::Property::FIBER_COLORMODE, 0, 0, 2, true );
    m_properties.set( Fn::Property::FIBER_COLOR, QColor( 255, 0, 0 ), true );
}

DatasetFibers::~DatasetFibers()
{
    m_fibs.clear();
}

QVector< QVector< float > > DatasetFibers::getFibs()
{
    return m_fibs;
}

QVector< QVector< float > > DatasetFibers::getSelectedFibs()
{
    if ( m_renderer == 0 )
    {
        return m_fibs;
    }
    else
    {
        QVector<bool>selected = m_renderer->getSelection();
        QVector<QVector<float> >out;
        for ( int i = 0; i < selected.size(); ++i )
        {
            if ( selected[i] )
            {
                out.push_back( m_fibs[i] );
            }
        }
        return out;
    }
}

void DatasetFibers::draw( QMatrix4x4 mvpMatrix, QMatrix4x4 mvMatrixInverse, QAbstractItemModel* globalModel, QAbstractItemModel* roiModel )
{
    if ( m_renderer == 0 )
    {
        m_renderer = new FiberRenderer( roiModel, m_fibs );
        m_renderer->setModel( globalModel );
        m_renderer->init();
        connect( m_properties.getProperty( Fn::Property::FIBER_COLOR ), SIGNAL( colorChanged( QColor ) ), m_renderer, SLOT( colorChanged( QColor ) ) );
    }
    m_renderer->setRenderParams( m_properties.get( Fn::Property::FIBER_COLORMODE ).toInt() );
    m_renderer->draw( mvpMatrix, mvMatrixInverse );
}

QString DatasetFibers::getValueAsString( int x, int y, int z )
{
    return QString( "" );
}
<|endoftext|>


<commit_before>#include <iostream>
#include <set>
#include <cassert>

template <typename T>
struct node {
    T data;
    node *left = nullptr, *right = nullptr;
    node(T data): data(data) {}
};

template <typename T>
class tree {
    node<T>* root = nullptr;

public:
    bool contains(const T& data) {
        auto curr = root;
        while (curr != nullptr) {
            if (curr->data == data)
                return true;
            curr = data < curr->data ? curr->left : curr->right;
        }
        return false;
    }

    void insert(T data) {
        auto ptr = &root;
        while (auto curr = *ptr) {
            if (curr->data == data)
                return;
            ptr = data < curr->data ? &curr->left : &curr->right;
        }
        *ptr = new node<T>(data);
    }

    void remove(const T& data) {
        auto ptr = &root;
        while (auto curr = *ptr) {
            if (data == curr->data) {
                if (curr->left == nullptr) {
                    *ptr = curr->right;
                } else if (curr->right == nullptr) {
                    *ptr = curr->left;
                } else {
                    auto l = curr->left, r = l->right;
                    if (r == nullptr) {
                        l->right = curr->right;
                        *ptr = l;
                    } else {
                        while (r->right != nullptr)
                            l = r, r = r->right;
                        l->right = r->left;
                        r->left = curr->left;
                        r->right = curr->right;
                        *ptr = r;
                    }
                }
                delete curr;
                return;
            }
            ptr = data < curr->data ? &curr->left : &curr->right;
        }
    }
};

int main() {
    tree<int> ours;
    std::set<int> theirs;
    int op_counts[] = {0, 0, 0};
    for (int i = 0; i < 100000; ++i) {
        int data = rand() % 100;
        int op = rand() % 3;
        ++op_counts[op];
        if (op == 0) {
            assert(ours.contains(data) == theirs.count(data));
        } else if (op == 1) {
            ours.insert(data);
            theirs.insert(data);
        } else {
            assert(op == 2);
            ours.remove(data);
            theirs.erase(data);
        }
    }

    for (int n : op_counts)
        assert(n > 0);
    std::cout << "All tests passed" << std::endl;
    return 0;
}
<commit_msg>Add parent ptrs to bst; implement iterator<commit_after>#include <iostream>
#include <set>
#include <cassert>

template <typename T>
class tree {

    struct node {
        const T data;
        node *left = nullptr, *right = nullptr, *parent;
        node(T data, node* parent): data(data), parent(parent) {}
    };

    struct iterator {
        node* n;
        iterator(node* n): n(n) {}
        bool operator==(iterator o) const { return n == o.n; }
        bool operator!=(iterator o) const { return n != o.n; }
        const T& operator*() const { return n->data; }
        const T* operator->() const { return &n->data; }
        iterator operator++(int) { auto copy = *this; ++(*this); return copy; }
        iterator& operator++() {
            if (n->right != nullptr) {
                n = n->right;
                while (n->left != nullptr) {
                    n = n->left;
                }
            } else {
                while (n->parent != nullptr && n == n->parent->right)
                    n = n->parent;
                n = n->parent;
            }
            return *this;
        }
    };

    node* root = nullptr;

public:
    bool contains(const T& data) const {
        auto n = root;
        while (n != nullptr) {
            if (n->data == data)
                return true;
            n = data < n->data ? n->left : n->right;
        }
        return false;
    }

    void insert(T data) {
        node* parent = nullptr;
        auto ptr = &root;
        while (auto n = *ptr) {
            if (n->data == data)
                return;
            parent = n;
            ptr = data < n->data ? &n->left : &n->right;
        }
        *ptr = new node(data, parent);
    }

    void remove(const T& data) {
        node* parent = nullptr;
        auto ptr = &root;
        while (auto n = *ptr) {
            if (data == n->data) {
                if (n->left == nullptr && n->right == nullptr) {
                    *ptr = n->right;
                } else if (n->left == nullptr) {
                    *ptr = n->right;
                    n->right->parent = parent;
                } else if (n->right == nullptr) {
                    *ptr = n->left;
                    n->left->parent = parent;
                } else {
                    auto l = n->left, r = l->right;
                    if (r == nullptr) {
                        l->right = n->right;
                        l->parent = parent;
                        n->right->parent = l;
                        *ptr = l;
                    } else {
                        while (r->right != nullptr)
                            l = r, r = r->right;
                        l->right = r->left;
                        if (l->right != nullptr)
                            l->right->parent = l;
                        r->left = n->left;
                        r->right = n->right;
                        r->parent = parent;
                        n->left->parent = r;
                        n->right->parent = r;
                        *ptr = r;
                    }
                }
                delete n;
                return;
            }
            parent = n;
            ptr = data < n->data ? &n->left : &n->right;
        }
    }

    iterator begin() const {
        if (!root)
            return end();
        auto n = root;
        while (n->left != nullptr)
            n = n->left;
        return iterator(n);
    }

    iterator end() const {
        return iterator(nullptr);
    }
};

int main() {
    tree<int> ours;
    std::set<int> theirs;
    int op_counts[] = {0, 0, 0, 0};
    for (int i = 0; i < 1000000; ++i) {
        int data = rand() % 100;
        int op = rand() % 4;
        ++op_counts[op];
        if (op == 0) {
            assert(ours.contains(data) == theirs.count(data));
        } else if (op == 1) {
            ours.insert(data);
            theirs.insert(data);
        } else if (op == 2) {
            ours.remove(data);
            theirs.erase(data);
        } else {
            assert(op == 3);
            auto our_it = ours.begin();
            auto their_it = theirs.begin();
            while (our_it != ours.end() && their_it != theirs.end())
                assert(*our_it++ == *their_it++);
            assert(our_it == ours.end() && their_it == theirs.end());
        }
    }

    for (int n : op_counts)
        assert(n > 0);
    std::cout << "All tests passed" << std::endl;
    return 0;
}
<|endoftext|>


<commit_before>#include <osmium/visitor.hpp>
#include <osmium/index/map/all.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/area/assembler.hpp>

#include "generic_writer.hpp"
#include "generic_handler.hpp"
#include "merged_input.hpp"
#include "write_handler.hpp"

template <typename T>
void apply_reader_simple(osmium::io::Reader &rd, T &h) {
    osmium::apply(rd, h);
}

template <typename T>
void apply_reader_simple_with_location(osmium::io::Reader &rd,
                         osmium::handler::NodeLocationsForWays<T> &l,
                         BaseHandler &h) {
    osmium::apply(rd, l, h);
}

PyObject *invalidLocationExceptionType = NULL;
PyObject *notFoundExceptionType = NULL;

void translator1(osmium::invalid_location const&) {
    PyErr_SetString(invalidLocationExceptionType, "Invalid location");
}

void translator2(osmium::not_found const&) {
    PyErr_SetString(notFoundExceptionType, "Element not found in index");
}

PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj = PyExc_Exception)
{
    using std::string;
    namespace bp = boost::python;

    string scopeName = bp::extract<string>(bp::scope().attr("__name__"));
    string qualifiedName0 = scopeName + "." + name;
    char* qualifiedName1 = const_cast<char*>(qualifiedName0.c_str());

    PyObject* typeObj = PyErr_NewException(qualifiedName1, baseTypeObj, 0);
    if(!typeObj) bp::throw_error_already_set();
    bp::scope().attr(name) = bp::handle<>(bp::borrowed(typeObj));
    return typeObj;
}

#include "index.cc"

BOOST_PYTHON_MODULE(_osmium)
{
    using namespace boost::python;
    docstring_options doc_options(true, true, false);

    invalidLocationExceptionType = createExceptionClass("InvalidLocationError", PyExc_RuntimeError);
    register_exception_translator<osmium::invalid_location>(&translator1);

    notFoundExceptionType = createExceptionClass("NotFoundError", PyExc_KeyError);
    register_exception_translator<osmium::not_found>(&translator2);

    class_<osmium::handler::NodeLocationsForWays<LocationTable>, boost::noncopyable>("NodeLocationsForWays",
            init<LocationTable&>())
        .def("ignore_errors", &osmium::handler::NodeLocationsForWays<LocationTable>::ignore_errors)
    ;

    class_<SimpleHandlerWrap, boost::noncopyable>("SimpleHandler",
        "The most generic of OSM data handlers. For each data type "
        "a callback can be implemented where the object is processed. Note that "
        "all objects that are handed into the handler are only readable and are "
        "only valid until the end of the callback is reached. Any data that "
        "should be retained must be copied into other data structures.")
        .def("apply_file", &SimpleHandlerWrap::apply_file,
              (arg("self"), arg("filename"),
               arg("locations")=false, arg("idx")="sparse_mem_array"),
             "Apply the handler to the given file. If locations is true, then\n"
             "a location handler will be applied before, which saves the node\n"
             "positions. In that case, the type of this position index can be\n"
             "further selected in idx. If an area callback is implemented, then\n"
             "the file will be scanned twice and a location handler and a\n"
             "handler for assembling multipolygons and areas from ways will\n"
             "be executed.")
        .def("apply_buffer", &SimpleHandlerWrap::apply_buffer,
              (arg("self"), arg("buffer"), arg("format"),
               arg("locations")=false, arg("idx")="sparse_mem_array"),
             "Apply the handler to a string buffer. The buffer must be a\n"
             "byte string.")
    ;
    def("apply", &apply_reader_simple<BaseHandler>,
        "Apply a chain of handlers.");
    def("apply", &apply_reader_simple<osmium::handler::NodeLocationsForWays<LocationTable>>);
    def("apply", &apply_reader_simple_with_location<LocationTable>);

    class_<SimpleWriterWrap, boost::noncopyable>("SimpleWriter",
        "The most generic class to write osmium objects into a file. The writer "
        "takes a file name as its mandatory parameter. The file must not yet "
        "exist. The file type to output is determined from the file extension. "
        "The second (optional) parameter is the buffer size. osmium caches the "
        "output data in an internal memory buffer before writing it on disk. This "
        "parameter allows changing the default buffer size of 4MB. Larger buffers "
        "are normally better but you should be aware that there are normally multiple "
        "buffers in use during the write process.",
        init<const char*, unsigned long>())
        .def(init<const char*>())
        .def("add_node", &SimpleWriterWrap::add_node,
             (arg("self"), arg("node")),
             "Add a new node to the file. The node may be an ``osmium.osm.Node`` object, "
             "an ``osmium.osm.mutable.Node`` object or any other Python object that "
             "implements the same attributes.")
        .def("add_way", &SimpleWriterWrap::add_way,
             (arg("self"), arg("way")),
             "Add a new way to the file. The way may be an ``osmium.osm.Way`` object, "
             "an ``osmium.osm.mutable.Way`` object or any other Python object that "
             "implements the same attributes.")
        .def("add_relation", &SimpleWriterWrap::add_relation,
             (arg("self"), arg("relation")),
             "Add a new relation to the file. The relation may be an "
             "``osmium.osm.Relation`` object, an ``osmium.osm.mutable.Way`` "
             "object or any other Python object that implements the same attributes.")
        .def("close", &SimpleWriterWrap::close,
             args("self"),
             "Flush the remaining buffers and close the writer. While it is not "
             "strictly necessary to call this function explicitly, it is still "
             "strongly recommended to close the writer as soon as possible, so "
             "that the buffer memory can be freed.")
    ;

    class_<WriteHandler, boost::noncopyable>("WriteHandler",
        "Handler function that writes all data directly to a file."
        "The handler takes a file name as its mandatory parameter. The file "
        "must not yet exist. The file type to output is determined from the "
        "file extension. "
        "The second (optional) parameter is the buffer size. osmium caches the "
        "output data in an internal memory buffer before writing it on disk. This "
        "parameter allows changing the default buffer size of 4MB. Larger buffers "
        "are normally better but you should be aware that there are normally multiple "
        "buffers in use during the write process.",
        init<const char*, unsigned long>())
        .def(init<const char*>())
        .def("close", &WriteHandler::close,
             args("self"),
             "Flush the remaining buffers and close the writer. While it is not "
             "strictly necessary to call this function explicitly, it is still "
             "strongly recommended to close the writer as soon as possible, so "
             "that the buffer memory can be freed.")
    ;

    class_<pyosmium::MergeInputReader, boost::noncopyable>("MergeInputReader",
        "Collects data from multiple input files and sorts and optionally "
        "deduplicates the data before applying it to a handler.")
        .def("apply", &pyosmium::MergeInputReader::apply,
            (arg("self"), arg("handler"), arg("simplify")=true),
            "Apply collected data to a handler. The data will be sorted first. "
            "If `simplify` is true (default) then duplicates will be eliminated "
            "and only the newest version of each object kept. After the data "
            "has been applied the buffer of the MergeInputReader is empty and "
            "new data can be added for the next round of application.")
        .def("apply_to_reader", &pyosmium::MergeInputReader::apply_to_reader,
            (arg("self"), arg("reader"), arg("writer"), arg("with_history")=false),
            "Apply the collected data to data from the given `reader` and write "
            "the result to `writer`. This function can be used to merge the diff "
            "data together with other OSM data (for example when updating a "
            "planet file. If `with_history` is true, then the collected data will "
            "be applied verbatim without removing duplicates. This is important "
            "when using OSM history files as input.")
        .def("add_file", &pyosmium::MergeInputReader::add_file,
            (arg("self"), arg("file")),
             "Add data from a file to the internal cache. The file type will be "
             "determined from the file extension.")
        .def("add_buffer", &pyosmium::MergeInputReader::add_buffer,
             (arg("self"), arg("buffer"), arg("format")),
             "Add data from a byte buffer. The format of the input data must "
             "be given in the `format` argument as a string. The data will be "
             "copied into internal buffers, so that the input buffer can be "
             "safely discarded after the function has been called.")
    ;
}
<commit_msg>add documentation for SimpleHandler callbacks back<commit_after>#include <osmium/visitor.hpp>
#include <osmium/index/map/all.hpp>
#include <osmium/handler/node_locations_for_ways.hpp>
#include <osmium/area/multipolygon_collector.hpp>
#include <osmium/area/assembler.hpp>

#include "generic_writer.hpp"
#include "generic_handler.hpp"
#include "merged_input.hpp"
#include "write_handler.hpp"

template <typename T>
void apply_reader_simple(osmium::io::Reader &rd, T &h) {
    osmium::apply(rd, h);
}

template <typename T>
void apply_reader_simple_with_location(osmium::io::Reader &rd,
                         osmium::handler::NodeLocationsForWays<T> &l,
                         BaseHandler &h) {
    osmium::apply(rd, l, h);
}

PyObject *invalidLocationExceptionType = NULL;
PyObject *notFoundExceptionType = NULL;

void translator1(osmium::invalid_location const&) {
    PyErr_SetString(invalidLocationExceptionType, "Invalid location");
}

void translator2(osmium::not_found const&) {
    PyErr_SetString(notFoundExceptionType, "Element not found in index");
}

PyObject* createExceptionClass(const char* name, PyObject* baseTypeObj = PyExc_Exception)
{
    using std::string;
    namespace bp = boost::python;

    string scopeName = bp::extract<string>(bp::scope().attr("__name__"));
    string qualifiedName0 = scopeName + "." + name;
    char* qualifiedName1 = const_cast<char*>(qualifiedName0.c_str());

    PyObject* typeObj = PyErr_NewException(qualifiedName1, baseTypeObj, 0);
    if(!typeObj) bp::throw_error_already_set();
    bp::scope().attr(name) = bp::handle<>(bp::borrowed(typeObj));
    return typeObj;
}

#include "index.cc"

BOOST_PYTHON_MODULE(_osmium)
{
    using namespace boost::python;
    docstring_options doc_options(true, true, false);

    invalidLocationExceptionType = createExceptionClass("InvalidLocationError", PyExc_RuntimeError);
    register_exception_translator<osmium::invalid_location>(&translator1);

    notFoundExceptionType = createExceptionClass("NotFoundError", PyExc_KeyError);
    register_exception_translator<osmium::not_found>(&translator2);

    class_<osmium::handler::NodeLocationsForWays<LocationTable>, boost::noncopyable>("NodeLocationsForWays",
            init<LocationTable&>())
        .def("ignore_errors", &osmium::handler::NodeLocationsForWays<LocationTable>::ignore_errors)
    ;

    class_<SimpleHandlerWrap, boost::noncopyable>("SimpleHandler",
        "The most generic of OSM data handlers. Derive your data processor "
        "from this class and implement callbacks for each object type you are "
        "interested in. The following data types are recognised: \n"
        " `node`, `way`, `relation`, `area` and `changeset`.\n "
        "A callback takes exactly one parameter which is the object. Note that "
        "all objects that are handed into the handler are only readable and are "
        "only valid until the end of the callback is reached. Any data that "
        "should be retained must be copied into other data structures.")
        .def("apply_file", &SimpleHandlerWrap::apply_file,
              (arg("self"), arg("filename"),
               arg("locations")=false, arg("idx")="sparse_mem_array"),
             "Apply the handler to the given file. If locations is true, then\n"
             "a location handler will be applied before, which saves the node\n"
             "positions. In that case, the type of this position index can be\n"
             "further selected in idx. If an area callback is implemented, then\n"
             "the file will be scanned twice and a location handler and a\n"
             "handler for assembling multipolygons and areas from ways will\n"
             "be executed.")
        .def("apply_buffer", &SimpleHandlerWrap::apply_buffer,
              (arg("self"), arg("buffer"), arg("format"),
               arg("locations")=false, arg("idx")="sparse_mem_array"),
             "Apply the handler to a string buffer. The buffer must be a\n"
             "byte string.")
    ;
    def("apply", &apply_reader_simple<BaseHandler>,
        "Apply a chain of handlers.");
    def("apply", &apply_reader_simple<osmium::handler::NodeLocationsForWays<LocationTable>>);
    def("apply", &apply_reader_simple_with_location<LocationTable>);

    class_<SimpleWriterWrap, boost::noncopyable>("SimpleWriter",
        "The most generic class to write osmium objects into a file. The writer "
        "takes a file name as its mandatory parameter. The file must not yet "
        "exist. The file type to output is determined from the file extension. "
        "The second (optional) parameter is the buffer size. osmium caches the "
        "output data in an internal memory buffer before writing it on disk. This "
        "parameter allows changing the default buffer size of 4MB. Larger buffers "
        "are normally better but you should be aware that there are normally multiple "
        "buffers in use during the write process.",
        init<const char*, unsigned long>())
        .def(init<const char*>())
        .def("add_node", &SimpleWriterWrap::add_node,
             (arg("self"), arg("node")),
             "Add a new node to the file. The node may be an ``osmium.osm.Node`` object, "
             "an ``osmium.osm.mutable.Node`` object or any other Python object that "
             "implements the same attributes.")
        .def("add_way", &SimpleWriterWrap::add_way,
             (arg("self"), arg("way")),
             "Add a new way to the file. The way may be an ``osmium.osm.Way`` object, "
             "an ``osmium.osm.mutable.Way`` object or any other Python object that "
             "implements the same attributes.")
        .def("add_relation", &SimpleWriterWrap::add_relation,
             (arg("self"), arg("relation")),
             "Add a new relation to the file. The relation may be an "
             "``osmium.osm.Relation`` object, an ``osmium.osm.mutable.Way`` "
             "object or any other Python object that implements the same attributes.")
        .def("close", &SimpleWriterWrap::close,
             args("self"),
             "Flush the remaining buffers and close the writer. While it is not "
             "strictly necessary to call this function explicitly, it is still "
             "strongly recommended to close the writer as soon as possible, so "
             "that the buffer memory can be freed.")
    ;

    class_<WriteHandler, boost::noncopyable>("WriteHandler",
        "Handler function that writes all data directly to a file."
        "The handler takes a file name as its mandatory parameter. The file "
        "must not yet exist. The file type to output is determined from the "
        "file extension. "
        "The second (optional) parameter is the buffer size. osmium caches the "
        "output data in an internal memory buffer before writing it on disk. This "
        "parameter allows changing the default buffer size of 4MB. Larger buffers "
        "are normally better but you should be aware that there are normally multiple "
        "buffers in use during the write process.",
        init<const char*, unsigned long>())
        .def(init<const char*>())
        .def("close", &WriteHandler::close,
             args("self"),
             "Flush the remaining buffers and close the writer. While it is not "
             "strictly necessary to call this function explicitly, it is still "
             "strongly recommended to close the writer as soon as possible, so "
             "that the buffer memory can be freed.")
    ;

    class_<pyosmium::MergeInputReader, boost::noncopyable>("MergeInputReader",
        "Collects data from multiple input files and sorts and optionally "
        "deduplicates the data before applying it to a handler.")
        .def("apply", &pyosmium::MergeInputReader::apply,
            (arg("self"), arg("handler"), arg("simplify")=true),
            "Apply collected data to a handler. The data will be sorted first. "
            "If `simplify` is true (default) then duplicates will be eliminated "
            "and only the newest version of each object kept. After the data "
            "has been applied the buffer of the MergeInputReader is empty and "
            "new data can be added for the next round of application.")
        .def("apply_to_reader", &pyosmium::MergeInputReader::apply_to_reader,
            (arg("self"), arg("reader"), arg("writer"), arg("with_history")=false),
            "Apply the collected data to data from the given `reader` and write "
            "the result to `writer`. This function can be used to merge the diff "
            "data together with other OSM data (for example when updating a "
            "planet file. If `with_history` is true, then the collected data will "
            "be applied verbatim without removing duplicates. This is important "
            "when using OSM history files as input.")
        .def("add_file", &pyosmium::MergeInputReader::add_file,
            (arg("self"), arg("file")),
             "Add data from a file to the internal cache. The file type will be "
             "determined from the file extension.")
        .def("add_buffer", &pyosmium::MergeInputReader::add_buffer,
             (arg("self"), arg("buffer"), arg("format")),
             "Add data from a byte buffer. The format of the input data must "
             "be given in the `format` argument as a string. The data will be "
             "copied into internal buffers, so that the input buffer can be "
             "safely discarded after the function has been called.")
    ;
}
<|endoftext|>


<commit_before>#include "Scaly.h"
namespace scaly {

// Some statistics
static int oversizedPagesAllocated;
static int oversizedBytesAllocated;
static int oversizedPagesDeallocated;
static int oversizedBytesDeallocated;
static int pagesDisposed;
static int extensionPagesAllocated;

extern __thread _Task* __CurrentTask;

_Page::_Page() {
	reset(); }

void _Page::reset() {
    // Allocate default extension page pointer and initialize it to zero
    *getLastExtensionPageLocation() = 0;
    extensions = 0;
    // Allocate space for the page itself
    setNextObject(align((char*)this + sizeof(_Page)));
    currentPage = this; }

void _Page::clear() {
    deallocatePageExtensions();
    reset(); }

_Page** _Page::getLastExtensionPageLocation() {
    // Frome where the ordinary extension page is pointed to
    return ((_Page**) ((char*) this + _pageSize)) - 1; }

void* _Page::operator new(size_t size, void* location) {
    return location; }

void* _Page::getNextObject() {
    return (char*)this + nextObjectOffset; }

void _Page::setNextObject(void* object) {
    nextObjectOffset = (char*)object - (char*)this; }

_Page** _Page::getNextExtensionPageLocation() {
    return getLastExtensionPageLocation() - extensions - 1; }

void* _Page::allocateObject(size_t size) {
    if (this != currentPage) {
        // We're already known to be full, so we delegate to the current page
        void* newObject = currentPage->allocateObject(size);
        // Possibly our current page was also full so we propagate back the new current page
        _Page* allocatingPage = ((Object*)newObject)->getPage();
        if ((allocatingPage != currentPage) && (newObject != allocatingPage))
            currentPage = allocatingPage;
        return newObject; }

    // Try to allocate from ourselves
    void* nextLocation = align((char*)getNextObject() + size);
    if (nextLocation <= (void*) getNextExtensionPageLocation()) {
        void* location = getNextObject();
        setNextObject(nextLocation);
        return location; }

    // So the space did not fit.

    // Calculate gross size to decide whether we're oversized
    size_t grossSize = sizeof(_Page) + size + sizeof(_Page**) + _alignment;
    if (grossSize > _pageSize) {
        if ((_Page**)getNextObject() == getLastExtensionPageLocation()) {
            // Allocate an extension page with default size
            _Page* defaultExtensionPage = allocateExtensionPage();
            // Make it our new current
            currentPage = defaultExtensionPage;
            // Try again with the new extension page
            return defaultExtensionPage->allocateObject(size); }

        // We allocate and free oversized objects directly.
        void* object;
        posix_memalign(&object, _pageSize, size);
        *getNextExtensionPageLocation() = (_Page*)object;
        extensions++;
        return object; }
    // So we're not oversized. Allocate the standard extension page.
    _Page* extensionPage = allocateExtensionPage();
    this->currentPage = extensionPage;
    // And allocate at last.
    return extensionPage->allocateObject(size); }

_Page* _Page::allocateExtensionPage() {
    _Page* pageLocation = __CurrentTask->getExtensionPage();
    if (!pageLocation)
        return 0;
    _Page* extensionPage = new (pageLocation) _Page();
    *getLastExtensionPageLocation() = pageLocation;
    return extensionPage; }

_Page* _Page::allocateExclusivePage() {
    if (this != currentPage)
        // We're already known to be full, so we delegate to the current page
        return currentPage->allocateExclusivePage();

    // Check first whether we need an ordinary extension
    if ((_Page**)getNextObject() == getLastExtensionPageLocation()) {
        // Allocate an extension page with default size
        _Page* defaultExtensionPage = allocateExtensionPage();
        // Make it our new current
        currentPage = defaultExtensionPage;
        // Try again with the new extension page
        return defaultExtensionPage->allocateExclusivePage(); }

    _Page* pageLocation = __CurrentTask->getExtensionPage();
    if (!pageLocation)
        return 0;

    _Page* exclusivePage = new (pageLocation) _Page();
    *getNextExtensionPageLocation() = pageLocation;
    extensions++;
    return exclusivePage; }

bool _Page::extend(void* address, size_t size) {
    if (!size)
        size = 1;
    void* nextLocation = align((char*) address + size);
    // If nextObject would not change because of the alignment, that's it
    if (nextLocation == (void*)getNextObject())
        return true;
    // If nextObject is already higher, other objects were allocated in the meantime
    if (nextLocation < getNextObject())
        return false;
    // Now we still have to check whether we still would have space left
    if (nextLocation >= (void*) getNextExtensionPageLocation())
        return false;
    // Allocate the extension
    setNextObject(nextLocation);
    return true; }

void _Page::deallocatePageExtensions() {
    for (_Page* page = this; page;) {
        _Page* nextExtensionPage = *page->getLastExtensionPageLocation();
        deallocateExtensionsOfPage(page);
        if (page != this)
            forget(page);
        page = nextExtensionPage; } }

void _Page::deallocateExtensionsOfPage(_Page* page) {
    // Deallocate the oversized or exclusive pages
    for (_Page** ppPage = page->getLastExtensionPageLocation() - 1; ppPage > page->getNextExtensionPageLocation(); ppPage--)
        forget(*ppPage); }

void _Page::forget(_Page* page) {
    __CurrentTask->releaseExtensionPage(page); }

bool _Page::reclaimArray(void* address) {
    if (currentPage->freeExtensionPage((_Page*)address))
        return true;
    for (_Page* page = this; page; page = *getLastExtensionPageLocation())
        if (page->freeExtensionPage(page))
            return true; }

_Page* _Page::getPage(void* address) {
    return (_Page*) (((intptr_t)address) & ~(intptr_t)(_pageSize - 1)); }

bool _Page::freeExtensionPage(_Page* _page) {
    // Find the extension Page pointer
    _Page** extensionPosition = getLastExtensionPageLocation() - 1;
    while (extensionPosition > getNextExtensionPageLocation()) {
        if (*extensionPosition == _page)
            break;
        extensionPosition--; }
    if (extensionPosition == getNextExtensionPageLocation())
        return false;

    // Shift the remaining array one position up
    for (_Page** shiftedPosition = extensionPosition; shiftedPosition > getNextExtensionPageLocation(); shiftedPosition--)
        *shiftedPosition = *(shiftedPosition - 1);
    // Make room for one more extension
    extensions--;
    forget(_page);
    return true; }

} // namespace
<commit_msg>some simplifications<commit_after>#include "Scaly.h"
namespace scaly {

extern __thread _Task* __CurrentTask;

_Page::_Page() {
	reset(); }

void _Page::reset() {
    // Allocate default extension page pointer and initialize it to zero
    *getLastExtensionPageLocation() = 0;
    extensions = 0;
    nextObjectOffset = sizeof(_Page);
    currentPage = this; }

void _Page::clear() {
    deallocatePageExtensions();
    reset(); }

_Page** _Page::getLastExtensionPageLocation() {
    // Frome where the ordinary extension page is pointed to
    return ((_Page**) ((char*) this + _pageSize)) - 1; }

void* _Page::operator new(size_t size, void* location) {
    return location; }

void* _Page::getNextObject() {
    return (char*)this + nextObjectOffset; }

void _Page::setNextObject(void* object) {
    nextObjectOffset = (char*)object - (char*)this; }

_Page** _Page::getNextExtensionPageLocation() {
    return getLastExtensionPageLocation() - extensions - 1; }

void* _Page::allocateObject(size_t size) {
    if (this != currentPage) {
        // We're already known to be full, so we delegate to the current page
        void* newObject = currentPage->allocateObject(size);
        // Possibly our current page was also full so we propagate back the new current page
        _Page* allocatingPage = ((Object*)newObject)->getPage();
        if ((allocatingPage != currentPage) && (newObject != allocatingPage))
            currentPage = allocatingPage;
        return newObject; }

    // Try to allocate from ourselves
    void* nextLocation = align((char*)getNextObject() + size);
    if (nextLocation <= (void*) getNextExtensionPageLocation()) {
        void* location = getNextObject();
        setNextObject(nextLocation);
        return location; }

    // So the space did not fit.

    // Calculate gross size to decide whether we're oversized
    size_t grossSize = sizeof(_Page) + size + sizeof(_Page**) + _alignment;
    if (grossSize > _pageSize) {
        if ((_Page**)getNextObject() == getLastExtensionPageLocation()) {
            // Allocate an extension page with default size
            _Page* defaultExtensionPage = allocateExtensionPage();
            // Make it our new current
            currentPage = defaultExtensionPage;
            // Try again with the new extension page
            return defaultExtensionPage->allocateObject(size); }

        // We allocate and free oversized objects directly.
        void* object;
        posix_memalign(&object, _pageSize, size);
        *getNextExtensionPageLocation() = (_Page*)object;
        extensions++;
        return object; }
    // So we're not oversized. Allocate the standard extension page.
    _Page* extensionPage = allocateExtensionPage();
    this->currentPage = extensionPage;
    // And allocate at last.
    return extensionPage->allocateObject(size); }

_Page* _Page::allocateExtensionPage() {
    _Page* pageLocation = __CurrentTask->getExtensionPage();
    if (!pageLocation)
        return 0;
    _Page* extensionPage = new (pageLocation) _Page();
    *getLastExtensionPageLocation() = pageLocation;
    return extensionPage; }

_Page* _Page::allocateExclusivePage() {
    if (this != currentPage)
        // We're already known to be full, so we delegate to the current page
        return currentPage->allocateExclusivePage();

    // Check first whether we need an ordinary extension
    if ((_Page**)getNextObject() == getLastExtensionPageLocation()) {
        // Allocate an extension page with default size
        _Page* defaultExtensionPage = allocateExtensionPage();
        // Make it our new current
        currentPage = defaultExtensionPage;
        // Try again with the new extension page
        return defaultExtensionPage->allocateExclusivePage(); }

    _Page* pageLocation = __CurrentTask->getExtensionPage();
    if (!pageLocation)
        return 0;

    _Page* exclusivePage = new (pageLocation) _Page();
    *getNextExtensionPageLocation() = pageLocation;
    extensions++;
    return exclusivePage; }

bool _Page::extend(void* address, size_t size) {
    if (!size)
        size = 1;
    void* nextLocation = align((char*) address + size);
    // If nextObject would not change because of the alignment, that's it
    if (nextLocation == (void*)getNextObject())
        return true;
    // If nextObject is already higher, other objects were allocated in the meantime
    if (nextLocation < getNextObject())
        return false;
    // Now we still have to check whether we still would have space left
    if (nextLocation >= (void*) getNextExtensionPageLocation())
        return false;
    // Allocate the extension
    setNextObject(nextLocation);
    return true; }

void _Page::deallocatePageExtensions() {
    for (_Page* page = this; page;) {
        _Page* nextExtensionPage = *page->getLastExtensionPageLocation();
        deallocateExtensionsOfPage(page);
        if (page != this)
            forget(page);
        page = nextExtensionPage; } }

void _Page::deallocateExtensionsOfPage(_Page* page) {
    // Deallocate the oversized or exclusive pages
    for (_Page** ppPage = page->getLastExtensionPageLocation() - 1; ppPage > page->getNextExtensionPageLocation(); ppPage--)
        forget(*ppPage); }

void _Page::forget(_Page* page) {
    __CurrentTask->releaseExtensionPage(page); }

bool _Page::reclaimArray(void* address) {
    if (currentPage->freeExtensionPage((_Page*)address))
        return true;
    for (_Page* page = this; page; page = *getLastExtensionPageLocation())
        if (page->freeExtensionPage(page))
            return true; }

_Page* _Page::getPage(void* address) {
    return (_Page*) (((intptr_t)address) & ~(intptr_t)(_pageSize - 1)); }

bool _Page::freeExtensionPage(_Page* _page) {
    // Find the extension Page pointer
    _Page** extensionPosition = getLastExtensionPageLocation() - 1;
    while (extensionPosition > getNextExtensionPageLocation()) {
        if (*extensionPosition == _page)
            break;
        extensionPosition--; }
    if (extensionPosition == getNextExtensionPageLocation())
        return false;

    // Shift the remaining array one position up
    for (_Page** shiftedPosition = extensionPosition; shiftedPosition > getNextExtensionPageLocation(); shiftedPosition--)
        *shiftedPosition = *(shiftedPosition - 1);
    // Make room for one more extension
    extensions--;
    forget(_page);
    return true; }

} // namespace
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_pool.h"

void TPool::setDrinkUnits(int n)
{
  setMaxDrinkUnits(n);
  TBaseCup::setDrinkUnits(n);
  setVolume(getVolume() + (getDrinkUnits() * SIP_VOLUME));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::addToDrinkUnits(int n)
{
  addToMaxDrinkUnits(n);
  TBaseCup::addToDrinkUnits(n);
  setVolume(getVolume() + (getDrinkUnits() * SIP_VOLUME));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::setDrinkType(liqTypeT n)
{
  TBaseCup::setDrinkType(n);
  updateDesc();
}

// the best way to do this would be to explicitly set the proper weight in the
// accessors, rather than using weightChangeObject.  It is prone to float
// rounding errors and some functions don't even bother to use it (ie, pour,
// which I fixed).  But instead of recoding everything, I'll just put this here
// so that pools don't generate errors in weightChangeObject.
void TPool::weightChangeObject(float fWeight)
{
  setWeight(obj_index[getItemIndex()].weight);
  TBaseCup::weightChangeObject(getDrinkUnits() * SIP_WEIGHT);
}

int TPool::getDrinkIndex() const
{
  int drinkunits=getDrinkUnits();

  if(drinkunits<=0){
    return 0;
  } else if(drinkunits<=5){
    return 1;
  } else if(drinkunits<=10){
    return 2;
  } else if(drinkunits<=25){
    return 3;
  } else if(drinkunits<=50){
    return 4;
  } else if(drinkunits<=100){
    return 5;
  } else if(drinkunits<=250){
    return 6;
  } else if(drinkunits<=1000){
    return 7;
  } else if(drinkunits<=10000){
    return 8;
  } else if(drinkunits<=25000){
    return 9;
  } else {
    return 10;
  }
}

void TPool::updateDesc()
{
  int drinkindex=getDrinkIndex();
  char buf[256];
  const char *liqname=DrinkInfo[getDrinkType()]->name;

  const char *poolname [] =
  {
    "a few drops of %s",
    "a tiny puddle of %s",
    "a small puddle of %s",
    "a puddle of %s",
    "a fair sized puddle of %s",
    "a big pool of %s",
    "a large pool of %s",
    "a huge pool of %s",
    "a massive pool of %s",
    "a tremendously huge pool of %s",
    "a veritable ocean of %s"
  };

  const char *pooldesc [] =
  {
    "A few drops of %s sprinkle the ground here and are fading fast.",
    "A tiny puddle of %s has gathered here.",
    "A small puddle of %s is here.",
    "A puddle of %s is here.",
    "A fair sized puddle of %s is here.",
    "A big pool of %s is here.",
    "A large pool of %s is here.",
    "A huge pool of %s is here.",
    "A massive pool of %s is here.",
    "A tremendously huge pool of %s dominates the area.",
    "A veritable ocean of %s covers the area."
  };

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    name = mud_str_dup(obj_index[getItemIndex()].name);
    ex_description = NULL;
    action_description = NULL;
  }

  sprintf(buf, poolname[drinkindex], liqname);
  shortDescr = mud_str_dup(buf);

  sprintf(buf, pooldesc[drinkindex], liqname);
  setDescr(mud_str_dup(buf));
}

bool TPool::isPluralItem() const
{
  // a few drops of blood
  if (getDrinkIndex() == 0)
    return TRUE;

  // otherwise, make recursive
  return TBaseCup::isPluralItem();
}

int TBeing::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=roomp->getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, "dropPool(): No object (%d) in database!", GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *roomp += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;
}

void TPool::decayMe()
{
  int drinkunits=getDrinkUnits();

  // check for non-decaying pools
  if (isDrinkConFlag(DRINK_PERM))
    return;

  if(drinkunits<=0)
    setDrinkUnits(0);
  else if(drinkunits<25)
    addToDrinkUnits(-1);
  else // large pools evaporate faster
    addToDrinkUnits(-(drinkunits/25));
}

void TPool::initPool(int amt, liqTypeT liq)
{
  string buf;

  swapToStrung();
  remObjStat(ITEM_TAKE);
  setDrinkType(liq);
  canBeSeen = 1;
  setMaterial(MAT_WATER);

  ssprintf(buf, "pool puddle %s %s",
	   DrinkInfo[liq]->name,
	   DrinkInfo[liq]->color);
  delete [] name;
  name = mud_str_dup(buf.c_str());

  fillMeAmount(amt, liq);
}

TPool::TPool() :
  TBaseCup()
{
}

TPool::TPool(const TPool &a) :
  TBaseCup(a)
{
}

TPool & TPool::operator=(const TPool &a)
{
  if (this == &a) return *this;
  TBaseCup::operator=(a);
  return *this;
}

TPool::~TPool()
{
}

void TPool::fillMeAmount(int amt, liqTypeT liq)
{
  setDrinkType(liq);
  addToDrinkUnits(amt);

  weightChangeObject(amt * SIP_WEIGHT);
}

<commit_msg>stripped color codes from pool names<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "obj_pool.h"

void TPool::setDrinkUnits(int n)
{
  setMaxDrinkUnits(n);
  TBaseCup::setDrinkUnits(n);
  setVolume(getVolume() + (getDrinkUnits() * SIP_VOLUME));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::addToDrinkUnits(int n)
{
  addToMaxDrinkUnits(n);
  TBaseCup::addToDrinkUnits(n);
  setVolume(getVolume() + (getDrinkUnits() * SIP_VOLUME));
  weightChangeObject(0);
  updateDesc();
  obj_flags.decay_time=getDrinkUnits();
}

void TPool::setDrinkType(liqTypeT n)
{
  TBaseCup::setDrinkType(n);
  updateDesc();
}

// the best way to do this would be to explicitly set the proper weight in the
// accessors, rather than using weightChangeObject.  It is prone to float
// rounding errors and some functions don't even bother to use it (ie, pour,
// which I fixed).  But instead of recoding everything, I'll just put this here
// so that pools don't generate errors in weightChangeObject.
void TPool::weightChangeObject(float fWeight)
{
  setWeight(obj_index[getItemIndex()].weight);
  TBaseCup::weightChangeObject(getDrinkUnits() * SIP_WEIGHT);
}

int TPool::getDrinkIndex() const
{
  int drinkunits=getDrinkUnits();

  if(drinkunits<=0){
    return 0;
  } else if(drinkunits<=5){
    return 1;
  } else if(drinkunits<=10){
    return 2;
  } else if(drinkunits<=25){
    return 3;
  } else if(drinkunits<=50){
    return 4;
  } else if(drinkunits<=100){
    return 5;
  } else if(drinkunits<=250){
    return 6;
  } else if(drinkunits<=1000){
    return 7;
  } else if(drinkunits<=10000){
    return 8;
  } else if(drinkunits<=25000){
    return 9;
  } else {
    return 10;
  }
}

void TPool::updateDesc()
{
  int drinkindex=getDrinkIndex();
  char buf[256];
  const char *liqname=DrinkInfo[getDrinkType()]->name;

  const char *poolname [] =
  {
    "a few drops of %s",
    "a tiny puddle of %s",
    "a small puddle of %s",
    "a puddle of %s",
    "a fair sized puddle of %s",
    "a big pool of %s",
    "a large pool of %s",
    "a huge pool of %s",
    "a massive pool of %s",
    "a tremendously huge pool of %s",
    "a veritable ocean of %s"
  };

  const char *pooldesc [] =
  {
    "A few drops of %s sprinkle the ground here and are fading fast.",
    "A tiny puddle of %s has gathered here.",
    "A small puddle of %s is here.",
    "A puddle of %s is here.",
    "A fair sized puddle of %s is here.",
    "A big pool of %s is here.",
    "A large pool of %s is here.",
    "A huge pool of %s is here.",
    "A massive pool of %s is here.",
    "A tremendously huge pool of %s dominates the area.",
    "A veritable ocean of %s covers the area."
  };

  if (isObjStat(ITEM_STRUNG)) {
    delete [] shortDescr;
    delete [] descr;

    extraDescription *exd;
    while ((exd = ex_description)) {
      ex_description = exd->next;
      delete exd;
    }
    ex_description = NULL;
    delete [] action_description;
    action_description = NULL;
  } else {
    addObjStat(ITEM_STRUNG);
    name=mud_str_dup(obj_index[getItemIndex()].name);
    ex_description = NULL;
    action_description = NULL;
  }

  sprintf(buf, poolname[drinkindex], liqname);
  shortDescr = mud_str_dup(buf);

  sprintf(buf, pooldesc[drinkindex], liqname);
  setDescr(mud_str_dup(buf));
}

bool TPool::isPluralItem() const
{
  // a few drops of blood
  if (getDrinkIndex() == 0)
    return TRUE;

  // otherwise, make recursive
  return TBaseCup::isPluralItem();
}

int TBeing::dropPool(int amt, liqTypeT liq)
{
  TPool *pool=NULL;
  TThing *t;
  TObj *obj;

  if(amt==0)
    return FALSE;

  /* look for preexisting pool */
  for(t=roomp->getStuff();t;t=t->nextThing){
    TPool *tp = dynamic_cast<TPool *>(t);
    if (tp && (tp->getDrinkType() == liq)){
      pool=tp;
      break;
    }
  }

  if(!pool){
    // create new pool
#if 1
// builder port uses stripped down database which was causing problems
// hence this setup instead.
    int robj = real_object(GENERIC_POOL);
    if (robj < 0 || robj >= (signed int) obj_index.size()) {
      vlogf(LOG_BUG, "dropPool(): No object (%d) in database!", GENERIC_POOL);
      return false;
    }

    obj = read_object(robj, REAL);
#else
    obj = read_object(GENERIC_POOL, VIRTUAL);
#endif
    pool = dynamic_cast<TPool *>(obj);
    if (!pool)
      return false;
    pool->initPool(amt, liq);

    *roomp += *pool;
  } else {
    pool->fillMeAmount(amt, liq);
  }

  return TRUE;
}

void TPool::decayMe()
{
  int drinkunits=getDrinkUnits();

  // check for non-decaying pools
  if (isDrinkConFlag(DRINK_PERM))
    return;

  if(drinkunits<=0)
    setDrinkUnits(0);
  else if(drinkunits<25)
    addToDrinkUnits(-1);
  else // large pools evaporate faster
    addToDrinkUnits(-(drinkunits/25));
}

void TPool::initPool(int amt, liqTypeT liq)
{
  string buf;

  swapToStrung();
  remObjStat(ITEM_TAKE);
  setDrinkType(liq);
  canBeSeen = 1;
  setMaterial(MAT_WATER);

  ssprintf(buf, "pool puddle %s %s",
	   stripColorCodes(DrinkInfo[liq]->name).c_str(),
	   stripColorCodes(DrinkInfo[liq]->color).c_str());
  delete [] name;
  name = mud_str_dup(buf.c_str());

  fillMeAmount(amt, liq);
}

TPool::TPool() :
  TBaseCup()
{
}

TPool::TPool(const TPool &a) :
  TBaseCup(a)
{
}

TPool & TPool::operator=(const TPool &a)
{
  if (this == &a) return *this;
  TBaseCup::operator=(a);
  return *this;
}

TPool::~TPool()
{
}

void TPool::fillMeAmount(int amt, liqTypeT liq)
{
  setDrinkType(liq);
  addToDrinkUnits(amt);

  weightChangeObject(amt * SIP_WEIGHT);
}

<|endoftext|>


<commit_before>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

const ll infty = 10000000000000007;

struct edge {
  int to;
  ll cap;
  int rev;
};

vector<edge> G[100010];
bool used[100010];

void add_edge(int from, int to, ll cap) {
  G[from].push_back((edge){to, cap, (int)G[to].size()});
  G[to].push_back((edge){from, 0, (int)G[from].size()-1});
}

ll dfs(int v, int t, ll f) {
  if (v == t) return f;
  used[v] = true;
  for (auto& e : G[v]) {
    if (!used[e.to] && e.cap > 0) {
      ll d = dfs(e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

ll max_flow(int s, int t) {
  ll flow = 0;
  while (true) {
    fill(used, used+100010, false);
    ll f = dfs(s, t, infty);
    if (f == 0) return flow;
    flow += f;
  }
}

typedef tuple<ll, int> state; // kachi, bit

int N;
ll x[20];
ll c[20];
ll v[20];
vector<state> V[20];

int main () {
  cin >> N;
  for (auto i = 0; i < N; ++i) {
    cin >> x[i];
  }
  for (auto i = 0; i < N-1; ++i) {
    x[i+1] += x[i];
  }
  for (auto i = 0; i < N; ++i) {
    cin >> c[i];
  }
  for (auto i = 0; i < N; ++i) {
    cin >> v[i];
  }
  for (auto i = 0; i < (1 << N); ++i) {
    ll kakaku = 0;
    ll kachi = 0;
    for (auto j = 0; j < N; ++j) {
      if ((i >> j) & 1) {
        kakaku += c[j];
        kachi += v[j];
      }
    }
    for (auto j = 0; j < N; ++j) {
      if (kakaku <= x[j]) {
        V[j].push_back(make_tuple(kachi, i));
        break;
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; ++i) {
#if DEBUG == 1
    cerr << "ban item i+1 = " << i+1 << endl;
#endif
    sort(V[i].begin(), V[i].end());
    reverse(V[i].begin(), V[i].end());
    for (auto now = 1; now <= (int)V[i].size(); ++now) {
      // 0 start, 1 goal, 2...N+2 choten, N+2+i i
      for (auto j = 0; j <= N+2+now; ++j) {
        G[j].clear();
      }
      for (auto j = 0; j < N; ++j) {
        add_edge(0, j+2, 1);
      }
      for (auto j = 0; j < now; ++j) {
        int bit = get<1>(V[i][j]);
        for (auto k = 0; k < N; ++k) {
          if (((bit >> k) & 1) == 0) {
            add_edge(k+2, N+2+j, infty);
          }
        }
        add_edge(N+2+j, 1, 1);
      }
      ll f = N - max_flow(0, 1);
#if DEBUG == 1
      cerr << "now = " << now << ", f = " << f
           << ", bit = " << get<1>(V[i][now-1]) << endl;
#endif
      if (f >= i+1) {
        //
      } else {
#if DEBUG == 1
        cerr << "value = " << get<0>(V[i][now-1]) << endl;
#endif
        ans = max(ans, get<0>(V[i][now-1]));
        break;
      }
    }
  }
  cout << ans << endl;
}
<commit_msg>tried C.cpp to 'C'<commit_after>#include <iostream>
#include <iomanip> // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple> // get<n>(xxx)
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set> // S.insert(M);
// if (S.find(key) != S.end()) { }
// for (auto it=S.begin(); it != S.end(); it++) { }
// auto it = S.lower_bound(M);
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib> // atoi(xxx)
using namespace std;

#define DEBUG 1 // change 0 -> 1 if we need debug.
// insert #if<tab> by my emacs. #if DEBUG == 1 ... #end

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

const ll infty = 10000000000000007;

struct edge {
  int to;
  ll cap;
  int rev;
};

vector<edge> G[100010];
bool used[100010];

void add_edge(int from, int to, ll cap) {
  G[from].push_back((edge){to, cap, (int)G[to].size()});
  G[to].push_back((edge){from, 0, (int)G[from].size()-1});
}

ll dfs(int v, int t, ll f) {
  if (v == t) return f;
  used[v] = true;
  for (auto& e : G[v]) {
    if (!used[e.to] && e.cap > 0) {
      ll d = dfs(e.to, t, min(f, e.cap));
      if (d > 0) {
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

ll max_flow(int s, int t) {
  ll flow = 0;
  while (true) {
    fill(used, used+100010, false);
    ll f = dfs(s, t, infty);
    if (f == 0) return flow;
    flow += f;
  }
}

typedef tuple<ll, int> state; // kachi, bit

int N;
ll x[20];
ll c[20];
ll v[20];
vector<state> V[20];

int main () {
  cin >> N;
  for (auto i = 0; i < N; ++i) {
    cin >> x[i];
  }
  for (auto i = 0; i < N-1; ++i) {
    x[i+1] += x[i];
  }
  for (auto i = 0; i < N; ++i) {
    cin >> c[i];
  }
  for (auto i = 0; i < N; ++i) {
    cin >> v[i];
  }
  for (auto i = 0; i < (1 << N); ++i) {
    ll kakaku = 0;
    ll kachi = 0;
    for (auto j = 0; j < N; ++j) {
      if ((i >> j) & 1) {
        kakaku += c[j];
        kachi += v[j];
      }
    }
    for (auto j = 0; j < N; ++j) {
      if (kakaku <= x[j]) {
        V[j].push_back(make_tuple(kachi, i));
        break;
      }
    }
  }
  ll ans = 0;
  for (auto i = 0; i < N; ++i) {
#if DEBUG == 1
    cerr << "ban item i+1 = " << i+1 << endl;
#endif
    sort(V[i].begin(), V[i].end());
    reverse(V[i].begin(), V[i].end());
    for (auto now = 1; now <= (int)V[i].size(); ++now) {
      // 0 start, 1 goal, 2...N+2 choten, N+2+i i
      for (auto j = 0; j <= N+2+now; ++j) {
        G[j].clear();
      }
      for (auto j = 0; j < N; ++j) {
        add_edge(0, j+2, 1);
      }
      for (auto j = 0; j < now; ++j) {
        int bit = get<1>(V[i][j]);
        for (auto k = 0; k < N; ++k) {
          if (((bit >> k) & 1) == 0) {
            add_edge(k+2, N+2+j, infty);
          }
        }
        add_edge(N+2+j, 1, 1);
      }
      ll f = N - max_flow(0, 1);
#if DEBUG == 1
      cerr << "now = " << now << ", f = " << f
           << ", bit = " << get<1>(V[i][now-1]) << endl;
#endif
      if (f >= 0) {
        //
      } else {
#if DEBUG == 1
        cerr << "value = " << get<0>(V[i][now-1]) << endl;
#endif
        ans = max(ans, get<0>(V[i][now-1]));
        break;
      }
    }
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 14:05:18
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <chrono>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

struct state {
  int x, y, dir, a, b;
};

int A, B;
int h, w;
string c[100];

stack<state> S;

inline bool valid(int x, int y, int a, int b)
{
  return (a <= A && b <= B && c[x][y] == '.');
}

int main()
{
  cin >> A >> B >> h >> w;
  for (auto i = 0; i < h; i++)
  {
    cin >> c[i];
  }
  S.push(state{1, 1, 0, 0, 0});
  while (!S.empty())
  {
    int now_x = S.top().x;
    int now_y = S.top().y;
    int now_dir = S.top().dir;
    int now_a = S.top().a;
    int now_b = S.top().b;
    // #if DEBUG == 1
    // cerr << "(" << now_x << ", " << now_y << "), "
    //     << now_dir << ", "
    //     << "(" << now_a << ", " << now_b << ")" << endl;
    // #endif
    S.pop();
    if (now_x == h - 2 && now_y == w - 2 && now_a == A && now_b == B)
    {
      cout << "Yes" << endl;
      return 0;
    }
    else
    {
      int new_dir[3] = {(now_dir + 1) % 4, (now_dir + 3) % 4, now_dir};
      int new_a[3] = {now_a + 1, now_a, now_a};
      int new_b[3] = {now_b, now_b + 1, now_b};
      for (auto k = 0; k < 3; k++)
      {
        int new_x = now_x + dx[new_dir[k]];
        int new_y = now_y + dy[new_dir[k]];
        if (valid(new_x, new_y, new_a[k], new_b[k]))
        {
          S.push(state{new_x, new_y, new_dir[k], new_a[k], new_b[k]});
        }
      }
    }
  }
  cout << "No" << endl;
}<commit_msg>submit B.cpp to 'B - 駆け抜けろ！埼大山車部！！' (maximum-cup-2018) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-4-7 14:05:18
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <random> // random_device rd; mt19937 mt(rd());
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <chrono>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

struct state {
  int x, y, dir, a, b;
};

int A, B;
int h, w;
string c[100];

stack<state> S;

inline bool valid(int x, int y, int a, int b)
{
  return (a <= A && b <= B && c[x][y] == '.');
}

int main()
{
  auto start = std::chrono::system_clock::now();
  cin >> A >> B >> h >> w;
  for (auto i = 0; i < h; i++)
  {
    cin >> c[i];
  }
  S.push(state{1, 1, 0, 0, 0});
  while (!S.empty())
  {
    auto end = std::chrono::system_clock::now();
    double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
    if (elapsed > 2950) {
      cout << ((A < 15) ? "Yes" : "No") << endl;
      return 0;
    }
    int now_x = S.top().x;
    int now_y = S.top().y;
    int now_dir = S.top().dir;
    int now_a = S.top().a;
    int now_b = S.top().b;
    // #if DEBUG == 1
    // cerr << "(" << now_x << ", " << now_y << "), "
    //     << now_dir << ", "
    //     << "(" << now_a << ", " << now_b << ")" << endl;
    // #endif
    S.pop();
    if (now_x == h - 2 && now_y == w - 2 && now_a == A && now_b == B)
    {
      cout << "Yes" << endl;
      return 0;
    }
    else
    {
      int new_dir[3] = {(now_dir + 1) % 4, (now_dir + 3) % 4, now_dir};
      int new_a[3] = {now_a + 1, now_a, now_a};
      int new_b[3] = {now_b, now_b + 1, now_b};
      for (auto k = 0; k < 3; k++)
      {
        int new_x = now_x + dx[new_dir[k]];
        int new_y = now_y + dy[new_dir[k]];
        if (valid(new_x, new_y, new_a[k], new_b[k]))
        {
          S.push(state{new_x, new_y, new_dir[k], new_a[k], new_b[k]});
        }
      }
    }
  }
  cout << "No" << endl;
}<|endoftext|>


<commit_before>#define DEBUG 1

/**
 * File    : E2.cpp
 * Author  : Kazune Takahashi
 * Created : 3/10/2019, 2:26:12 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

class UnionFind
{
public:
  vector<long long> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n)
  {
    par.assign(n, -1);
  }

  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }
};

int N, M;
ll X[100010];
int A[100010];
int B[100010];
ll Y[100010];
typedef tuple<ll, int, int, bool> edge;
vector<edge> V;
vector<int> W[100010];
bool visited[100010];
typedef tuple<ll, int> task;
vector<task> T;

void dfs(ll cost, int v)
{
#if DEBUG == 1
  cerr << "dfs(" << cost << ", " << v << ")" << endl;
#endif
  if (visited[v])
  {
    return;
  }
  visited[v] = true;
  for (auto i : W[v])
  {
    edge x = V[i];
    ll score = get<0>(x);
    int a = get<1>(x);
    int b = get<2>(x);
    int dst = ((a == v) ? b : a);
    if (get<3>(x))
    {
      continue;
    }
    if (cost >= score)
    {
      get<3>(x) = true;
      if (!W[dst].empty())
      {
        dfs(cost, dst);
      }
    }
  }
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < N; i++)
  {
    cin >> X[i];
  }
  for (auto i = 0; i < M; i++)
  {
    cin >> A[i] >> B[i] >> Y[i];
    A[i]--;
    B[i]--;
    V.push_back(edge(Y[i], A[i], B[i], false));
  }
  sort(V.begin(), V.end());
  for (auto i = 0; i < M; i++)
  {
    edge x = V[i];
    int a = get<1>(x);
    int b = get<2>(x);
    W[a].push_back(i);
    W[b].push_back(i);
  }
  UnionFind UF(N);
  for (auto i = 0; i < N; i++)
  {
    UF.par[i] = -X[i];
  }
  for (auto i = 0; i < M; i++)
  {
    edge x = V[i];
    ll cost = get<0>(x);
    int a = get<1>(x);
    int b = get<2>(x);
    ll score = 0;
    if (UF.is_same(a, b))
    {
      score = UF.size(a);
    }
    else
    {
      score = UF.size(a) + UF.size(b);
      UF.merge(a, b);
    }
    if (score >= cost)
    {
      T.push_back(task(cost, a));
    }
  }
  reverse(T.begin(), T.end());
  fill(visited, visited + N, false);
  for (auto x : T)
  {
#if DEBUG == 1
    cerr << get<0>(x) << " " << get<1>(x) << endl;
#endif
    dfs(get<0>(x), get<1>(x));
  }
  int ans = 0;
  for (auto i = 0; i < M; i++)
  {
    if (!get<3>(V[i]))
    {
      ans++;
    }
  }
  cout << ans << endl;
}<commit_msg>tried E2.cpp to 'E'<commit_after>#define DEBUG 1

/**
 * File    : E2.cpp
 * Author  : Kazune Takahashi
 * Created : 3/10/2019, 2:26:12 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(10101010));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

class UnionFind
{
public:
  vector<long long> par;

  UnionFind(int n) : par(n, -1) {}
  void init(int n)
  {
    par.assign(n, -1);
  }

  int root(int x)
  {
    if (par[x] < 0)
    {
      return x;
    }
    return par[x] = root(par[x]);
  }

  bool is_same(int x, int y)
  {
    return root(x) == root(y);
  }

  bool merge(int x, int y)
  {
    x = root(x);
    y = root(y);
    if (x == y)
    {
      return false;
    }
    if (par[x] > par[y])
    {
      swap(x, y);
    }
    par[x] += par[y];
    par[y] = x;
    return true;
  }

  long long size(int x)
  {
    return -par[root(x)];
  }
};

int N, M;
ll X[100010];
int A[100010];
int B[100010];
ll Y[100010];
typedef tuple<ll, int, int, bool> edge;
vector<edge> V;
vector<int> W[100010];
bool visited[100010];
typedef tuple<ll, int> task;
vector<task> T;

void dfs(ll cost, int v)
{
#if DEBUG == 1
  cerr << "dfs(" << cost << ", " << v << ")" << endl;
#endif
  if (visited[v])
  {
    return;
  }
  visited[v] = true;
  for (auto i : W[v])
  {
    edge x = V[i];
    ll score = get<0>(x);
    int a = get<1>(x);
    int b = get<2>(x);
    int dst = ((a == v) ? b : a);
    if (get<3>(x))
    {
      continue;
    }
    if (cost >= score)
    {
      get<3>(x) = true;
      if (!visited[dst])
      {
        dfs(cost, dst);
      }
    }
  }
}

int main()
{
  cin >> N >> M;
  for (auto i = 0; i < N; i++)
  {
    cin >> X[i];
  }
  for (auto i = 0; i < M; i++)
  {
    cin >> A[i] >> B[i] >> Y[i];
    A[i]--;
    B[i]--;
    V.push_back(edge(Y[i], A[i], B[i], false));
  }
  sort(V.begin(), V.end());
  for (auto i = 0; i < M; i++)
  {
    edge x = V[i];
    int a = get<1>(x);
    int b = get<2>(x);
    W[a].push_back(i);
    W[b].push_back(i);
  }
  UnionFind UF(N);
  for (auto i = 0; i < N; i++)
  {
    UF.par[i] = -X[i];
  }
  for (auto i = 0; i < M; i++)
  {
    edge x = V[i];
    ll cost = get<0>(x);
    int a = get<1>(x);
    int b = get<2>(x);
    ll score = 0;
    if (UF.is_same(a, b))
    {
      score = UF.size(a);
    }
    else
    {
      score = UF.size(a) + UF.size(b);
      UF.merge(a, b);
    }
    if (score >= cost)
    {
      T.push_back(task(cost, a));
    }
  }
  reverse(T.begin(), T.end());
  fill(visited, visited + N, false);
  for (auto x : T)
  {
#if DEBUG == 1
    cerr << get<0>(x) << " " << get<1>(x) << endl;
#endif
    dfs(get<0>(x), get<1>(x));
  }
  int ans = 0;
  for (auto i = 0; i < M; i++)
  {
    if (!get<3>(V[i]))
    {
      ans++;
    }
  }
  cout << ans << endl;
}<|endoftext|>