<commit_before>/**
 * @file mpc.cpp
 * @brief  Brief description of file.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <mpd/client.h>
#include <mpd/status.h>
#include <mpd/search.h>
#include <mpd/entity.h>
#include <mpd/song.h>

#include "../include/plugins.h"

const char *todo = "Tidy up song data item access. Some form of hash?";

/// handles the connection. This should be created by "connect",
/// and disconnection will be handled by the destructor, which
/// runs on exit.

class Connection {
    char *error;
    void seterror(const char *s){
        if(error)free(error);
        error=strdup(s);
    }

public:
    mpd_connection *mpd;
    Connection(){
        error = NULL;
        mpd=NULL;
    }
    ~Connection(){
        if(error)free(error);
        if(mpd)
            mpd_connection_free(mpd);
    }

    const char *geterror(){
        return error;
    }

    /// returns NULL or an error. host can be null for default,
    /// port zero for default.
    const char *connect(const char *host, int port=0){
        mpd = mpd_connection_new(host,port,2000); // 2 second timeout
        if(mpd_connection_get_error(mpd)!=MPD_ERROR_SUCCESS){
            seterror(mpd_connection_get_error_message(mpd));
            mpd_connection_free(mpd);
            mpd=NULL;
            return error;
        }
        return NULL;
    }
    void disconnect(){
        if(error)free(error);
        if(mpd)
            mpd_connection_free(mpd);
        error=NULL;mpd=NULL;
    }

    void check(){
        if(!mpd)
            throw("MPD not connected");
    }

    void throwError(){
        char buf[1024];
        sprintf(buf,"MPD error: %s",mpd_connection_get_error_message(mpd));
        mpd_connection_clear_error(mpd);
        throw buf;
    }
};

Connection conn;

static PluginValue *makeSong(const mpd_song *song){
    PluginValue *p = new PluginValue();
    p->setHash();
    p->setHashVal("name",new PluginValue(mpd_song_get_uri(song)));
    p->setHashVal("id",new PluginValue(mpd_song_get_id(song)));
    p->setHashVal("pos",new PluginValue(mpd_song_get_pos(song)));
    p->setHashVal("duration",new PluginValue(mpd_song_get_duration(song)));

    for(int i=(int)MPD_TAG_ARTIST;i<(int)MPD_TAG_COUNT;i++){
        const char *s = mpd_song_get_tag(song,(mpd_tag_type)i,0);
        if(s){
            char buf[256];
            const char *tagname = mpd_tag_name((mpd_tag_type)i);
            strcpy(buf,tagname);
            for(char *q=buf;*q;q++)*q=tolower(*q);
            p->setHashVal(buf,new PluginValue(s));
        }
    }

    return p;
}

static void connectFunc(PluginValue *res,PluginValue *params){
    if(conn.mpd)
        conn.disconnect();

    const char *host;
    if(params[0].type == PV_NONE)
        host = NULL;
    else
        host = params[0].getString();
    int port = params[1].getInt();

    const char *error = conn.connect(host,port);
    if(error)
        throw error;
}

static void searchFunc(PluginValue *res,PluginValue *params){
    conn.check();

    if(params->type != PV_HASH)
        throw "must be a hash in mpc$search";

    // start the search

    if(!mpd_search_db_songs(conn.mpd,false))
        conn.throwError();

    // add constraints
    PluginValue *key,*value;
    for(key = params->v.head;key;key=value->next){
        value = key->next;

        if(!mpd_search_add_tag_constraint(conn.mpd,MPD_OPERATOR_DEFAULT,
                                          mpd_tag_name_iparse(key->getString()),
                                          value->getString()))
            conn.throwError();
    }
    if(!mpd_search_commit(conn.mpd))
        conn.throwError();

    res->setList();
    mpd_song *song;
    while((song=mpd_recv_song(conn.mpd))!=NULL){
        PluginValue *pv = makeSong(song);
        res->addToList(pv);
        mpd_song_free(song);
    }
    if (mpd_connection_get_error(conn.mpd) != MPD_ERROR_SUCCESS) {
        goto error;
    }

    if (!mpd_response_finish(conn.mpd)) {
        goto error;
    }

    return;
    // ugly, yes.
error:
    if(res->type == PV_LIST){
        PluginValue *q;
        for(PluginValue *p=res->v.head;p;p=q){
            q=p->next;
            delete p;
        }
    }
    throw mpd_connection_get_error_message(conn.mpd);
}

static void tagsFunc(PluginValue *res,PluginValue *params){
    conn.check();

    PluginValue *hash = params+1;
    if(hash->type != PV_HASH)
        throw "must be a hash in mpc$search";

    const char *tag = params->getString();

    // start the search

    mpd_tag_type tagid = mpd_tag_name_iparse(tag);
    if(!mpd_search_db_tags(conn.mpd,tagid))
        conn.throwError();

    // add constraints
    PluginValue *key,*value;
    for(key = hash->v.head;key;key=value->next){
        value = key->next;

        if(!mpd_search_add_tag_constraint(conn.mpd,MPD_OPERATOR_DEFAULT,
                                          mpd_tag_name_iparse(key->getString()),
                                          value->getString()))
            conn.throwError();
    }
    if(!mpd_search_commit(conn.mpd))
        conn.throwError();

    res->setList();
    while(mpd_pair *pair = mpd_recv_pair_tag(conn.mpd,tagid)){
        res->addToList(new PluginValue(pair->value));
        mpd_return_pair(conn.mpd,pair);
    }

    if (mpd_connection_get_error(conn.mpd) != MPD_ERROR_SUCCESS)
        conn.throwError();

    if (!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void addFunc(PluginValue *res,PluginValue *params){
    conn.check();

    mpd_command_list_begin(conn.mpd,false);

    if(params->type == PV_OBJ){
        mpd_send_add(conn.mpd,params->getHashVal("name")->getString());
    } else if(params->type == PV_LIST) {
        for(PluginValue *p=params->v.head;p;p=p->next){
            mpd_send_add(conn.mpd,p->getHashVal("name")->getString());
        }
    } else throw("inappropriate type for 'mpc$add'");
    mpd_command_list_end(conn.mpd);

    if(!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void clearFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_clear(conn.mpd))
        conn.throwError();
}

static void listFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_command_list_begin(conn.mpd,true);
    mpd_send_list_queue_meta(conn.mpd);
    mpd_command_list_end(conn.mpd);

    res->setList();
    for(mpd_entity* entity = mpd_recv_entity(conn.mpd);
        entity;
        entity = mpd_recv_entity(conn.mpd)) {
        if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
            const mpd_song* song = mpd_entity_get_song(entity);
            PluginValue *pv = makeSong(song);
            res->addToList(pv);
        }
        mpd_entity_free(entity);
    }
    if(!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void playFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(params->type == PV_NONE){
        if(!mpd_run_play(conn.mpd))
            conn.throwError();
    } else {
        if(!mpd_run_play_pos(conn.mpd,params->getInt()))
            conn.throwError();
    }
}
static void pauseFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_toggle_pause(conn.mpd))
        conn.throwError();
}
static void stopFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_stop(conn.mpd))
        conn.throwError();
}
static void nextFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_next(conn.mpd))
        conn.throwError();
}
static void prevFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_previous(conn.mpd))
        conn.throwError();
}

static void statFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_status *stat = mpd_run_status(conn.mpd);
    if(!stat)
        conn.throwError();
    res->setHash();
    res->setHashVal("consume",new PluginValue(mpd_status_get_consume(stat)?1:0));
    res->setHashVal("crossfade",new PluginValue((int)mpd_status_get_crossfade(stat)));
    res->setHashVal("elapsed",new PluginValue((int)mpd_status_get_elapsed_time(stat)));
    res->setHashVal("total",new PluginValue((int)mpd_status_get_total_time(stat)));
    res->setHashVal("update",new PluginValue((int)mpd_status_get_update_id(stat)));
    res->setHashVal("volume",new PluginValue((int)mpd_status_get_volume(stat)));
    if(mpd_status_get_error(stat))
        res->setHashVal("error",new PluginValue(mpd_status_get_error(stat)));
    res->setHashVal("queuelength",new PluginValue((int)mpd_status_get_queue_length(stat)));
    res->setHashVal("queueversion",new PluginValue((int)mpd_status_get_queue_version(stat)));

    res->setHashVal("id",new PluginValue((int)mpd_status_get_song_id(stat)));
    res->setHashVal("pos",new PluginValue((int)mpd_status_get_song_pos(stat)));

    const char *state;
    switch(mpd_status_get_state(stat)){
    case MPD_STATE_UNKNOWN:state="unknown";break;
    case MPD_STATE_STOP:state="stop";break;
    case MPD_STATE_PLAY:state="play";break;
    case MPD_STATE_PAUSE:state="pause";break;
    }
    PluginValue *pv = new PluginValue();
    pv->setSymbol(state);
    res->setHashVal("state",pv);

    res->setHashVal("random",new PluginValue(mpd_status_get_random(stat)?1:0));
    res->setHashVal("repeat",new PluginValue(mpd_status_get_repeat(stat)?1:0));
    res->setHashVal("single",new PluginValue(mpd_status_get_single(stat)?1:0));
}

static void loadFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_load(conn.mpd,params[0].getString()))
        conn.throwError();
}
static void saveFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_save(conn.mpd,params[0].getString()))
        conn.throwError();
}
static void rmFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_rm(conn.mpd,params[0].getString()))
        conn.throwError();
}

static void playlistsFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_send_list_playlists(conn.mpd);
    res->setList();
    while(mpd_playlist *p = mpd_recv_playlist(conn.mpd)){
        res->addToList(new PluginValue(mpd_playlist_get_path(p)));
    }
    mpd_response_finish(conn.mpd);
}

/// this is used for functions which are harder to do!

static void mpcFunc(PluginValue *res,PluginValue *params){
    FILE *fp;

    char buf[1024];
    snprintf(buf,1024,"/usr/bin/mpc %s",params[0].getString());
    fp = popen(buf,"r");
    res->setList();
    if(fp!=NULL){
        while(fgets(buf,sizeof(buf)-1,fp)!=NULL){
            PluginValue *pv = new PluginValue();
            buf[strlen(buf)-1]=0; // strip trailing LF
            pv->setString(buf);
            res->addToList(pv);
        }
        pclose(fp);
    } else
        res->setNone();
}

static PluginFunc funcs[]= {
    {"connect",connectFunc,2}, // (hostOrNone portOrZero --)

    // searches, returning song objects or tag values
    {"search",searchFunc,1}, // (constrainthash -- list)
    {"tags",tagsFunc,2}, // (constrainthash tagname -- listofvaluesfortag)

    // playlist manipulation
    {"add",addFunc,1}, // (songlist--)
    {"clear",clearFunc,0},
    {"list",listFunc,0},
    {"stat",statFunc,0}, // (-- hash)

    {"play",playFunc,1}, // (noneOrID --)
    {"pause",pauseFunc,0},
    {"stop",stopFunc,0},
    {"next",nextFunc,0},
    {"prev",prevFunc,0},

    {"load",loadFunc,1},
    {"save",saveFunc,1},
    {"rm",rmFunc,1},
    {"playlists",playlistsFunc,0}, // (-- list)

    // shell command function
    {"mpc",mpcFunc,1},
    {NULL,NULL,-1}
};

static PluginInfo info = {
    "mpc",funcs
};

extern "C" PluginInfo *init(){
    printf("Initialising MPC plugin\n%s\n",todo);
    return &info;
}

<commit_msg>removed todo<commit_after>/**
 * @file mpc.cpp
 * @brief  Brief description of file.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <mpd/client.h>
#include <mpd/status.h>
#include <mpd/search.h>
#include <mpd/entity.h>
#include <mpd/song.h>

#include "../include/plugins.h"

/// handles the connection. This should be created by "connect",
/// and disconnection will be handled by the destructor, which
/// runs on exit.

class Connection {
    char *error;
    void seterror(const char *s){
        if(error)free(error);
        error=strdup(s);
    }

public:
    mpd_connection *mpd;
    Connection(){
        error = NULL;
        mpd=NULL;
    }
    ~Connection(){
        if(error)free(error);
        if(mpd)
            mpd_connection_free(mpd);
    }

    const char *geterror(){
        return error;
    }

    /// returns NULL or an error. host can be null for default,
    /// port zero for default.
    const char *connect(const char *host, int port=0){
        mpd = mpd_connection_new(host,port,2000); // 2 second timeout
        if(mpd_connection_get_error(mpd)!=MPD_ERROR_SUCCESS){
            seterror(mpd_connection_get_error_message(mpd));
            mpd_connection_free(mpd);
            mpd=NULL;
            return error;
        }
        return NULL;
    }
    void disconnect(){
        if(error)free(error);
        if(mpd)
            mpd_connection_free(mpd);
        error=NULL;mpd=NULL;
    }

    void check(){
        if(!mpd)
            throw("MPD not connected");
    }

    void throwError(){
        char buf[1024];
        sprintf(buf,"MPD error: %s",mpd_connection_get_error_message(mpd));
        mpd_connection_clear_error(mpd);
        throw buf;
    }
};

Connection conn;

static PluginValue *makeSong(const mpd_song *song){
    PluginValue *p = new PluginValue();
    p->setHash();
    p->setHashVal("name",new PluginValue(mpd_song_get_uri(song)));
    p->setHashVal("id",new PluginValue(mpd_song_get_id(song)));
    p->setHashVal("pos",new PluginValue(mpd_song_get_pos(song)));
    p->setHashVal("duration",new PluginValue(mpd_song_get_duration(song)));

    for(int i=(int)MPD_TAG_ARTIST;i<(int)MPD_TAG_COUNT;i++){
        const char *s = mpd_song_get_tag(song,(mpd_tag_type)i,0);
        if(s){
            char buf[256];
            const char *tagname = mpd_tag_name((mpd_tag_type)i);
            strcpy(buf,tagname);
            for(char *q=buf;*q;q++)*q=tolower(*q);
            p->setHashVal(buf,new PluginValue(s));
        }
    }

    return p;
}

static void connectFunc(PluginValue *res,PluginValue *params){
    if(conn.mpd)
        conn.disconnect();

    const char *host;
    if(params[0].type == PV_NONE)
        host = NULL;
    else
        host = params[0].getString();
    int port = params[1].getInt();

    const char *error = conn.connect(host,port);
    if(error)
        throw error;
}

static void searchFunc(PluginValue *res,PluginValue *params){
    conn.check();

    if(params->type != PV_HASH)
        throw "must be a hash in mpc$search";

    // start the search

    if(!mpd_search_db_songs(conn.mpd,false))
        conn.throwError();

    // add constraints
    PluginValue *key,*value;
    for(key = params->v.head;key;key=value->next){
        value = key->next;

        if(!mpd_search_add_tag_constraint(conn.mpd,MPD_OPERATOR_DEFAULT,
                                          mpd_tag_name_iparse(key->getString()),
                                          value->getString()))
            conn.throwError();
    }
    if(!mpd_search_commit(conn.mpd))
        conn.throwError();

    res->setList();
    mpd_song *song;
    while((song=mpd_recv_song(conn.mpd))!=NULL){
        PluginValue *pv = makeSong(song);
        res->addToList(pv);
        mpd_song_free(song);
    }
    if (mpd_connection_get_error(conn.mpd) != MPD_ERROR_SUCCESS) {
        goto error;
    }

    if (!mpd_response_finish(conn.mpd)) {
        goto error;
    }

    return;
    // ugly, yes.
error:
    if(res->type == PV_LIST){
        PluginValue *q;
        for(PluginValue *p=res->v.head;p;p=q){
            q=p->next;
            delete p;
        }
    }
    throw mpd_connection_get_error_message(conn.mpd);
}

static void tagsFunc(PluginValue *res,PluginValue *params){
    conn.check();

    PluginValue *hash = params+1;
    if(hash->type != PV_HASH)
        throw "must be a hash in mpc$search";

    const char *tag = params->getString();

    // start the search

    mpd_tag_type tagid = mpd_tag_name_iparse(tag);
    if(!mpd_search_db_tags(conn.mpd,tagid))
        conn.throwError();

    // add constraints
    PluginValue *key,*value;
    for(key = hash->v.head;key;key=value->next){
        value = key->next;

        if(!mpd_search_add_tag_constraint(conn.mpd,MPD_OPERATOR_DEFAULT,
                                          mpd_tag_name_iparse(key->getString()),
                                          value->getString()))
            conn.throwError();
    }
    if(!mpd_search_commit(conn.mpd))
        conn.throwError();

    res->setList();
    while(mpd_pair *pair = mpd_recv_pair_tag(conn.mpd,tagid)){
        res->addToList(new PluginValue(pair->value));
        mpd_return_pair(conn.mpd,pair);
    }

    if (mpd_connection_get_error(conn.mpd) != MPD_ERROR_SUCCESS)
        conn.throwError();

    if (!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void addFunc(PluginValue *res,PluginValue *params){
    conn.check();

    mpd_command_list_begin(conn.mpd,false);

    if(params->type == PV_OBJ){
        mpd_send_add(conn.mpd,params->getHashVal("name")->getString());
    } else if(params->type == PV_LIST) {
        for(PluginValue *p=params->v.head;p;p=p->next){
            mpd_send_add(conn.mpd,p->getHashVal("name")->getString());
        }
    } else throw("inappropriate type for 'mpc$add'");
    mpd_command_list_end(conn.mpd);

    if(!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void clearFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_clear(conn.mpd))
        conn.throwError();
}

static void listFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_command_list_begin(conn.mpd,true);
    mpd_send_list_queue_meta(conn.mpd);
    mpd_command_list_end(conn.mpd);

    res->setList();
    for(mpd_entity* entity = mpd_recv_entity(conn.mpd);
        entity;
        entity = mpd_recv_entity(conn.mpd)) {
        if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
            const mpd_song* song = mpd_entity_get_song(entity);
            PluginValue *pv = makeSong(song);
            res->addToList(pv);
        }
        mpd_entity_free(entity);
    }
    if(!mpd_response_finish(conn.mpd))
        conn.throwError();
}

static void playFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(params->type == PV_NONE){
        if(!mpd_run_play(conn.mpd))
            conn.throwError();
    } else {
        if(!mpd_run_play_pos(conn.mpd,params->getInt()))
            conn.throwError();
    }
}
static void pauseFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_toggle_pause(conn.mpd))
        conn.throwError();
}
static void stopFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_stop(conn.mpd))
        conn.throwError();
}
static void nextFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_next(conn.mpd))
        conn.throwError();
}
static void prevFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_previous(conn.mpd))
        conn.throwError();
}

static void statFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_status *stat = mpd_run_status(conn.mpd);
    if(!stat)
        conn.throwError();
    res->setHash();
    res->setHashVal("consume",new PluginValue(mpd_status_get_consume(stat)?1:0));
    res->setHashVal("crossfade",new PluginValue((int)mpd_status_get_crossfade(stat)));
    res->setHashVal("elapsed",new PluginValue((int)mpd_status_get_elapsed_time(stat)));
    res->setHashVal("total",new PluginValue((int)mpd_status_get_total_time(stat)));
    res->setHashVal("update",new PluginValue((int)mpd_status_get_update_id(stat)));
    res->setHashVal("volume",new PluginValue((int)mpd_status_get_volume(stat)));
    if(mpd_status_get_error(stat))
        res->setHashVal("error",new PluginValue(mpd_status_get_error(stat)));
    res->setHashVal("queuelength",new PluginValue((int)mpd_status_get_queue_length(stat)));
    res->setHashVal("queueversion",new PluginValue((int)mpd_status_get_queue_version(stat)));

    res->setHashVal("id",new PluginValue((int)mpd_status_get_song_id(stat)));
    res->setHashVal("pos",new PluginValue((int)mpd_status_get_song_pos(stat)));

    const char *state;
    switch(mpd_status_get_state(stat)){
    case MPD_STATE_UNKNOWN:state="unknown";break;
    case MPD_STATE_STOP:state="stop";break;
    case MPD_STATE_PLAY:state="play";break;
    case MPD_STATE_PAUSE:state="pause";break;
    }
    PluginValue *pv = new PluginValue();
    pv->setSymbol(state);
    res->setHashVal("state",pv);

    res->setHashVal("random",new PluginValue(mpd_status_get_random(stat)?1:0));
    res->setHashVal("repeat",new PluginValue(mpd_status_get_repeat(stat)?1:0));
    res->setHashVal("single",new PluginValue(mpd_status_get_single(stat)?1:0));
}

static void loadFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_load(conn.mpd,params[0].getString()))
        conn.throwError();
}
static void saveFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_save(conn.mpd,params[0].getString()))
        conn.throwError();
}
static void rmFunc(PluginValue *res,PluginValue *params){
    conn.check();
    if(!mpd_run_rm(conn.mpd,params[0].getString()))
        conn.throwError();
}

static void playlistsFunc(PluginValue *res,PluginValue *params){
    conn.check();
    mpd_send_list_playlists(conn.mpd);
    res->setList();
    while(mpd_playlist *p = mpd_recv_playlist(conn.mpd)){
        res->addToList(new PluginValue(mpd_playlist_get_path(p)));
    }
    mpd_response_finish(conn.mpd);
}

/// this is used for functions which are harder to do!

static void mpcFunc(PluginValue *res,PluginValue *params){
    FILE *fp;

    char buf[1024];
    snprintf(buf,1024,"/usr/bin/mpc %s",params[0].getString());
    fp = popen(buf,"r");
    res->setList();
    if(fp!=NULL){
        while(fgets(buf,sizeof(buf)-1,fp)!=NULL){
            PluginValue *pv = new PluginValue();
            buf[strlen(buf)-1]=0; // strip trailing LF
            pv->setString(buf);
            res->addToList(pv);
        }
        pclose(fp);
    } else
        res->setNone();
}

static PluginFunc funcs[]= {
    {"connect",connectFunc,2}, // (hostOrNone portOrZero --)

    // searches, returning song objects or tag values
    {"search",searchFunc,1}, // (constrainthash -- list)
    {"tags",tagsFunc,2}, // (constrainthash tagname -- listofvaluesfortag)

    // playlist manipulation
    {"add",addFunc,1}, // (songlist--)
    {"clear",clearFunc,0},
    {"list",listFunc,0},
    {"stat",statFunc,0}, // (-- hash)

    {"play",playFunc,1}, // (noneOrID --)
    {"pause",pauseFunc,0},
    {"stop",stopFunc,0},
    {"next",nextFunc,0},
    {"prev",prevFunc,0},

    {"load",loadFunc,1},
    {"save",saveFunc,1},
    {"rm",rmFunc,1},
    {"playlists",playlistsFunc,0}, // (-- list)

    // shell command function
    {"mpc",mpcFunc,1},
    {NULL,NULL,-1}
};

static PluginInfo info = {
    "mpc",funcs
};

extern "C" PluginInfo *init(){
    printf("Initialising MPC plugin\n");
    return &info;
}

<|endoftext|>


<commit_before>//
// File:   tabulatedpotential.cc
// Author: ruehle
//
// Created on August 2, 2007, 3:18 PM
//

#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <string>
#include <boost/lexical_cast.hpp>
#include "analysistool.h"
#include <tools/histogram.h>
#include "version.h"
#include "bondedstatistics.h"
#include "tabulatedpotential.h"

using namespace std;
using namespace boost;

TabulatedPotential::TabulatedPotential()
{
    _tab_smooth1 = _tab_smooth2 = 0;
    _T = 300;
}

void TabulatedPotential::Register(map<string, AnalysisTool *> &lib)
{
    lib["tab"] = this;
    lib["hist"] = this;
}

void TabulatedPotential::Command(BondedStatistics &bs, string cmd, vector<string> &args)
{
    if(args[0] == "set") {
        if(cmd == "hist") SetOption(_hist_options, args);
        else if(cmd == "tab") {
            if(!SetOption(_tab_options, args)) {
                if(args.size() >2) {
                    if(args[1] == "smooth1")
                        _tab_smooth1 = lexical_cast<int>(args[2]);
                    else if(args[1] == "smooth2")
                        _tab_smooth2 = lexical_cast<int>(args[2]);
                    else if(args[1] == "T")
                        _T = lexical_cast<double>(args[2]);
                    else {
                        cout << "unknown option " << args[2] << endl;
                        return;
                    }
                }
            }
            if(args.size() <=2) {
                cout << "smooth1: " << _tab_smooth1 << endl;
                cout << "smooth2: " << _tab_smooth2 << endl;
                cout << "T: " << _T << endl;
            }
        }
    }
    else if(args.size() >= 2) {
        if(cmd == "hist") WriteHistogram(bs, args);
        else if(cmd == "tab") WritePotential(bs, args);
    }
    else cout << "wrong number of arguments" << endl;
}

bool TabulatedPotential::SetOption(Histogram::options_t &op, const vector<string> &args)
{
    if(args.size() >2) {
        if(args[1] == "n")
            op._n = lexical_cast<int>(args[2]);
        else if(args[1] == "min") {
            op._min = lexical_cast<double>(args[2]);
        }
        else if(args[1] == "max")
            op._max = lexical_cast<double>(args[2]);
        else if(args[1] == "periodic")
            op._periodic = lexical_cast<bool>(args[2]);
        else if(args[1] == "auto")
            op._auto_interval = lexical_cast<bool>(args[2]);
        else if(args[1] == "extend")
            op._extend_interval = lexical_cast<bool>(args[2]);
        else if(args[1] == "scale") {
            if(args[2]=="no" || args[2]=="bond" || args[2]=="angle")
                op._scale = args[2];
            else {
                cout << "scale can be: no, bond or angle\n";
            }
        }
        else {
            return false;
        }
    }
    else {
        cout << "n: " << op._n << endl;
        cout << "min: " << op._min << endl;
        cout << "max: " << op._max << endl;
        cout << "periodic: " << op._periodic << endl;
        cout << "auto: " << op._auto_interval << endl;
        cout << "extend: " << op._extend_interval << endl;
        cout << "scale: " << op._scale << endl;
    }
    return true;
}

void TabulatedPotential::WriteHistogram(BondedStatistics &bs, vector<string> &args)
{
    ofstream out;
    DataCollection<double>::selection *sel = NULL;

    for(size_t i=1; i<args.size(); i++)
        sel = bs.BondedValues().select(args[i], sel);
    Histogram h(_hist_options);
    h.ProcessData(sel);
    out.open(args[0].c_str());
/*    out << "# histogram, created csg version " <<  VERSION_STR  << endl;
    out << "# n = " << _hist_options._n << endl;
    out << "# min = " << _hist_options._min << endl;
    out << "# max = " << _hist_options._max << endl;
    out << "# periodic = " << _hist_options._periodic << endl;
    out << "# auto = " << _hist_options._auto_interval << endl;
    out << "# extend = " << _hist_options._extend_interval << endl;
    out << "# scale = " << _hist_options._scale << endl;*/
    out << h ;
    out.close();
    cout << "histogram created using " << sel->size() << " data-rows, written to " << args[0] << endl;
    delete sel;
}

void TabulatedPotential::CalcForce(vector<double> &U, vector<double> &F, double dx, bool bPeriodic)
{
    size_t n=U.size();
    double f = 0.5/dx;
    F.resize(n);
    if(bPeriodic)
        F[n-1] = F[0] = -(U[1] - U[n-2])*f;
    else {
        F[0] = -(U[1] - U[0])*2*f;
        F[n-1] = -(U[n-1] - U[n-2])*2*f;
    }
    for(size_t i=1; i<n-1; i++)
        F[i] = -(U[i+1] - U[i-1])*f;
}

void TabulatedPotential::WritePotential(BondedStatistics &bs, vector<string> &args)
{
   ofstream out;
    DataCollection<double>::selection *sel = NULL;

    for(size_t i=1; i<args.size(); i++)
        sel = bs.BondedValues().select(args[i], sel);
    Histogram h(_tab_options);
    h.ProcessData(sel);
    for(int i=0; i<_tab_smooth1; ++i)
        Smooth(h.getPdf(), _tab_options._periodic);
    BoltzmannInvert(h.getPdf(), _T);
    for(int i=0; i<_tab_smooth2; ++i)
        Smooth(h.getPdf(), _tab_options._periodic);
    out.open(args[0].c_str());

/*       out << "# tabulated potential, created csg version " VERSION_STR  << endl;
    out << "# n = " << _tab_options._n << endl;
    out << "# min = " << _tab_options._min << endl;
    out << "# max = " << _tab_options._max << endl;
    out << "# periodic = " << _tab_options._periodic << endl;
    out << "# auto = " << _tab_options._auto_interval << endl;
    out << "# extend = " << _tab_options._extend_interval << endl;
    out << "# scale = " << _tab_options._scale << endl;
    out << "# smooth1 = " << _tab_smooth1 << endl;
    out << "# smooth2 = " << _tab_smooth2 << endl;
    out << "# T = " << _T << endl;*/

    vector<double> F;

    CalcForce(h.getPdf(), F, h.getInterval(), _tab_options._periodic);
    for(int i=0; i<h.getN(); i++) {
        out << h.getMin() + h.getInterval()*((double)i) << " " << h.getPdf()[i] << " " << F[i] << endl;
    }
    out.close();
    cout << "histogram created using " << sel->size() << " data-rows, written to " << args[0] << endl;
    delete sel;
}

void TabulatedPotential::Smooth(vector<double> &data, bool bPeriodic)
{
    double old[3];
    int n=data.size();
    if(bPeriodic) {
        old[0] = data[n-3];
        old[1] = data[n-2];
    }
    else {
        old[0] = data[0];
        old[1] = data[0];
    }
    size_t i;
    for(i=0; i<data.size()-2; i++) {
        old[3] = data[i];
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 2.*data[i+1] + data[i+2])/9.;
        old[0]=old[1];
        old[1]=old[3];;
    }
    if(bPeriodic) {
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 2.*data[i+1] + data[0])/9.;
        old[0]=old[1];old[1]=data[i];
        data[n-1] = data[0];
    }
    else {
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 3.*data[i+1])/9.;
        old[0]=old[1];old[1]=data[i];
        i++;
        data[i] = (old[0] + 2.*old[1] + 6.*data[i])/9.;
    }
}

void TabulatedPotential::BoltzmannInvert(vector<double> &data, double T)
{
    double _min, _max;

    _min = numeric_limits<double>::max();
    _max = numeric_limits<double>::min();

    for(size_t i=0; i<data.size(); i++) {
        _max = max(data[i], _max);
        if(data[i] > 0) _min = min(data[i], _min);
    }
    _max = -8.3109*T*log(_max)*0.001;
    _min = -8.3109*T*log(_min)*0.001-_max;

    for(size_t i=0; i<data.size(); i++) {
        if(data[i] == 0) data[i] = _min;
        else
            data[i] = -8.3109*T*log(data[i])*0.001 - _max;
    }
}
<commit_msg>added normalize option, corrected normalization after scaling<commit_after>//
// File:   tabulatedpotential.cc
// Author: ruehle
//
// Created on August 2, 2007, 3:18 PM
//

#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <string>
#include <boost/lexical_cast.hpp>
#include "analysistool.h"
#include <tools/histogram.h>
#include "version.h"
#include "bondedstatistics.h"
#include "tabulatedpotential.h"

using namespace std;
using namespace boost;

TabulatedPotential::TabulatedPotential()
{
    _tab_smooth1 = _tab_smooth2 = 0;
    _T = 300;
}

void TabulatedPotential::Register(map<string, AnalysisTool *> &lib)
{
    lib["tab"] = this;
    lib["hist"] = this;
}

void TabulatedPotential::Command(BondedStatistics &bs, string cmd, vector<string> &args)
{
    if(args[0] == "set") {
        if(cmd == "hist") SetOption(_hist_options, args);
        else if(cmd == "tab") {
            if(!SetOption(_tab_options, args)) {
                if(args.size() >2) {
                    if(args[1] == "smooth1")
                        _tab_smooth1 = lexical_cast<int>(args[2]);
                    else if(args[1] == "smooth2")
                        _tab_smooth2 = lexical_cast<int>(args[2]);
                    else if(args[1] == "T")
                        _T = lexical_cast<double>(args[2]);
                    else {
                        cout << "unknown option " << args[2] << endl;
                        return;
                    }
                }
            }
            if(args.size() <=2) {
                cout << "smooth1: " << _tab_smooth1 << endl;
                cout << "smooth2: " << _tab_smooth2 << endl;
                cout << "T: " << _T << endl;
            }
        }
    }
    else if(args.size() >= 2) {
        if(cmd == "hist") WriteHistogram(bs, args);
        else if(cmd == "tab") WritePotential(bs, args);
    }
    else cout << "wrong number of arguments" << endl;
}

bool TabulatedPotential::SetOption(Histogram::options_t &op, const vector<string> &args)
{
    if(args.size() >2) {
        if(args[1] == "n")
            op._n = lexical_cast<int>(args[2]);
        else if(args[1] == "min") {
            op._min = lexical_cast<double>(args[2]);
        }
        else if(args[1] == "max")
            op._max = lexical_cast<double>(args[2]);
        else if(args[1] == "periodic")
            op._periodic = lexical_cast<bool>(args[2]);
        else if(args[1] == "auto")
            op._auto_interval = lexical_cast<bool>(args[2]);
        else if(args[1] == "extend")
            op._extend_interval = lexical_cast<bool>(args[2]);
        else if(args[1] == "normalize")
            op._normalize = lexical_cast<bool>(args[2]);
        else if(args[1] == "scale") {
            if(args[2]=="no" || args[2]=="bond" || args[2]=="angle")
                op._scale = args[2];
            else {
                cout << "scale can be: no, bond or angle\n";
            }
        }
        else {
            return false;
        }
    }
    else {
        cout << "n: " << op._n << endl;
        cout << "min: " << op._min << endl;
        cout << "max: " << op._max << endl;
        cout << "periodic: " << op._periodic << endl;
        cout << "auto: " << op._auto_interval << endl;
        cout << "extend: " << op._extend_interval << endl;
        cout << "scale: " << op._scale << endl;
        cout << "normalize: " << op._normalize << endl;
    }
    return true;
}

void TabulatedPotential::WriteHistogram(BondedStatistics &bs, vector<string> &args)
{
    ofstream out;
    DataCollection<double>::selection *sel = NULL;

    for(size_t i=1; i<args.size(); i++)
        sel = bs.BondedValues().select(args[i], sel);
    Histogram h(_hist_options);
    h.ProcessData(sel);
    out.open(args[0].c_str());
/*    out << "# histogram, created csg version " <<  VERSION_STR  << endl;
    out << "# n = " << _hist_options._n << endl;
    out << "# min = " << _hist_options._min << endl;
    out << "# max = " << _hist_options._max << endl;
    out << "# periodic = " << _hist_options._periodic << endl;
    out << "# auto = " << _hist_options._auto_interval << endl;
    out << "# extend = " << _hist_options._extend_interval << endl;
    out << "# scale = " << _hist_options._scale << endl;*/
    out << h ;
    out.close();
    cout << "histogram created using " << sel->size() << " data-rows, written to " << args[0] << endl;
    delete sel;
}

void TabulatedPotential::CalcForce(vector<double> &U, vector<double> &F, double dx, bool bPeriodic)
{
    size_t n=U.size();
    double f = 0.5/dx;
    F.resize(n);
    if(bPeriodic)
        F[n-1] = F[0] = -(U[1] - U[n-2])*f;
    else {
        F[0] = -(U[1] - U[0])*2*f;
        F[n-1] = -(U[n-1] - U[n-2])*2*f;
    }
    for(size_t i=1; i<n-1; i++)
        F[i] = -(U[i+1] - U[i-1])*f;
}

void TabulatedPotential::WritePotential(BondedStatistics &bs, vector<string> &args)
{
   ofstream out;
    DataCollection<double>::selection *sel = NULL;

    for(size_t i=1; i<args.size(); i++)
        sel = bs.BondedValues().select(args[i], sel);
    Histogram h(_tab_options);
    h.ProcessData(sel);
    for(int i=0; i<_tab_smooth1; ++i)
        Smooth(h.getPdf(), _tab_options._periodic);
    BoltzmannInvert(h.getPdf(), _T);
    for(int i=0; i<_tab_smooth2; ++i)
        Smooth(h.getPdf(), _tab_options._periodic);
    out.open(args[0].c_str());

/*       out << "# tabulated potential, created csg version " VERSION_STR  << endl;
    out << "# n = " << _tab_options._n << endl;
    out << "# min = " << _tab_options._min << endl;
    out << "# max = " << _tab_options._max << endl;
    out << "# periodic = " << _tab_options._periodic << endl;
    out << "# auto = " << _tab_options._auto_interval << endl;
    out << "# extend = " << _tab_options._extend_interval << endl;
    out << "# scale = " << _tab_options._scale << endl;
    out << "# smooth1 = " << _tab_smooth1 << endl;
    out << "# smooth2 = " << _tab_smooth2 << endl;
    out << "# T = " << _T << endl;*/

    vector<double> F;

    CalcForce(h.getPdf(), F, h.getInterval(), _tab_options._periodic);
    for(int i=0; i<h.getN(); i++) {
        out << h.getMin() + h.getInterval()*((double)i) << " " << h.getPdf()[i] << " " << F[i] << endl;
    }
    out.close();
    cout << "histogram created using " << sel->size() << " data-rows, written to " << args[0] << endl;
    delete sel;
}

void TabulatedPotential::Smooth(vector<double> &data, bool bPeriodic)
{
    double old[3];
    int n=data.size();
    if(bPeriodic) {
        old[0] = data[n-3];
        old[1] = data[n-2];
    }
    else {
        old[0] = data[0];
        old[1] = data[0];
    }
    size_t i;
    for(i=0; i<data.size()-2; i++) {
        old[3] = data[i];
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 2.*data[i+1] + data[i+2])/9.;
        old[0]=old[1];
        old[1]=old[3];;
    }
    if(bPeriodic) {
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 2.*data[i+1] + data[0])/9.;
        old[0]=old[1];old[1]=data[i];
        data[n-1] = data[0];
    }
    else {
        data[i] = (old[0] + 2.*old[1] + 3.*data[i] + 3.*data[i+1])/9.;
        old[0]=old[1];old[1]=data[i];
        i++;
        data[i] = (old[0] + 2.*old[1] + 6.*data[i])/9.;
    }
}

void TabulatedPotential::BoltzmannInvert(vector<double> &data, double T)
{
    double _min, _max;

    _min = numeric_limits<double>::max();
    _max = numeric_limits<double>::min();

    for(size_t i=0; i<data.size(); i++) {
        _max = max(data[i], _max);
        if(data[i] > 0) _min = min(data[i], _min);
    }
    _max = -8.3109*T*log(_max)*0.001;
    _min = -8.3109*T*log(_min)*0.001-_max;

    for(size_t i=0; i<data.size(); i++) {
        if(data[i] == 0) data[i] = _min;
        else
            data[i] = -8.3109*T*log(data[i])*0.001 - _max;
    }
}
<|endoftext|>


<commit_before>// Time:  O(m * n)
// Space: O(1)

class Solution {
public:
    vector<vector<int>> imageSmoother(vector<vector<int>>& M) {
        const auto m = M.size(), n = M[0].size();
        vector<vector<int>> result(M);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                result[i][j] = getGray(M, i, j);
            }
        }
        return result;
    }

private:
    int getGray(const vector<vector<int>>& M, int i, int j) {
        const auto& m = M.size(), n = M[0].size();
        static const vector<pair<int, int>> directions = { {-1, -1}, {0, -1}, {1, -1},
                                                           {-1,  0}, {0,  0}, {1,  0},
                                                           {-1,  1}, {0,  1}, {1,  1} };
        double total = 0.0;
        int count = 0;
        for (const auto& direction : directions) {
            const auto& ii = i + direction.first;
            const auto& jj = j + direction.second;
            if (0 <= ii && ii < m && 0 <= jj && jj < n) {
                total += M[ii][jj];
                ++count;
            }
        }
        return static_cast<int>(total / count);
    }
};
<commit_msg>Update image-smoother.cpp<commit_after>// Time:  O(m * n)
// Space: O(1)

class Solution {
public:
    vector<vector<int>> imageSmoother(vector<vector<int>>& M) {
        const auto m = M.size(), n = M[0].size();
        vector<vector<int>> result(M);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                result[i][j] = getGray(M, i, j);
            }
        }
        return result;
    }

private:
    int getGray(const vector<vector<int>>& M, int i, int j) {
        const auto& m = M.size(), n = M[0].size();
        double total = 0.0;
        int count = 0;
        for (int r = -1; r < 2; ++r) {
            for (int c = -1; c < 2; ++c) {
                const auto& ii = i + r;
                const auto& jj = j + c;
                if (0 <= ii && ii < m && 0 <= jj && jj < n) {
                    total += M[ii][jj];
                    ++count;
                }
            }
        }
        return static_cast<int>(total / count);
    }
};
<|endoftext|>


<commit_before>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    int rotatedDigits(int N) {
        vector<int> dp(N + 1);
        unordered_set<int> same = {0, 1, 8};
        unordered_set<int> diff = {2, 5, 6, 9};
        for (const auto& i : same) {
            if (i <= N) {
                dp[i] = 1;
            }
        }
        for (const auto& i : diff) {
            if (i <= N) {
                dp[i] = 2;
            }
        }
        for (int i = 0; 10 * i <= N; ++i) {
            if (dp[i] > 0) {
                for (const auto& j : same) {
                    if (i * 10 + j <= N) {
                        dp[i * 10 + j] = max(1, dp[i]);
                    }
                }
                for (const auto& j : diff) {
                    if (i * 10 + j <= N) {
                        dp[i * 10 + j] = 2;
                    }
                }
            }
        }
        return accumulate(dp.begin(), dp.end(), 0,
                          [](int a, int b) {
                              return a + static_cast<int>(b == 2);
                          });
    }

};

// Time:  O(nlogn) = O(n), because O(logn) = O(32) by this input
// Space: O(logn) = O(1)
class Solution2 {
public:
    int rotatedDigits(int N) {
        int result = 0;
        for (int i = 0; i <= N; ++i){
            string s(to_string(i));
            unordered_set<char> lookup(s.begin(),s.end());
            if (lookup.count('3') ||
                lookup.count('4') ||
                lookup.count('7')) {
                continue;
            }
            if (lookup.count('2') ||
                lookup.count('5') ||
                lookup.count('6') ||
                lookup.count('9')) {
                ++result;
            }
        }
        return result;
    }
};
<commit_msg>Update rotated-digits.cpp<commit_after>// Time:  O(n)
// Space: O(n)

class Solution {
public:
    int rotatedDigits(int N) {
        enum State { INVALID, SAME, DIFF };
        vector<State> dp(N + 1);
        unordered_set<int> same = {0, 1, 8};
        unordered_set<int> diff = {2, 5, 6, 9};
        for (const auto& i : same) {
            if (i <= N) {
                dp[i] = SAME;
            }
        }
        for (const auto& i : diff) {
            if (i <= N) {
                dp[i] = DIFF;
            }
        }
        for (int i = 0; 10 * i <= N; ++i) {
            if (dp[i] != INVALID) {
                for (const auto& j : same) {
                    if (i * 10 + j <= N) {
                        dp[i * 10 + j] = max(SAME, dp[i]);
                    }
                }
                for (const auto& j : diff) {
                    if (i * 10 + j <= N) {
                        dp[i * 10 + j] = DIFF;
                    }
                }
            }
        }
        return accumulate(dp.begin(), dp.end(), 0,
                          [](int a, int b) {
                              return a + static_cast<int>(b == DIFF);
                          });
    }

};

// Time:  O(nlogn) = O(n), because O(logn) = O(32) by this input
// Space: O(logn) = O(1)
class Solution2 {
public:
    int rotatedDigits(int N) {
        int result = 0;
        for (int i = 0; i <= N; ++i){
            string s(to_string(i));
            unordered_set<char> lookup(s.begin(),s.end());
            if (lookup.count('3') ||
                lookup.count('4') ||
                lookup.count('7')) {
                continue;
            }
            if (lookup.count('2') ||
                lookup.count('5') ||
                lookup.count('6') ||
                lookup.count('9')) {
                ++result;
            }
        }
        return result;
    }
};
<|endoftext|>


<commit_before>//============================================================================
// Name        : hw-verilog.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <random>
#include <stdlib.h>
#include <time.h>
#include "Cromossomo.h"
#include "Populacao.h"
#include "IcarusFitnessCalculator.h"

int main() {
	std::mt19937 mt;
	mt.seed(time(nullptr));
	Populacao<20, 4, 1, 4, 2, 2> populacao(mt, true,
			new IcarusFitnessCalculator(4, 1,
					[](const std::vector<std::vector<std::bitset<8>>>& individual_output)
					-> double {
						int num_acertos = 0;
						for (unsigned int i = 0; i < 15; i++) {
							num_acertos += individual_output[i][0] == 0;
						}
						num_acertos += individual_output[15][0] == 1;
						if (num_acertos == 16) {
							return 200000000.0;
						}
						return 1.0 / (double) num_acertos;
					}));

	populacao.proxima_geracao();

	populacao.melhor_individuo().criar_arquivo_verilog("melhor.v");

	return 0;
}
<commit_msg>Implementado main loop do algoritmo genético.<commit_after>//============================================================================
// Name        : hw-verilog.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <random>
#include <stdlib.h>
#include <time.h>
#include "Cromossomo.h"
#include "Populacao.h"
#include "IcarusFitnessCalculator.h"

int main() {
	const double MELHOR_FITNESS = 20000000.0;
	std::mt19937 mt;
	mt.seed(time(nullptr));
	Populacao<20, 4, 1, 4, 5, 5> populacao(mt, true,
			new IcarusFitnessCalculator(4, 1,
					[&](const std::vector<std::vector<std::bitset<8>>>& individual_output)
					-> double {
						int num_acertos = 0;
						for (unsigned int i = 0; i < 15; i++) {
							num_acertos += individual_output[i][0] == 0;
						}
						num_acertos += individual_output[15][0] == 1;
						if (num_acertos == 16) {
							return MELHOR_FITNESS;
						}
						return 1.0 / (double) num_acertos;
					}));

	int geracao = 0;
	while (populacao.melhor_individuo().fitness() != MELHOR_FITNESS) {
		populacao.proxima_geracao();
		std::cout << ++geracao << ": " <<
				populacao.melhor_individuo().fitness() << std::endl;
	}

	populacao.melhor_individuo().criar_arquivo_verilog("melhor.v");

	return 0;
}
<|endoftext|>


<commit_before>// Copyright 2016, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Björn Buchhold (buchhold@informatik.uni-freiburg.de)

#include <fstream>
#include "../util/StringUtils.h"
#include "../util/Exception.h"
#include "../util/Log.h"
#include "./QueryPlanningCostFactors.h"

// _____________________________________________________________________________
QueryPlanningCostFactors::QueryPlanningCostFactors() : _factors() {
  // Set default values
  _factors["FILTER_PUNISH"] = 10.0;
  _factors["NO_FILTER_PUNISH"] = 1.0;
  _factors["FILTER_SELECTIVITY"] = 0.1;
  _factors["HASH_MAP_OPERATION_COST"] = 20.0;
  _factors["JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR"] = 0.7;
  _factors["DUMMY_JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR"] = 1000.0;
  _factors["DISK_RANDOM_ACCESS_COST"] = 1000;
}

// _____________________________________________________________________________
void QueryPlanningCostFactors::readFromFile(const string& fileName) {
  std::ifstream in(fileName.c_str());
  string line;
  while (std::getline(in, line)) {
    auto v = ad_utility::split(line, '\t');
    AD_CHECK_EQ(v.size(), 2);
    LOG(INFO) << "Setting cost factor: " << v[0] << " from "
              << _factors[v[0]] << " to " << atof(v[1].c_str()) << '\n';
    _factors[v[0]] = atof(v[1].c_str());

  }
}

// _____________________________________________________________________________
double QueryPlanningCostFactors::getCostFactor(const string& key) const {
  return _factors.find(key)->second;
}

<commit_msg>trying different cost factors, now that a bug has been fixed<commit_after>// Copyright 2016, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Björn Buchhold (buchhold@informatik.uni-freiburg.de)

#include <fstream>
#include "../util/StringUtils.h"
#include "../util/Exception.h"
#include "../util/Log.h"
#include "./QueryPlanningCostFactors.h"

// _____________________________________________________________________________
QueryPlanningCostFactors::QueryPlanningCostFactors() : _factors() {
  // Set default values
  _factors["FILTER_PUNISH"] = 2.0;
  _factors["NO_FILTER_PUNISH"] = 1.0;
  _factors["FILTER_SELECTIVITY"] = 0.1;
  _factors["HASH_MAP_OPERATION_COST"] = 50.0;
  _factors["JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR"] = 0.7;
  _factors["DUMMY_JOIN_SIZE_ESTIMATE_CORRECTION_FACTOR"] = 1000.0;
  _factors["DISK_RANDOM_ACCESS_COST"] = 1000;
}

// _____________________________________________________________________________
void QueryPlanningCostFactors::readFromFile(const string& fileName) {
  std::ifstream in(fileName.c_str());
  string line;
  while (std::getline(in, line)) {
    auto v = ad_utility::split(line, '\t');
    AD_CHECK_EQ(v.size(), 2);
    LOG(INFO) << "Setting cost factor: " << v[0] << " from "
              << _factors[v[0]] << " to " << atof(v[1].c_str()) << '\n';
    _factors[v[0]] = atof(v[1].c_str());

  }
}

// _____________________________________________________________________________
double QueryPlanningCostFactors::getCostFactor(const string& key) const {
  return _factors.find(key)->second;
}

<|endoftext|>


<commit_before>#include "engine/guidance/post_processing.hpp"
#include "extractor/guidance/turn_instruction.hpp"

#include "engine/guidance/toolkit.hpp"

#include <boost/assert.hpp>
#include <iostream>

using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
using TurnType = osrm::extractor::guidance::TurnType;
using DirectionModifier = osrm::extractor::guidance::DirectionModifier;

namespace osrm
{
namespace engine
{
namespace guidance
{

namespace detail
{
bool canMergeTrivially(const PathData &destination, const PathData &source)
{
    return destination.exit == 0 && destination.name_id == source.name_id &&
           destination.travel_mode == source.travel_mode && isSilent(destination.turn_instruction);
}

PathData forwardInto(PathData destination, const PathData &source)
{
    // Merge a turn into a silent turn
    // Overwrites turn instruction and increases exit NR
    destination.duration_until_turn += source.duration_until_turn;
    destination.exit = source.exit;
    return destination;
}

PathData accumulateInto(PathData destination, const PathData &source)
{
    // Merge a turn into a silent turn
    // Overwrites turn instruction and increases exit NR
    BOOST_ASSERT(canMergeTrivially(destination, source));
    destination.duration_until_turn += source.duration_until_turn;
    destination.exit = source.exit + 1;
    return destination;
}

PathData mergeInto(PathData destination, const PathData &source)
{
    if (source.turn_instruction == TurnInstruction::NO_TURN())
    {
        BOOST_ASSERT(canMergeTrivially(destination, source));
        return detail::forwardInto(destination, source);
    }
    if (source.turn_instruction.type == TurnType::Suppressed)
    {
        return detail::forwardInto(destination, source);
    }
    if (source.turn_instruction.type == TurnType::StayOnRoundabout)
    {
        return detail::forwardInto(destination, source);
    }
    if (entersRoundabout(source.turn_instruction))
    {
        return detail::forwardInto(destination, source);
    }
    return destination;
}

} // namespace detail

void print(const std::vector<std::vector<PathData>> &leg_data)
{
    std::cout << "Path\n";
    int legnr = 0;
    for (const auto &leg : leg_data)
    {
        std::cout << "\tLeg: " << ++legnr << "\n";
        int segment = 0;
        for (const auto &data : leg)
        {
            std::cout << "\t\t[" << ++segment << "]: " << (int)data.turn_instruction.type << " "
                      << (int)data.turn_instruction.direction_modifier << " exit: " << data.exit
                      << "\n";
        }
    }
    std::cout << std::endl;
}

std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
{
    if (leg_data.empty())
        return leg_data;

#define PRINT_DEBUG 0
    unsigned carry_exit = 0;
#if PRINT_DEBUG
    std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
    std::cout << "Input\n";
    print(leg_data);
#endif
    // Count Street Exits forward
    bool on_roundabout = false;
    for (auto &path_data : leg_data)
    {
        if (not path_data.empty())
            path_data[0].exit = carry_exit;

        for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
        {
            if (entersRoundabout(path_data[data_index].turn_instruction))
            {
                path_data[data_index].exit += 1;
                on_roundabout = true;
            }

            if (isSilent(path_data[data_index].turn_instruction) &&
                path_data[data_index].turn_instruction != TurnInstruction::NO_TURN())
            {
                path_data[data_index].exit += 1;
            }
            if (leavesRoundabout(path_data[data_index].turn_instruction))
            {
                if (!on_roundabout)
                {
                    BOOST_ASSERT(leg_data[0][0].turn_instruction.type ==
                                 TurnInstruction::NO_TURN());
                    if (path_data[data_index].turn_instruction.type == TurnType::ExitRoundabout)
                        leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
                    if (path_data[data_index].turn_instruction.type == TurnType::ExitRotary)
                        leg_data[0][0].turn_instruction.type = TurnType::EnterRotary;
                    path_data[data_index].exit += 1;
                }
                on_roundabout = false;
            }
            if (path_data[data_index].turn_instruction.type == TurnType::EnterRoundaboutAtExit)
            {
                path_data[data_index].exit += 1;
                path_data[data_index].turn_instruction.type = TurnType::EnterRoundabout;
            }
            else if (path_data[data_index].turn_instruction.type == TurnType::EnterRotaryAtExit)
            {
                path_data[data_index].exit += 1;
                path_data[data_index].turn_instruction.type = TurnType::EnterRotary;
            }

            if (isSilent(path_data[data_index].turn_instruction) ||
                entersRoundabout(path_data[data_index].turn_instruction))
            {
                path_data[data_index + 1] =
                    detail::mergeInto(path_data[data_index + 1], path_data[data_index]);
            }
            carry_exit = path_data[data_index].exit;
        }
    }
#if PRINT_DEBUG
    std::cout << "Merged\n";
    print(leg_data);
#endif
    on_roundabout = false;
    // Move Roundabout exit numbers to front
    for (auto rev_itr = leg_data.rbegin(); rev_itr != leg_data.rend(); ++rev_itr)
    {
        auto &path_data = *rev_itr;
        for (std::size_t data_index = path_data.size(); data_index > 1; --data_index)
        {
            if (entersRoundabout(path_data[data_index - 1].turn_instruction))
            {
                if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction))
                    path_data[data_index - 1].exit = 0;
                on_roundabout = false;
            }
            if (on_roundabout)
            {
                path_data[data_index - 2].exit = path_data[data_index - 1].exit;
            }
            if (leavesRoundabout(path_data[data_index - 1].turn_instruction) &&
                !entersRoundabout(path_data[data_index - 1].turn_instruction))
            {
                path_data[data_index - 2].exit = path_data[data_index - 1].exit;
                on_roundabout = true;
            }
        }
        auto prev_leg = std::next(rev_itr);
        if (!path_data.empty() && prev_leg != leg_data.rend())
        {
            if (on_roundabout && path_data[0].exit)
                prev_leg->back().exit = path_data[0].exit;
        }
    }

#if PRINT_DEBUG
    std::cout << "Move To Front\n";
    print(leg_data);
#endif
    // silence silent turns for good
    for (auto &path_data : leg_data)
    {
        for (auto &data : path_data)
        {
            if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) &&
                                                    !entersRoundabout(data.turn_instruction)))
            {
                data.turn_instruction = TurnInstruction::NO_TURN();
                data.duration_until_turn = 0;
                data.exit = 0;
            }
        }
    }

    return std::move(leg_data);
}

} // namespace guidance
} // namespace engine
} // namespace osrm
<commit_msg>Uses static_casts for underlying type in post processing<commit_after>#include "engine/guidance/post_processing.hpp"
#include "extractor/guidance/turn_instruction.hpp"

#include "engine/guidance/toolkit.hpp"

#include <boost/assert.hpp>
#include <iostream>
#include <vector>

using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
using TurnType = osrm::extractor::guidance::TurnType;
using DirectionModifier = osrm::extractor::guidance::DirectionModifier;

namespace osrm
{
namespace engine
{
namespace guidance
{

namespace detail
{
bool canMergeTrivially(const PathData &destination, const PathData &source)
{
    return destination.exit == 0 && destination.name_id == source.name_id &&
           destination.travel_mode == source.travel_mode && isSilent(destination.turn_instruction);
}

PathData forwardInto(PathData destination, const PathData &source)
{
    // Merge a turn into a silent turn
    // Overwrites turn instruction and increases exit NR
    destination.duration_until_turn += source.duration_until_turn;
    destination.exit = source.exit;
    return destination;
}

PathData accumulateInto(PathData destination, const PathData &source)
{
    // Merge a turn into a silent turn
    // Overwrites turn instruction and increases exit NR
    BOOST_ASSERT(canMergeTrivially(destination, source));
    destination.duration_until_turn += source.duration_until_turn;
    destination.exit = source.exit + 1;
    return destination;
}

PathData mergeInto(PathData destination, const PathData &source)
{
    if (source.turn_instruction == TurnInstruction::NO_TURN())
    {
        BOOST_ASSERT(canMergeTrivially(destination, source));
        return detail::forwardInto(destination, source);
    }
    if (source.turn_instruction.type == TurnType::Suppressed)
    {
        return detail::forwardInto(destination, source);
    }
    if (source.turn_instruction.type == TurnType::StayOnRoundabout)
    {
        return detail::forwardInto(destination, source);
    }
    if (entersRoundabout(source.turn_instruction))
    {
        return detail::forwardInto(destination, source);
    }
    return destination;
}

} // namespace detail

void print(const std::vector<std::vector<PathData>> &leg_data)
{
    std::cout << "Path\n";
    int legnr = 0;
    for (const auto &leg : leg_data)
    {
        std::cout << "\tLeg: " << ++legnr << "\n";
        int segment = 0;
        for (const auto &data : leg)
        {
            const auto type = static_cast<int>(data.turn_instruction.type);
            const auto modifier = static_cast<int>(data.turn_instruction.direction_modifier);

            std::cout << "\t\t[" << ++segment << "]: " << type << " " << modifier
                      << " exit: " << data.exit << "\n";
        }
    }
    std::cout << std::endl;
}

std::vector<std::vector<PathData>> postProcess(std::vector<std::vector<PathData>> leg_data)
{
    if (leg_data.empty())
        return leg_data;

#define PRINT_DEBUG 0
    unsigned carry_exit = 0;
#if PRINT_DEBUG
    std::cout << "[POSTPROCESSING ITERATION]" << std::endl;
    std::cout << "Input\n";
    print(leg_data);
#endif
    // Count Street Exits forward
    bool on_roundabout = false;
    for (auto &path_data : leg_data)
    {
        if (not path_data.empty())
            path_data[0].exit = carry_exit;

        for (std::size_t data_index = 0; data_index + 1 < path_data.size(); ++data_index)
        {
            if (entersRoundabout(path_data[data_index].turn_instruction))
            {
                path_data[data_index].exit += 1;
                on_roundabout = true;
            }

            if (isSilent(path_data[data_index].turn_instruction) &&
                path_data[data_index].turn_instruction != TurnInstruction::NO_TURN())
            {
                path_data[data_index].exit += 1;
            }
            if (leavesRoundabout(path_data[data_index].turn_instruction))
            {
                if (!on_roundabout)
                {
                    BOOST_ASSERT(leg_data[0][0].turn_instruction.type ==
                                 TurnInstruction::NO_TURN());
                    if (path_data[data_index].turn_instruction.type == TurnType::ExitRoundabout)
                        leg_data[0][0].turn_instruction.type = TurnType::EnterRoundabout;
                    if (path_data[data_index].turn_instruction.type == TurnType::ExitRotary)
                        leg_data[0][0].turn_instruction.type = TurnType::EnterRotary;
                    path_data[data_index].exit += 1;
                }
                on_roundabout = false;
            }
            if (path_data[data_index].turn_instruction.type == TurnType::EnterRoundaboutAtExit)
            {
                path_data[data_index].exit += 1;
                path_data[data_index].turn_instruction.type = TurnType::EnterRoundabout;
            }
            else if (path_data[data_index].turn_instruction.type == TurnType::EnterRotaryAtExit)
            {
                path_data[data_index].exit += 1;
                path_data[data_index].turn_instruction.type = TurnType::EnterRotary;
            }

            if (isSilent(path_data[data_index].turn_instruction) ||
                entersRoundabout(path_data[data_index].turn_instruction))
            {
                path_data[data_index + 1] =
                    detail::mergeInto(path_data[data_index + 1], path_data[data_index]);
            }
            carry_exit = path_data[data_index].exit;
        }
    }
#if PRINT_DEBUG
    std::cout << "Merged\n";
    print(leg_data);
#endif
    on_roundabout = false;
    // Move Roundabout exit numbers to front
    for (auto rev_itr = leg_data.rbegin(); rev_itr != leg_data.rend(); ++rev_itr)
    {
        auto &path_data = *rev_itr;
        for (std::size_t data_index = path_data.size(); data_index > 1; --data_index)
        {
            if (entersRoundabout(path_data[data_index - 1].turn_instruction))
            {
                if (!on_roundabout && !leavesRoundabout(path_data[data_index - 1].turn_instruction))
                    path_data[data_index - 1].exit = 0;
                on_roundabout = false;
            }
            if (on_roundabout)
            {
                path_data[data_index - 2].exit = path_data[data_index - 1].exit;
            }
            if (leavesRoundabout(path_data[data_index - 1].turn_instruction) &&
                !entersRoundabout(path_data[data_index - 1].turn_instruction))
            {
                path_data[data_index - 2].exit = path_data[data_index - 1].exit;
                on_roundabout = true;
            }
        }
        auto prev_leg = std::next(rev_itr);
        if (!path_data.empty() && prev_leg != leg_data.rend())
        {
            if (on_roundabout && path_data[0].exit)
                prev_leg->back().exit = path_data[0].exit;
        }
    }

#if PRINT_DEBUG
    std::cout << "Move To Front\n";
    print(leg_data);
#endif
    // silence silent turns for good
    for (auto &path_data : leg_data)
    {
        for (auto &data : path_data)
        {
            if (isSilent(data.turn_instruction) || (leavesRoundabout(data.turn_instruction) &&
                                                    !entersRoundabout(data.turn_instruction)))
            {
                data.turn_instruction = TurnInstruction::NO_TURN();
                data.duration_until_turn = 0;
                data.exit = 0;
            }
        }
    }

    return std::move(leg_data);
}

} // namespace guidance
} // namespace engine
} // namespace osrm
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <bh.h>
#include <map>
#include <string>
#include <algorithm>
#include <tuple>
#include <iostream>
#include <sstream>

using namespace std;

/** Create a new base array.
 *
 * @param type The type of data in the array
 * @param nelements The number of elements
 * @param new_base The handler for the newly created base
 * @return Error code (BH_SUCCESS, BH_OUT_OF_MEMORY)
 */
bh_error bh_create_base(bh_type    type,
                        bh_index   nelements,
                        bh_base**  new_base)
{

    bh_base *base = (bh_base *) malloc(sizeof(bh_base));
    if(base == NULL)
        return BH_OUT_OF_MEMORY;
    base->type = type;
    base->nelem = nelements;
    base->data = NULL;
    *new_base = base;

    return BH_SUCCESS;
}

/** Destroy the base array.
 *
 * @param base  The base array in question
 */
void bh_destroy_base(bh_base**  base)
{
    bh_base *b = *base;
    free(b);
    b = NULL;
}

// Returns the label of this base array
// NB: generated a new label if necessary
static map<const bh_base*, unsigned int>label_map;
unsigned int bh_base::get_label() const
{
   if(label_map.find(this) == label_map.end())
       label_map[this] = label_map.size();
   return label_map[this];
}

ostream& operator<<(ostream& out, const bh_base& b)
{
    unsigned int label = b.get_label();
    out << "a" << label << "{dtype: " << bh_type_text(b.type) << ", nelem: " \
        << b.nelem << ", address: " << &b << "}";
    return out;
}

string bh_base::str() const
{
    stringstream ss;
    ss << *this;
    return ss.str();
}

vector<tuple<int64_t, int64_t, int64_t> > bh_view::python_notation() const
{
    //stride&shape&index for each dimension (in that order)
    vector<tuple<int64_t, int64_t, int64_t> > sns;
    for(int64_t i=0; i<this->ndim; ++i)
    {
        sns.push_back(make_tuple(this->stride[i], this->shape[i], i));
    }
    //Let's sort them such that the greatest strides comes first
    sort(sns.begin(), sns.end(), greater<tuple<int64_t, int64_t, int64_t> >());

    //Now let's compute start&end&stride of each dimension, which
    //makes up the python notation e.g. [2:4:1]
    vector<tuple<int64_t, int64_t, int64_t> > sne(sns.size());
    int64_t offset = this->start;
    for(size_t i=0; i<sns.size(); ++i)
    {
        int64_t stride = std::get<0>(sns[i]);
        int64_t shape  = std::get<1>(sns[i]);
        int64_t index  = std::get<2>(sns[i]);

        int64_t start = 0;
        if (stride > 0)//avoid division by zero
            start = offset / stride;
        int64_t end = start + shape;
        offset -= start * stride;
        sne[index] = make_tuple(start, end, stride);
    }

    /*
    //Find the contiguous strides, that is the stride of each dimension
    //assuming the view is contiguous.
    int64_t cont_stride = 1;
    for(int64_t i=sns.size()-1; i >= 0; --i)
    {
        int64_t stride = std::get<0>(sns[i]);
        int64_t shape  = std::get<1>(sns[i]);
        int64_t index  = std::get<2>(sns[i]);

        if(stride == cont_stride)
            std::get<2>(sne[index]) = -1;//Flag it as unnecessary
        cont_stride *= shape;
    }
    */
    return sne;
}

ostream& operator<<(ostream& out, const bh_view& v)
{
    unsigned int label = v.base->get_label();
    out << "a" << label << "[";

    for(const tuple<int64_t, int64_t, int64_t> sne: v.python_notation())
    {
        int64_t start  = std::get<0>(sne);
        int64_t end    = std::get<1>(sne);
        int64_t stride = std::get<2>(sne);
        out << start << ":" << end << ":" << stride << ",";
    }
    out << "]";
    return out;
}
<commit_msg>core: minor cleanup<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#include <bh.h>
#include <map>
#include <string>
#include <algorithm>
#include <tuple>
#include <iostream>
#include <sstream>

using namespace std;

/** Create a new base array.
 *
 * @param type The type of data in the array
 * @param nelements The number of elements
 * @param new_base The handler for the newly created base
 * @return Error code (BH_SUCCESS, BH_OUT_OF_MEMORY)
 */
bh_error bh_create_base(bh_type    type,
                        bh_index   nelements,
                        bh_base**  new_base)
{

    bh_base *base = (bh_base *) malloc(sizeof(bh_base));
    if(base == NULL)
        return BH_OUT_OF_MEMORY;
    base->type = type;
    base->nelem = nelements;
    base->data = NULL;
    *new_base = base;

    return BH_SUCCESS;
}

/** Destroy the base array.
 *
 * @param base  The base array in question
 */
void bh_destroy_base(bh_base**  base)
{
    bh_base *b = *base;
    free(b);
    b = NULL;
}

// Returns the label of this base array
// NB: generated a new label if necessary
static map<const bh_base*, unsigned int>label_map;
unsigned int bh_base::get_label() const
{
   if(label_map.find(this) == label_map.end())
       label_map[this] = label_map.size();
   return label_map[this];
}

ostream& operator<<(ostream& out, const bh_base& b)
{
    unsigned int label = b.get_label();
    out << "a" << label << "{dtype: " << bh_type_text(b.type) << ", nelem: " \
        << b.nelem << ", address: " << &b << "}";
    return out;
}

string bh_base::str() const
{
    stringstream ss;
    ss << *this;
    return ss.str();
}

vector<tuple<int64_t, int64_t, int64_t> > bh_view::python_notation() const
{
    //stride&shape&index for each dimension (in that order)
    vector<tuple<int64_t, int64_t, int64_t> > sns;
    for(int64_t i=0; i<this->ndim; ++i)
    {
        sns.push_back(make_tuple(this->stride[i], this->shape[i], i));
    }
    //Let's sort them such that the greatest strides comes first
    sort(sns.begin(), sns.end(), greater<tuple<int64_t, int64_t, int64_t> >());

    //Now let's compute start&end&stride of each dimension, which
    //makes up the python notation e.g. [2:4:1]
    vector<tuple<int64_t, int64_t, int64_t> > sne(sns.size());
    int64_t offset = this->start;
    for(size_t i=0; i<sns.size(); ++i)
    {
        int64_t stride = std::get<0>(sns[i]);
        int64_t shape  = std::get<1>(sns[i]);
        int64_t index  = std::get<2>(sns[i]);

        int64_t start = 0;
        if (stride > 0)//avoid division by zero
            start = offset / stride;
        int64_t end = start + shape;
        offset -= start * stride;
        sne[index] = make_tuple(start, end, stride);
    }

    /*
    //Find the contiguous strides, that is the stride of each dimension
    //assuming the view is contiguous.
    int64_t cont_stride = 1;
    for(int64_t i=sns.size()-1; i >= 0; --i)
    {
        int64_t stride = std::get<0>(sns[i]);
        int64_t shape  = std::get<1>(sns[i]);
        int64_t index  = std::get<2>(sns[i]);

        if(stride == cont_stride)
            std::get<2>(sne[index]) = -1;//Flag it as unnecessary
        cont_stride *= shape;
    }
    */
    return sne;
}

ostream& operator<<(ostream& out, const bh_view& v)
{
    unsigned int label = v.base->get_label();
    out << "a" << label << "[";

    const vector<tuple<int64_t, int64_t, int64_t> > sne = v.python_notation();
    for(size_t i=0; i<sne.size(); ++i)
    {
        int64_t start  = std::get<0>(sne[i]);
        int64_t end    = std::get<1>(sne[i]);
        int64_t stride = std::get<2>(sne[i]);
        out << start << ":" << end << ":" << stride;
        if(i < sne.size()-1)//Not the last iteration
            out << ",";
    }
    out << "]";
    return out;
}
<|endoftext|>


<commit_before>#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/find_if.hpp>

#include <boost/assert.hpp>

#include <algorithm>
#include <functional>
#include <limits>

namespace osrm
{
namespace extractor
{
namespace guidance
{

ConnectedRoad::ConnectedRoad(const TurnOperation turn, const bool entry_allowed)
    : TurnOperation(turn), entry_allowed(entry_allowed)
{
}

bool ConnectedRoad::compareByAngle(const ConnectedRoad &other) const { return angle < other.angle; }

void ConnectedRoad::mirror()
{
    const constexpr DirectionModifier::Enum mirrored_modifiers[] = {DirectionModifier::UTurn,
                                                                    DirectionModifier::SharpLeft,
                                                                    DirectionModifier::Left,
                                                                    DirectionModifier::SlightLeft,
                                                                    DirectionModifier::Straight,
                                                                    DirectionModifier::SlightRight,
                                                                    DirectionModifier::Right,
                                                                    DirectionModifier::SharpRight};

    static_assert(sizeof(mirrored_modifiers) / sizeof(DirectionModifier::Enum) ==
                      DirectionModifier::MaxDirectionModifier,
                  "The list of mirrored modifiers needs to match the available modifiers in size.");

    if (angularDeviation(angle, 0) > std::numeric_limits<double>::epsilon())
    {
        angle = 360 - angle;
        instruction.direction_modifier = mirrored_modifiers[instruction.direction_modifier];
    }
}

ConnectedRoad ConnectedRoad::getMirroredCopy() const
{
    ConnectedRoad copy(*this);
    copy.mirror();
    return copy;
}

std::string toString(const ConnectedRoad &road)
{
    std::string result = "[connection] ";
    result += std::to_string(road.eid);
    result += " allows entry: ";
    result += std::to_string(road.entry_allowed);
    result += " angle: ";
    result += std::to_string(road.angle);
    result += " bearing: ";
    result += std::to_string(road.bearing);
    result += " instruction: ";
    result += std::to_string(static_cast<std::int32_t>(road.instruction.type)) + " " +
              std::to_string(static_cast<std::int32_t>(road.instruction.direction_modifier)) + " " +
              std::to_string(static_cast<std::int32_t>(road.lane_data_id));
    return result;
}

Intersection::Base::iterator Intersection::findClosestTurn(double angle)
{
    // use the const operator to avoid code duplication
    return begin() +
           std::distance(cbegin(), static_cast<const Intersection *>(this)->findClosestTurn(angle));
}

Intersection::Base::const_iterator Intersection::findClosestTurn(double angle) const
{
    return std::min_element(
        begin(), end(), [angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
            return util::guidance::angularDeviation(lhs.angle, angle) <
                   util::guidance::angularDeviation(rhs.angle, angle);
        });
}

bool Intersection::valid() const
{
    return !empty() &&
           std::is_sorted(begin(), end(), std::mem_fn(&ConnectedRoad::compareByAngle)) &&
           operator[](0).angle < std::numeric_limits<double>::epsilon();
}

std::uint8_t
Intersection::getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &graph) const
{
    BOOST_ASSERT(valid()); // non empty()

    const auto to_lane_count = [&](const ConnectedRoad &road) {
        return graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
    };

    // boost::range::transformed sadly does not work with lamdas since they are not copy
    // constructable. We need to work around this :(
    std::uint8_t max_lanes = 0;
    const auto extract_maximal_value = [&max_lanes](std::uint8_t value) {
        max_lanes = std::max(max_lanes, value);
        return false;
    };

    const auto view = *this | boost::adaptors::transformed(to_lane_count);
    boost::range::find_if(view, extract_maximal_value);
    return max_lanes;
}

} // namespace guidance
} // namespace extractor
} // namespace osrm
<commit_msg>Use explicit std::function for to_lane_count instead of auto<commit_after>#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"

#include <boost/range/adaptor/transformed.hpp>
#include <boost/range/algorithm/find_if.hpp>

#include <boost/assert.hpp>

#include <algorithm>
#include <functional>
#include <limits>

namespace osrm
{
namespace extractor
{
namespace guidance
{

ConnectedRoad::ConnectedRoad(const TurnOperation turn, const bool entry_allowed)
    : TurnOperation(turn), entry_allowed(entry_allowed)
{
}

bool ConnectedRoad::compareByAngle(const ConnectedRoad &other) const { return angle < other.angle; }

void ConnectedRoad::mirror()
{
    const constexpr DirectionModifier::Enum mirrored_modifiers[] = {DirectionModifier::UTurn,
                                                                    DirectionModifier::SharpLeft,
                                                                    DirectionModifier::Left,
                                                                    DirectionModifier::SlightLeft,
                                                                    DirectionModifier::Straight,
                                                                    DirectionModifier::SlightRight,
                                                                    DirectionModifier::Right,
                                                                    DirectionModifier::SharpRight};

    static_assert(sizeof(mirrored_modifiers) / sizeof(DirectionModifier::Enum) ==
                      DirectionModifier::MaxDirectionModifier,
                  "The list of mirrored modifiers needs to match the available modifiers in size.");

    if (angularDeviation(angle, 0) > std::numeric_limits<double>::epsilon())
    {
        angle = 360 - angle;
        instruction.direction_modifier = mirrored_modifiers[instruction.direction_modifier];
    }
}

ConnectedRoad ConnectedRoad::getMirroredCopy() const
{
    ConnectedRoad copy(*this);
    copy.mirror();
    return copy;
}

std::string toString(const ConnectedRoad &road)
{
    std::string result = "[connection] ";
    result += std::to_string(road.eid);
    result += " allows entry: ";
    result += std::to_string(road.entry_allowed);
    result += " angle: ";
    result += std::to_string(road.angle);
    result += " bearing: ";
    result += std::to_string(road.bearing);
    result += " instruction: ";
    result += std::to_string(static_cast<std::int32_t>(road.instruction.type)) + " " +
              std::to_string(static_cast<std::int32_t>(road.instruction.direction_modifier)) + " " +
              std::to_string(static_cast<std::int32_t>(road.lane_data_id));
    return result;
}

Intersection::Base::iterator Intersection::findClosestTurn(double angle)
{
    // use the const operator to avoid code duplication
    return begin() +
           std::distance(cbegin(), static_cast<const Intersection *>(this)->findClosestTurn(angle));
}

Intersection::Base::const_iterator Intersection::findClosestTurn(double angle) const
{
    return std::min_element(
        begin(), end(), [angle](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
            return util::guidance::angularDeviation(lhs.angle, angle) <
                   util::guidance::angularDeviation(rhs.angle, angle);
        });
}

bool Intersection::valid() const
{
    return !empty() &&
           std::is_sorted(begin(), end(), std::mem_fn(&ConnectedRoad::compareByAngle)) &&
           operator[](0).angle < std::numeric_limits<double>::epsilon();
}

std::uint8_t
Intersection::getHighestConnectedLaneCount(const util::NodeBasedDynamicGraph &graph) const
{
    BOOST_ASSERT(valid()); // non empty()

    const std::function<std::uint8_t(const ConnectedRoad &)> to_lane_count =
        [&](const ConnectedRoad &road) {
            return graph.GetEdgeData(road.eid).road_classification.GetNumberOfLanes();
        };

    std::uint8_t max_lanes = 0;
    const auto extract_maximal_value = [&max_lanes](std::uint8_t value) {
        max_lanes = std::max(max_lanes, value);
        return false;
    };

    const auto view = *this | boost::adaptors::transformed(to_lane_count);
    boost::range::find_if(view, extract_maximal_value);
    return max_lanes;
}

} // namespace guidance
} // namespace extractor
} // namespace osrm
<|endoftext|>


<commit_before>/* Copyright (C) 2018, Project Pluto

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TLE struct tle
#define MAX_TLES 20000

TLE
   {
   char name_line[80], line1[80], line2[80];
   };

int n_duplicates = 0, heavens_above_html_tles = 0;

int load_tles_from_file( FILE *ifile, TLE *tles, char *already_found)
{
   int rval = 0;
   char buff[80], prev_line[80];

   *prev_line = '\0';
   while( fgets( buff, sizeof( buff), ifile))
      {
      if( *buff == '1' && heavens_above_html_tles &&
                            !memcmp( buff + 69, "", 7))
         strcpy( buff + 69, "\n");
      if( *buff == '1' && strlen( buff) > 69 && buff[69] < ' ')
         {
         char buff2[80];
         const int norad_number = atoi( buff + 2);

         if( fgets( buff2, sizeof( buff2), ifile))
            if( *buff2 == '2' && strlen( buff2) > 69 && buff2[69] < ' ')
               {
               if( !already_found[norad_number])
                  {
                  if( heavens_above_html_tles)     /* can't use HA names */
                     *prev_line = '\0';
                  strcpy( tles[rval].name_line, prev_line);
                  strcpy( tles[rval].line1, buff);
                  strcpy( tles[rval].line2, buff2);
                  already_found[norad_number] = 1;
                  rval++;
                  *buff = '\0';
                  }
               else
                  n_duplicates++;
               }
         }
      strcpy( prev_line, buff);
      }
   return( rval);
}

FILE *test_fopen( const char *filename, const char *permits)
{
   FILE *rval = fopen( filename, permits);

   if( !rval)
      {
      printf( "%s not opened\n", filename);
      exit( -1);
      }
   return( rval);
}

void show_tle( FILE *ofile, const TLE *tle)
{
   fprintf( ofile, "%s", tle->name_line);
   fprintf( ofile, "%s", tle->line1);
   fprintf( ofile, "%s", tle->line2);
}

static int compare_doubles( const char *buff1, const char *buff2)
{
   const double d1 = atof( buff1);
   const double d2 = atof( buff2);
   int rval;

   if( d1 < d2)
      rval = -1;
   else if( d1 > d2)
      rval = 1;
   else
      rval = 0;
   return( rval);
}

int tle_compare( const TLE *tle1, const TLE *tle2, const char sort_method)
{
   int i, rval = 0;

   switch( sort_method)
      {
      case 'n': case 'N':        /* sort by NORAD number */
         for( i = 2; !rval && i < 8; i++)
            rval = tle1->line1[i] - tle2->line1[i];
         break;
      case 'm': case 'M':        /* sort by mean motion */
         rval = compare_doubles( tle1->line2 + 52, tle2->line2 + 52);
         break;
      case 'e': case 'E':        /* sort by eccentricity */
         for( i = 26; !rval && i < 33; i++)
            rval = tle1->line2[i] - tle2->line2[i];
         break;
      case 'p': case 'P':        /* sort by epoch */
         for( i = 18; !rval && i < 32; i++)
            rval = tle1->line1[i] - tle2->line1[i];
         break;
      }
   if( sort_method >= 'A' && sort_method <= 'Z')
      rval = -rval;
   return( rval);
}

      /* MS Windows lacks the re-entrant qsort_r;  we have to use  */
      /* plain old non-re-entrant qsort and a global variable.     */
      /* BSD has it,  but with the wrong order of arguments.       */
#ifdef __linux
#define HAVE_REENTRANT_QSORT
#endif

#ifdef HAVE_REENTRANT_QSORT
int tle_compare_for_qsort_r( const void *a, const void *b, void *c)
{
   return( tle_compare( (const TLE *)a, (const TLE *)b, *(char *)c));
}
#else
static char comparison_method;

int tle_compare_for_qsort( const void *a, const void *b)
{
   return( tle_compare( (const TLE *)a, (const TLE *)b, comparison_method));
}
#endif

static void error_exit( void)
{
   printf( "'mergetle' will merge TLEs from one or more files.  Optionally,\n");
   printf( "the output can be sorted.  For example:\n\n");
   printf( "mergetle geosynch.tle molniya.tle visual.tle -se -oall.tle\n\n");
   printf( "would create a file 'all.tle',  containing elements from the three\n");
   printf( "input .tle files,  sorted by NORAD number.  If a satellite appears\n");
   printf( "in more than one .tle,  the .tle from the first file on the command\n");
   printf( "line is used.  Options are:\n\n");
   printf( "-sn, -sN       Sort output by ascending/descending NORAD number\n");
   printf( "-sm, -sM       Sort output by ascending/descending mean motion\n");
   printf( "-se, -sE       Sort output by ascending/descending eccentricity\n");
   printf( "-sp, -sP       Sort output by ascending/descending epoch\n");
   printf( "-o(filename)   Set name of output .tle file (default is out.tle)\n");
   printf( "-n             Remove names from input TLEs\n");
   printf( "-h             Remove HTML tags from input.  This allows you to extract\n");
   printf( "                 TLEs from certain Web pages.\n");
   exit( -1);
}

int main( const int argc, const char **argv)
{
   TLE *tles = (TLE *)calloc( MAX_TLES, sizeof( TLE));
   char *already_found = (char *)calloc( 100000, sizeof( char));
   int n_found = 0, i, strip_names = 0;
   char sort_method = 0;
   const char *output_filename = "out.tle";
   FILE *ofile;

   if( argc < 2)
      error_exit( );
   for( i = 1; i < argc; i++)
      if( argv[i][0] == '-')
         switch( argv[i][1])
            {
            case 'o':
               output_filename = argv[i] + 2;
               break;
            case 's':
               sort_method = argv[i][2];
               break;
            case 'n':
               strip_names = 1;
               printf( "Names will be removed in output\n");
               break;
            case 'h':
               heavens_above_html_tles = 1;
               printf( "HTML tags will be removed from input\n");
               break;
            default:
               printf( "Ignoring unknown option '%s'\n", argv[i]);
               break;
            }
      else
         {
         FILE *ifile = test_fopen( argv[i], "rb");
         int n;

         n_duplicates = 0;
         n = load_tles_from_file( ifile, tles + n_found, already_found);
         printf( "%d TLEs added from %s,  with %d duplicates found\n",
                            n, argv[i], n_duplicates);
         n_found += n;
         fclose( ifile);
         }
   free( already_found);
   if( strip_names)
      for( i = 0; i < n_found; i++)
         tles[i].name_line[0] = '\0';
#ifndef HAVE_REENTRANT_QSORT
   comparison_method = sort_method;
   qsort( tles, n_found, sizeof( TLE), tle_compare_for_qsort);
#else
   qsort_r( tles, n_found, sizeof( TLE), tle_compare_for_qsort_r, &sort_method);
#endif
   ofile = test_fopen( output_filename, "wb");
   for( i = 0; i < n_found; i++)
      show_tle( ofile, tles + i);
}
<commit_msg>'mergetle' can now sort TLEs by inclination or ascending node<commit_after>/* Copyright (C) 2018, Project Pluto

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TLE struct tle
#define MAX_TLES 20000

TLE
   {
   char name_line[80], line1[80], line2[80];
   };

int n_duplicates = 0, heavens_above_html_tles = 0;

int load_tles_from_file( FILE *ifile, TLE *tles, char *already_found)
{
   int rval = 0;
   char buff[80], prev_line[80];

   *prev_line = '\0';
   while( fgets( buff, sizeof( buff), ifile))
      {
      if( *buff == '1' && heavens_above_html_tles &&
                            !memcmp( buff + 69, "", 7))
         strcpy( buff + 69, "\n");
      if( *buff == '1' && strlen( buff) > 69 && buff[69] < ' ')
         {
         char buff2[80];
         const int norad_number = atoi( buff + 2);

         if( fgets( buff2, sizeof( buff2), ifile))
            if( *buff2 == '2' && strlen( buff2) > 69 && buff2[69] < ' ')
               {
               if( !already_found[norad_number])
                  {
                  if( heavens_above_html_tles)     /* can't use HA names */
                     *prev_line = '\0';
                  strcpy( tles[rval].name_line, prev_line);
                  strcpy( tles[rval].line1, buff);
                  strcpy( tles[rval].line2, buff2);
                  already_found[norad_number] = 1;
                  rval++;
                  *buff = '\0';
                  }
               else
                  n_duplicates++;
               }
         }
      strcpy( prev_line, buff);
      }
   return( rval);
}

FILE *test_fopen( const char *filename, const char *permits)
{
   FILE *rval = fopen( filename, permits);

   if( !rval)
      {
      printf( "%s not opened\n", filename);
      exit( -1);
      }
   return( rval);
}

void show_tle( FILE *ofile, const TLE *tle)
{
   fprintf( ofile, "%s", tle->name_line);
   fprintf( ofile, "%s", tle->line1);
   fprintf( ofile, "%s", tle->line2);
}

static int compare_doubles( const char *buff1, const char *buff2)
{
   const double d1 = atof( buff1);
   const double d2 = atof( buff2);
   int rval;

   if( d1 < d2)
      rval = -1;
   else if( d1 > d2)
      rval = 1;
   else
      rval = 0;
   return( rval);
}

int tle_compare( const TLE *tle1, const TLE *tle2, const char sort_method)
{
   int i, rval = 0;

   switch( sort_method)
      {
      case 'n': case 'N':        /* sort by NORAD number */
         for( i = 2; !rval && i < 8; i++)
            rval = tle1->line1[i] - tle2->line1[i];
         break;
      case 'm': case 'M':        /* sort by mean motion */
         rval = compare_doubles( tle1->line2 + 52, tle2->line2 + 52);
         break;
      case 'e': case 'E':        /* sort by eccentricity */
         for( i = 26; !rval && i < 33; i++)
            rval = tle1->line2[i] - tle2->line2[i];
         break;
      case 'p': case 'P':        /* sort by epoch */
         for( i = 18; !rval && i < 32; i++)
            rval = tle1->line1[i] - tle2->line1[i];
         break;
      case 'i': case 'I':        /* sort by incl */
         rval = compare_doubles( tle1->line2 + 8, tle2->line2 + 8);
         break;
      case 'o': case 'O':        /* sort by ascending node */
         rval = compare_doubles( tle1->line2 + 17, tle2->line2 + 17);
         break;
      }
   if( sort_method >= 'A' && sort_method <= 'Z')
      rval = -rval;
   return( rval);
}

      /* MS Windows lacks the re-entrant qsort_r;  we have to use  */
      /* plain old non-re-entrant qsort and a global variable.     */
      /* BSD has it,  but with the wrong order of arguments.       */
#ifdef __linux
#define HAVE_REENTRANT_QSORT
#endif

#ifdef HAVE_REENTRANT_QSORT
int tle_compare_for_qsort_r( const void *a, const void *b, void *c)
{
   return( tle_compare( (const TLE *)a, (const TLE *)b, *(char *)c));
}
#else
static char comparison_method;

int tle_compare_for_qsort( const void *a, const void *b)
{
   return( tle_compare( (const TLE *)a, (const TLE *)b, comparison_method));
}
#endif

static void error_exit( void)
{
   printf( "'mergetle' will merge TLEs from one or more files.  Optionally,\n");
   printf( "the output can be sorted.  For example:\n\n");
   printf( "mergetle geosynch.tle molniya.tle visual.tle -se -oall.tle\n\n");
   printf( "would create a file 'all.tle',  containing elements from the three\n");
   printf( "input .tle files,  sorted by NORAD number.  If a satellite appears\n");
   printf( "in more than one .tle,  the .tle from the first file on the command\n");
   printf( "line is used.  Options are:\n\n");
   printf( "-sn, -sN       Sort output by ascending/descending NORAD number\n");
   printf( "-sm, -sM       Sort output by ascending/descending mean motion\n");
   printf( "-se, -sE       Sort output by ascending/descending eccentricity\n");
   printf( "-sp, -sP       Sort output by ascending/descending epoch\n");
   printf( "-si, -sI       Sort output by ascending/descending inclination\n");
   printf( "-so, -sO       Sort output by ascending/descending ascending node\n");
   printf( "-o(filename)   Set name of output .tle file (default is out.tle)\n");
   printf( "-n             Remove names from input TLEs\n");
   printf( "-h             Remove HTML tags from input.  This allows you to extract\n");
   printf( "                 TLEs from certain Web pages.\n");
   exit( -1);
}

int main( const int argc, const char **argv)
{
   TLE *tles = (TLE *)calloc( MAX_TLES, sizeof( TLE));
   char *already_found = (char *)calloc( 100000, sizeof( char));
   int n_found = 0, i, strip_names = 0;
   char sort_method = 0;
   const char *output_filename = "out.tle";
   FILE *ofile;

   if( argc < 2)
      error_exit( );
   for( i = 1; i < argc; i++)
      if( argv[i][0] == '-')
         switch( argv[i][1])
            {
            case 'o':
               output_filename = argv[i] + 2;
               break;
            case 's':
               sort_method = argv[i][2];
               break;
            case 'n':
               strip_names = 1;
               printf( "Names will be removed in output\n");
               break;
            case 'h':
               heavens_above_html_tles = 1;
               printf( "HTML tags will be removed from input\n");
               break;
            default:
               printf( "Ignoring unknown option '%s'\n", argv[i]);
               break;
            }
      else
         {
         FILE *ifile = test_fopen( argv[i], "rb");
         int n;

         n_duplicates = 0;
         n = load_tles_from_file( ifile, tles + n_found, already_found);
         printf( "%d TLEs added from %s,  with %d duplicates found\n",
                            n, argv[i], n_duplicates);
         n_found += n;
         fclose( ifile);
         }
   free( already_found);
   if( strip_names)
      for( i = 0; i < n_found; i++)
         tles[i].name_line[0] = '\0';
#ifndef HAVE_REENTRANT_QSORT
   comparison_method = sort_method;
   qsort( tles, n_found, sizeof( TLE), tle_compare_for_qsort);
#else
   qsort_r( tles, n_found, sizeof( TLE), tle_compare_for_qsort_r, &sort_method);
#endif
   ofile = test_fopen( output_filename, "wb");
   for( i = 0; i < n_found; i++)
      show_tle( ofile, tles + i);
}
<|endoftext|>