<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.Secretfile.c_str());
    Secret=read_Secretfile(F.Secretfile,F);

    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    //diagnostic
    int count_ss=0;
    int count_sf=0;
    for(int g=0;g<M.size();++g){
        if(M[g].SS) count_ss++;
        if(M[g].SF) count_sf++;
    }
    printf("  number SS = %d  number SF = %d\n",count_ss,count_sf);

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if any SS or SF are assigned
    int SS_count=0;
    int SF_count=0;
    std::vector <int> class_count(3,0);
    for( int j=0;j<F.Nplate;++j){
        for (int k=0;k<F.Nfiber;++k){
            if(A.TF[j][k]!=-1){
                if(M[A.TF[j][k]].SS)SS_count++;
                if(M[A.TF[j][k]].SF)SF_count++;
                class_count[M[A.TF[j][k]].priority_class]++;
            }
        }
    }
    printf("after simple assign,  SS assigned %d  SF assigned %d\n",SS_count,SF_count);
    printf(" class 0 %d  class 1 %d  class 2 %d\n", class_count[0],class_count[1],class_count[2]);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //diagnostic
    /*
    for (int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("  js = %d  available SF for fibers\n",js);
        for (int k=0;k<10;++k){
            printf(" %d ",P[js].SF_av_gal_fiber[k*500].size());
        }
        printf("\n  petals");
        for (int q=0;q<F.Npetal;++q){
            printf(" %d",P[js].SF_av_gal[q].size());
        }
        printf("\n");
    }
    */

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        //printf(" before assign_sf_ss js= %d\n",js);
        A.next_plate=js;
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        //printf("before assign_unused js= %d \n",js);
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        printf(" before pass = %d  at %d  tiles\n",i,update_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.NUsedplate; jj++) {
            int j = A.suborder[jj];
            //printf("  next plate is %d \n",j);
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            //A.next_plate++;
        }
        //update target information for interval i
        //A.next_plate=F.pass_intervals[i];
        for (int jj=update_intervals[i]; jj<update_intervals[i+1]; jj++) {
            //int j = A.suborder[A.next_plate];
            //int js=A.suborder[jj];
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            //A.next_plate++;
        }

        //if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);
    }
    // check on SS and SF

    for(int js=0;js<F.NUsedplate;++js){
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>fix diagnostic for SS SF<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("# Read %s galaxies from %s \n",f(F.Ngal).c_str(),F.Secretfile.c_str());
    Secret=read_Secretfile(F.Secretfile,F);

    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    //diagnostic
    int count_ss=0;
    int count_sf=0;
    for(int g=0;g<M.size();++g){
        if(M[g].SS) count_ss++;
        if(M[g].SF) count_sf++;
    }
    printf("  number SS = %d  number SF = %d\n",count_ss,count_sf);

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);

	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if any SS or SF are assigned
    int SS_count=0;
    int SF_count=0;
    std::vector <int> class_count(3,0);
    for( int j=0;j<F.Nplate;++j){
        for (int k=0;k<F.Nfiber;++k){
            if(A.TF[j][k]!=-1){
                if(M[A.TF[j][k]].SS)SS_count++;
                if(M[A.TF[j][k]].SF)SF_count++;
                class_count[M[A.TF[j][k]].priority_class]++;
            }
        }
    }
    printf("after simple assign,  SS assigned %d  SF assigned %d\n",SS_count,SF_count);
    printf(" class 0 %d  class 1 %d  class 2 %d\n", class_count[0],class_count[1],class_count[2]);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //diagnostic
    /*
    for (int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("  js = %d  available SF for fibers\n",js);
        for (int k=0;k<10;++k){
            printf(" %d ",P[js].SF_av_gal_fiber[k*500].size());
        }
        printf("\n  petals");
        for (int q=0;q<F.Npetal;++q){
            printf(" %d",P[js].SF_av_gal[q].size());
        }
        printf("\n");
    }
    */

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A);
		redistribute_tf(M,P,pp,F,A);
	}

	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        //printf(" before assign_sf_ss js= %d\n",js);
        A.next_plate=js;
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        //printf("before assign_unused js= %d \n",js);
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        printf(" before pass = %d  at %d  tiles\n",i,update_intervals[i]);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        A.next_plate=F.pass_intervals[i];
        for (int jj=F.pass_intervals[i]; jj<F.NUsedplate; jj++) {
            int j = A.suborder[jj];
            //printf("  next plate is %d \n",j);
            assign_sf_ss(j,M,P,pp,F,A); // Assign SS and SF
            assign_unused(j,M,P,pp,F,A);
            //A.next_plate++;
        }
        //update target information for interval i
        //A.next_plate=F.pass_intervals[i];
        for (int jj=update_intervals[i]; jj<update_intervals[i+1]; jj++) {
            //int j = A.suborder[A.next_plate];
            //int js=A.suborder[jj];
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A,F.Nplate-1); else printf("\n");
            //A.next_plate++;
        }

        //if(A.next_plate<F.Nplate){
        redistribute_tf(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        improve(M,P,pp,F,A);
        redistribute_tf(M,P,pp,F,A);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);
    }
    // check on SS and SF

    for(int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>


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

#include "openma/io/handlerplugin.h"
#include "openma/io/device.h"
#include "openma/io/enums.h"
#include "openma/base/pluginmanager.h"

// #ifdef OPENMA_IO_STATIC_DEFINE
#include "../plugins/staticiopluginloader.h"
// #endif

namespace ma
{
namespace io
{
  /**
   * Convenient method to load handler plugins.
   * Internally this method uses a static object. It will be populated the first time this function is used.
   */
  const std::vector<HandlerPlugin*>& load_handler_plugins()
  {
    static PluginManager<HandlerPlugin> manager;
    if (manager.plugins().empty())
    {
// #ifndef OPENMA_IO_STATIC_DEFINE
      // Dynamic loading
      // {"trialformats","bodyformats"})
// #error Not yet implemented
// #else
      // Static include
      load_handler_plugins(&manager);
// #endif
    }
    return manager.plugins();
  };

  /**
   * @class HandlerPlugin openma/io/handlerplugin.h
   * @brief Interface to load handler(s) dynamically.
   *
   * A format is a string composed of two parts. Both separated by a dot. The left side of the dot is the name of company that developed the format (e.g.'codamotion'), while the right part is the (file) extension used for this format (e.g. mdf).
   *
   * @ingroup openma_io
   */

  /**
   * Default constructor
   */
  HandlerPlugin::HandlerPlugin()
  {};

  /**
   * Destructor (default)
   */
  HandlerPlugin::~HandlerPlugin() = default;

  /**
   * @fn virtual std::vector<std::string> supportedFormats() const _OPENMA_NOEXCEPT = 0;
   * Returns a list of supported format by this plugin.
   */

  /**
   * @fn virtual Capability HandlerPlugin::capabilities(const std::string& format) const _OPENMA_NOEXCEPT
   * Returns the capabilities availble for a handler managed by this plugin. In case multiple handlers are managed by this plugin, you can use @a format to returns the corresponding capabilities. For example:
   * @code{.unparsed}
   * Capability MyHandler::capabilities(const std::string& format) const _OPENMA_NOEXCEPT
   * {
   *    if (format.compare("openma.foo") == 0)
   *      eturn Capability::CanReadAndWrite;
   *    else if (format.compare("openma.bar") == 0)
   *      eturn Capability::CanRead;
   * };
   * @endcode
   */

  /**
   * @fn virtual Signature HandlerPlugin::detectSignature(const Device* const device, std::string* format) const _OPENMA_NOEXCEPT = 0;
   * Detect the signature used fo one of the supported format. If the string @a format is not null, the detected format will be set. Because, the @a device is a const pointer, it is needed to use the method Device::peek() to extract content without modifying the device.
   * In case no signature exists for the supported formats, this method shall return Signature::NotAvailable.
   */

  /**
   * Try to detect the extension used by one of the supported format in the string @a str.
   * If the string @a format is not null, the detected format will be set inside.
   * @note This detection method is not robust. If possible use the signature detection.
   */
  bool HandlerPlugin::detectExtension(const std::string& str, std::string* format) const _OPENMA_NOEXCEPT
  {
    auto formats = this->supportedFormats();
    auto idx = str.find_last_of('.');
    if (idx != std::string::npos)
    {
      auto ext = str.substr(idx+1);
      auto len = ext.length();
      for (const auto& f: formats)
      {
        if (f.substr(f.length()-len,len).compare(ext) == 0)
        {
          if (format != nullptr)
            *format = f;
          return true;
        }
      }
    }
    return false;
  };

  /**
   * @fn virtual Handler* HandlerPlugin::create(Device* device, const std::string& format) = 0;
   * Create a new handler. The @a device is passed to the created handler. The usage of @a format can be twofold. First, it can be used to verify if the given format is supported by this plugin. Second, it will help to choose the good handler if multiple formats are managed by the plugin.
   */
};
};<commit_msg>Force the extension and format to be in lower case before the comparison.<commit_after>/*
 * Open Source Movement Analysis Library
 * Copyright (C) 2016, Moveck Solution Inc., all rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *     * Redistributions of source code must retain the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials
 *       provided with the distribution.
 *     * Neither the name(s) of the copyright holders nor the names
 *       of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written
 *       permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "openma/io/handlerplugin.h"
#include "openma/io/device.h"
#include "openma/io/enums.h"
#include "openma/base/pluginmanager.h"

// #ifdef OPENMA_IO_STATIC_DEFINE
#include "../plugins/staticiopluginloader.h"
// #endif

#include <algorithm> // std::transform

namespace ma
{
namespace io
{
  /**
   * Convenient method to load handler plugins.
   * Internally this method uses a static object. It will be populated the first time this function is used.
   */
  const std::vector<HandlerPlugin*>& load_handler_plugins()
  {
    static PluginManager<HandlerPlugin> manager;
    if (manager.plugins().empty())
    {
// #ifndef OPENMA_IO_STATIC_DEFINE
      // Dynamic loading
      // {"trialformats","bodyformats"})
// #error Not yet implemented
// #else
      // Static include
      load_handler_plugins(&manager);
// #endif
    }
    return manager.plugins();
  };

  /**
   * @class HandlerPlugin openma/io/handlerplugin.h
   * @brief Interface to load handler(s) dynamically.
   *
   * A format is a string composed of two parts. Both separated by a dot. The left side of the dot is the name of company that developed the format (e.g.'codamotion'), while the right part is the (file) extension used for this format (e.g. mdf).
   *
   * @ingroup openma_io
   */

  /**
   * Default constructor
   */
  HandlerPlugin::HandlerPlugin()
  {};

  /**
   * Destructor (default)
   */
  HandlerPlugin::~HandlerPlugin() = default;

  /**
   * @fn virtual std::vector<std::string> supportedFormats() const _OPENMA_NOEXCEPT = 0;
   * Returns a list of supported format by this plugin.
   */

  /**
   * @fn virtual Capability HandlerPlugin::capabilities(const std::string& format) const _OPENMA_NOEXCEPT
   * Returns the capabilities availble for a handler managed by this plugin. In case multiple handlers are managed by this plugin, you can use @a format to returns the corresponding capabilities. For example:
   * @code{.unparsed}
   * Capability MyHandler::capabilities(const std::string& format) const _OPENMA_NOEXCEPT
   * {
   *    if (format.compare("openma.foo") == 0)
   *      return Capability::CanReadAndWrite;
   *    else if (format.compare("openma.bar") == 0)
   *      return Capability::CanRead;
   * };
   * @endcode
   */

  /**
   * @fn virtual Signature HandlerPlugin::detectSignature(const Device* const device, std::string* format) const _OPENMA_NOEXCEPT = 0;
   * Detect the signature used fo one of the supported format. If the string @a format is not null, the detected format will be set. Because, the @a device is a const pointer, it is needed to use the method Device::peek() to extract content without modifying the device.
   * In case no signature exists for the supported formats, this method shall return Signature::NotAvailable.
   */

  /**
   * Try to detect the extension used by one of the supported format in the string @a str.
   * If the string @a format is not null, the detected format will be set inside.
   * @note This detection method is not robust. If possible use the signature detection.
   */
  bool HandlerPlugin::detectExtension(const std::string& str, std::string* format) const _OPENMA_NOEXCEPT
  {
    auto formats = this->supportedFormats();
    auto idx = str.find_last_of('.');
    if ((idx != std::string::npos) && (idx != (str.size()-1)))
    {
      auto ext = str.substr(idx+1);
      std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
      auto len = ext.length();
      for (const auto& f: formats)
      {
        auto subf = f.substr(f.length()-len,len);
        std::transform(subf.begin(), subf.end(), subf.begin(), tolower);
        if (subf.compare(ext) == 0)
        {
          if (format != nullptr)
            *format = f;
          return true;
        }
      }
    }
    return false;
  };

  /**
   * @fn virtual Handler* HandlerPlugin::create(Device* device, const std::string& format) = 0;
   * Create a new handler. The @a device is passed to the created handler. The usage of @a format can be twofold. First, it can be used to verify if the given format is supported by this plugin. Second, it will help to choose the good handler if multiple formats are managed by the plugin.
   */
};
};<|endoftext|>


<commit_before>#include <clpeak.h>

#define MSTRINGIFY(...) #__VA_ARGS__

static const char *stringifiedKernels =
    #include "global_bandwidth_kernels.cl"
    #include "compute_sp_kernels.cl"
    #include "compute_hp_kernels.cl"
    #include "compute_dp_kernels.cl"
    #include "compute_integer_kernels.cl"
    ;

static const char *stringifiedKernelsNoInt =
    #include "global_bandwidth_kernels.cl"
    #include "compute_sp_kernels.cl"
    #include "compute_hp_kernels.cl"
    #include "compute_dp_kernels.cl"
    ;

#ifdef USE_STUB_OPENCL
// Prototype
extern "C" {
void stubOpenclReset();
}
#endif

clPeak::clPeak(): forcePlatform(false), forceDevice(false), useEventTimer(false),
    isGlobalBW(true), isComputeSP(true), isComputeDP(true), isComputeInt(true),
    isTransferBW(true), isKernelLatency(true),
    specifiedPlatform(-1), specifiedDevice(-1)
{
}

clPeak::~clPeak()
{
  if(log) delete log;
}

int clPeak::runAll()
{
  try
  {
#ifdef USE_STUB_OPENCL
    stubOpenclReset();
#endif
    vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    log->xmlOpenTag("clpeak");
    log->xmlAppendAttribs("os", OS_NAME);
    for(int p=0; p < (int)platforms.size(); p++)
    {
      if(forcePlatform && (p != specifiedPlatform))
        continue;

      std::string platformName = platforms[p].getInfo<CL_PLATFORM_NAME>();
      trimString(platformName);

      log->print(NEWLINE "Platform: " + platformName + NEWLINE);
      log->xmlOpenTag("platform");
      log->xmlAppendAttribs("name", platformName);

      bool isIntel = (platformName.find("Intel") != std::string::npos)? true: false;
      bool isApple = (platformName.find("Apple") != std::string::npos)? true: false;
      bool isSnapdragon = (platformName.find("Snapdragon") != std::string::npos) ? true : false;

      cl_context_properties cps[3] = {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)(platforms[p])(),
        0
      };

      // Use only gpus in snapdragon, it would crash otherwise!
      cl_device_type device_type = (isSnapdragon)? CL_DEVICE_TYPE_GPU: CL_DEVICE_TYPE_ALL;

      cl::Context ctx(device_type, cps);
      vector<cl::Device> devices = ctx.getInfo<CL_CONTEXT_DEVICES>();

      cl::Program prog;

      // FIXME Disabling integer compute tests on intel platform
      // Kernel build is taking much much longer time
      // FIXME Disabling integer compute tests on apple platform
      // Causes Segmentation fault: 11
      if(isIntel || isApple)
      {
        cl::Program::Sources source(1, make_pair(stringifiedKernelsNoInt, (strlen(stringifiedKernelsNoInt)+1)));
        isComputeInt = false;
        prog = cl::Program(ctx, source);
      }
      else
      {
        cl::Program::Sources source(1, make_pair(stringifiedKernels, (strlen(stringifiedKernels)+1)));
        prog = cl::Program(ctx, source);
      }

      for(int d=0; d < (int)devices.size(); d++)
      {
        if(forceDevice && (d != specifiedDevice))
          continue;

        device_info_t devInfo = getDeviceInfo(devices[d]);

        log->print(TAB "Device: " + devInfo.deviceName + NEWLINE);
        log->print(TAB TAB "Driver version  : ");
        log->print(devInfo.driverVersion);  log->print(" (" OS_NAME ")" NEWLINE);
        log->print(TAB TAB "Compute units   : ");
        log->print(devInfo.numCUs);         log->print(NEWLINE);
        log->print(TAB TAB "Clock frequency : ");
        log->print(devInfo.maxClockFreq);   log->print(" MHz" NEWLINE);
        log->xmlOpenTag("device");
        log->xmlAppendAttribs("name", devInfo.deviceName);
        log->xmlAppendAttribs("driver_version", devInfo.driverVersion);
        log->xmlAppendAttribs("compute_units", devInfo.numCUs);
        log->xmlAppendAttribs("clock_frequency", devInfo.maxClockFreq);
        log->xmlAppendAttribs("clock_frequency_unit", "MHz");

        try
        {
          vector<cl::Device> dev = {devices[d]};
          prog.build(dev, BUILD_OPTIONS);
        }
        catch (cl::Error &error)
        {
          log->print(TAB TAB "Build Log: " + prog.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[d])
                     + NEWLINE NEWLINE);
          continue;
        }

        cl::CommandQueue queue = cl::CommandQueue(ctx, devices[d], CL_QUEUE_PROFILING_ENABLE);

        runGlobalBandwidthTest(queue, prog, devInfo);
        runComputeSP(queue, prog, devInfo);
        runComputeHP(queue, prog, devInfo);
        runComputeDP(queue, prog, devInfo);
        runComputeInteger(queue, prog, devInfo);
        runTransferBandwidthTest(queue, prog, devInfo);
        runKernelLatency(queue, prog, devInfo);

        log->print(NEWLINE);
        log->xmlCloseTag();       // device
      }
      log->xmlCloseTag();           // platform
    }
    log->xmlCloseTag();               // clpeak
  }
  catch(cl::Error &error)
  {
    stringstream ss;
    ss << error.what() << " (" << error.err() << ")" NEWLINE;

    log->print(ss.str());
    return -1;
  }

  return 0;
}

float clPeak::run_kernel(cl::CommandQueue &queue, cl::Kernel &kernel, cl::NDRange &globalSize, cl::NDRange &localSize, int iters)
{
  float timed = 0;

  // Dummy calls
  queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
  queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
  queue.finish();

  if(useEventTimer)
  {
    for(int i=0; i<iters; i++)
    {
      cl::Event timeEvent;

      queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize, NULL, &timeEvent);
      queue.finish();
      timed += timeInUS(timeEvent);
    }
  } else      // std timer
  {
    Timer timer;

    timer.start();
    for(int i=0; i<iters; i++)
    {
      queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
    }
    queue.finish();
    timed = timer.stopAndTime();
  }

  return (timed / iters);
}

<commit_msg>Disable integer kernel in intel only on windows<commit_after>#include <clpeak.h>

#define MSTRINGIFY(...) #__VA_ARGS__

static const char *stringifiedKernels =
    #include "global_bandwidth_kernels.cl"
    #include "compute_sp_kernels.cl"
    #include "compute_hp_kernels.cl"
    #include "compute_dp_kernels.cl"
    #include "compute_integer_kernels.cl"
    ;

static const char *stringifiedKernelsNoInt =
    #include "global_bandwidth_kernels.cl"
    #include "compute_sp_kernels.cl"
    #include "compute_hp_kernels.cl"
    #include "compute_dp_kernels.cl"
    ;

#ifdef USE_STUB_OPENCL
// Prototype
extern "C" {
void stubOpenclReset();
}
#endif

clPeak::clPeak(): forcePlatform(false), forceDevice(false), useEventTimer(false),
    isGlobalBW(true), isComputeSP(true), isComputeDP(true), isComputeInt(true),
    isTransferBW(true), isKernelLatency(true),
    specifiedPlatform(-1), specifiedDevice(-1)
{
}

clPeak::~clPeak()
{
  if(log) delete log;
}

int clPeak::runAll()
{
  try
  {
#ifdef USE_STUB_OPENCL
    stubOpenclReset();
#endif
    vector<cl::Platform> platforms;
    cl::Platform::get(&platforms);

    log->xmlOpenTag("clpeak");
    log->xmlAppendAttribs("os", OS_NAME);
    for(int p=0; p < (int)platforms.size(); p++)
    {
      if(forcePlatform && (p != specifiedPlatform))
        continue;

      std::string platformName = platforms[p].getInfo<CL_PLATFORM_NAME>();
      trimString(platformName);

      log->print(NEWLINE "Platform: " + platformName + NEWLINE);
      log->xmlOpenTag("platform");
      log->xmlAppendAttribs("name", platformName);

      // Disable intel integer kernel only on windows
      bool isIntel = false;
      #if defined(_WIN32)
        isIntel = (platformName.find("Intel") != std::string::npos)? true: false;
      #endif

      bool isApple = (platformName.find("Apple") != std::string::npos)? true: false;
      bool isSnapdragon = (platformName.find("Snapdragon") != std::string::npos) ? true : false;

      cl_context_properties cps[3] = {
        CL_CONTEXT_PLATFORM,
        (cl_context_properties)(platforms[p])(),
        0
      };

      // Use only gpus in snapdragon, it would crash otherwise!
      cl_device_type device_type = (isSnapdragon)? CL_DEVICE_TYPE_GPU: CL_DEVICE_TYPE_ALL;

      cl::Context ctx(device_type, cps);
      vector<cl::Device> devices = ctx.getInfo<CL_CONTEXT_DEVICES>();

      cl::Program prog;

      // FIXME Disabling integer compute tests on intel platform
      // Kernel build is taking much much longer time
      // FIXME Disabling integer compute tests on apple platform
      // Causes Segmentation fault: 11
      if(isIntel || isApple)
      {
        cl::Program::Sources source(1, make_pair(stringifiedKernelsNoInt, (strlen(stringifiedKernelsNoInt)+1)));
        isComputeInt = false;
        prog = cl::Program(ctx, source);
      }
      else
      {
        cl::Program::Sources source(1, make_pair(stringifiedKernels, (strlen(stringifiedKernels)+1)));
        prog = cl::Program(ctx, source);
      }

      for(int d=0; d < (int)devices.size(); d++)
      {
        if(forceDevice && (d != specifiedDevice))
          continue;

        device_info_t devInfo = getDeviceInfo(devices[d]);

        log->print(TAB "Device: " + devInfo.deviceName + NEWLINE);
        log->print(TAB TAB "Driver version  : ");
        log->print(devInfo.driverVersion);  log->print(" (" OS_NAME ")" NEWLINE);
        log->print(TAB TAB "Compute units   : ");
        log->print(devInfo.numCUs);         log->print(NEWLINE);
        log->print(TAB TAB "Clock frequency : ");
        log->print(devInfo.maxClockFreq);   log->print(" MHz" NEWLINE);
        log->xmlOpenTag("device");
        log->xmlAppendAttribs("name", devInfo.deviceName);
        log->xmlAppendAttribs("driver_version", devInfo.driverVersion);
        log->xmlAppendAttribs("compute_units", devInfo.numCUs);
        log->xmlAppendAttribs("clock_frequency", devInfo.maxClockFreq);
        log->xmlAppendAttribs("clock_frequency_unit", "MHz");

        try
        {
          vector<cl::Device> dev = {devices[d]};
          prog.build(dev, BUILD_OPTIONS);
        }
        catch (cl::Error &error)
        {
          log->print(TAB TAB "Build Log: " + prog.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[d])
                     + NEWLINE NEWLINE);
          continue;
        }

        cl::CommandQueue queue = cl::CommandQueue(ctx, devices[d], CL_QUEUE_PROFILING_ENABLE);

        runGlobalBandwidthTest(queue, prog, devInfo);
        runComputeSP(queue, prog, devInfo);
        runComputeHP(queue, prog, devInfo);
        runComputeDP(queue, prog, devInfo);
        runComputeInteger(queue, prog, devInfo);
        runTransferBandwidthTest(queue, prog, devInfo);
        runKernelLatency(queue, prog, devInfo);

        log->print(NEWLINE);
        log->xmlCloseTag();       // device
      }
      log->xmlCloseTag();           // platform
    }
    log->xmlCloseTag();               // clpeak
  }
  catch(cl::Error &error)
  {
    stringstream ss;
    ss << error.what() << " (" << error.err() << ")" NEWLINE;

    log->print(ss.str());
    return -1;
  }

  return 0;
}

float clPeak::run_kernel(cl::CommandQueue &queue, cl::Kernel &kernel, cl::NDRange &globalSize, cl::NDRange &localSize, int iters)
{
  float timed = 0;

  // Dummy calls
  queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
  queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
  queue.finish();

  if(useEventTimer)
  {
    for(int i=0; i<iters; i++)
    {
      cl::Event timeEvent;

      queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize, NULL, &timeEvent);
      queue.finish();
      timed += timeInUS(timeEvent);
    }
  } else      // std timer
  {
    Timer timer;

    timer.start();
    for(int i=0; i<iters; i++)
    {
      queue.enqueueNDRangeKernel(kernel, cl::NullRange, globalSize, localSize);
    }
    queue.finish();
    timed = timer.stopAndTime();
  }

  return (timed / iters);
}

<|endoftext|>


<commit_before>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/bootstrapper.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/cpu-profiler.h"
#include "src/debug.h"
#include "src/prettyprinter.h"
#include "src/rewriter.h"
#include "src/runtime.h"

namespace v8 {
namespace internal {

#if defined(_WIN64)
typedef double (*ModuloFunction)(double, double);
static ModuloFunction modulo_function = NULL;
// Defined in codegen-x64.cc.
ModuloFunction CreateModuloFunction();

void init_modulo_function() {
  modulo_function = CreateModuloFunction();
}

double modulo(double x, double y) {
  // Note: here we rely on dependent reads being ordered. This is true
  // on all architectures we currently support.
  return (*modulo_function)(x, y);
}
#elif defined(_WIN32)

double modulo(double x, double y) {
  // Workaround MS fmod bugs. ECMA-262 says:
  // dividend is finite and divisor is an infinity => result equals dividend
  // dividend is a zero and divisor is nonzero finite => result equals dividend
  if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
      !(x == 0 && (y != 0 && std::isfinite(y)))) {
    x = fmod(x, y);
  }
  return x;
}
#else  // POSIX

double modulo(double x, double y) {
  return std::fmod(x, y);
}
#endif  // defined(_WIN64)

#define UNARY_MATH_FUNCTION(name, generator)             \
static UnaryMathFunction fast_##name##_function = NULL;  \
void init_fast_##name##_function() {                     \
  fast_##name##_function = generator;                    \
}                                                        \
double fast_##name(double x) {                           \
  return (*fast_##name##_function)(x);                   \
}

UNARY_MATH_FUNCTION(exp, CreateExpFunction())
UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())

#undef UNARY_MATH_FUNCTION

void lazily_initialize_fast_exp() {
  if (fast_exp_function == NULL) {
    init_fast_exp_function();
  }
}

#define __ ACCESS_MASM(masm_)

#ifdef DEBUG

Comment::Comment(MacroAssembler* masm, const char* msg)
    : masm_(masm), msg_(msg) {
  __ RecordComment(msg);
}

Comment::~Comment() {
  if (msg_[0] == '[') __ RecordComment("]");
}

#endif  // DEBUG

#undef __

void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
  bool print_source = false;
  bool print_ast = false;
  const char* ftype;

  if (info->isolate()->bootstrapper()->IsActive()) {
    print_source = FLAG_print_builtin_source;
    print_ast = FLAG_print_builtin_ast;
    ftype = "builtin";
  } else {
    print_source = FLAG_print_source;
    print_ast = FLAG_print_ast;
    ftype = "user-defined";
  }

  if (FLAG_trace_codegen || print_source || print_ast) {
    PrintF("[generating %s code for %s function: ", kind, ftype);
    if (info->IsStub()) {
      const char* name =
          CodeStub::MajorName(info->code_stub()->MajorKey(), true);
      PrintF("%s", name == NULL ? "<unknown>" : name);
    } else {
      PrintF("%s", info->function()->debug_name()->ToCString().get());
    }
    PrintF("]\n");
  }

#ifdef DEBUG
  if (!info->IsStub() && print_source) {
    PrintF("--- Source from AST ---\n%s\n",
           PrettyPrinter(info->zone()).PrintProgram(info->function()));
  }

  if (!info->IsStub() && print_ast) {
    PrintF("--- AST ---\n%s\n",
           AstPrinter(info->zone()).PrintProgram(info->function()));
  }
#endif  // DEBUG
}

Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
                                             Code::Flags flags,
                                             CompilationInfo* info) {
  Isolate* isolate = info->isolate();

  // Allocate and install the code.
  CodeDesc desc;
  bool is_crankshafted =
      Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
      info->IsStub();
  masm->GetCode(&desc);
  Handle<Code> code =
      isolate->factory()->NewCode(desc, flags, masm->CodeObject(),
                                  false, is_crankshafted,
                                  info->prologue_offset(),
                                  info->is_debug() && !is_crankshafted);
  isolate->counters()->total_compiled_code_size()->Increment(
      code->instruction_size());
  isolate->heap()->IncrementCodeGeneratedBytes(is_crankshafted,
      code->instruction_size());
  return code;
}

void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
#ifdef ENABLE_DISASSEMBLER
  AllowDeferredHandleDereference allow_deference_for_print_code;
  bool print_code = info->isolate()->bootstrapper()->IsActive()
      ? FLAG_print_builtin_code
      : (FLAG_print_code ||
         (info->IsStub() && FLAG_print_code_stubs) ||
         (info->IsOptimizing() && FLAG_print_opt_code));
  if (print_code) {
    // Print the source code if available.
    FunctionLiteral* function = info->function();
    bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION ||
        code->kind() == Code::FUNCTION;

    CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
    OFStream os(tracing_scope.file());
    if (print_source) {
      Handle<Script> script = info->script();
      if (!script->IsUndefined() && !script->source()->IsUndefined()) {
        os << "--- Raw source ---\n";
        ConsStringIteratorOp op;
        StringCharacterStream stream(String::cast(script->source()),
                                     &op,
                                     function->start_position());
        // fun->end_position() points to the last character in the stream. We
        // need to compensate by adding one to calculate the length.
        int source_len =
            function->end_position() - function->start_position() + 1;
        for (int i = 0; i < source_len; i++) {
          if (stream.HasMore()) {
            os << AsReversiblyEscapedUC16(stream.GetNext());
          }
        }
        os << "\n\n";
      }
    }
    if (info->IsOptimizing()) {
      if (FLAG_print_unopt_code) {
        os << "--- Unoptimized code ---\n";
        info->closure()->shared()->code()->Disassemble(
            function->debug_name()->ToCString().get(), os);
      }
      os << "--- Optimized code ---\n"
         << "optimization_id = " << info->optimization_id() << "\n";
    } else {
      os << "--- Code ---\n";
    }
    if (print_source) {
      os << "source_position = " << function->start_position() << "\n";
    }
    if (info->IsStub()) {
      CodeStub::Major major_key = info->code_stub()->MajorKey();
      code->Disassemble(CodeStub::MajorName(major_key, false), os);
    } else {
      code->Disassemble(function->debug_name()->ToCString().get(), os);
    }
    os << "--- End code ---\n";
  }
#endif  // ENABLE_DISASSEMBLER
}

bool CodeGenerator::RecordPositions(MacroAssembler* masm,
                                    int pos,
                                    bool right_here) {
  if (pos != RelocInfo::kNoPosition) {
    masm->positions_recorder()->RecordStatementPosition(pos);
    masm->positions_recorder()->RecordPosition(pos);
    if (right_here) {
      return masm->positions_recorder()->WriteRecordedPositions();
    }
  }
  return false;
}

} }  // namespace v8::internal
<commit_msg>Allow trace-codegen to dereference handles.<commit_after>// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#include "src/bootstrapper.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/cpu-profiler.h"
#include "src/debug.h"
#include "src/prettyprinter.h"
#include "src/rewriter.h"
#include "src/runtime.h"

namespace v8 {
namespace internal {

#if defined(_WIN64)
typedef double (*ModuloFunction)(double, double);
static ModuloFunction modulo_function = NULL;
// Defined in codegen-x64.cc.
ModuloFunction CreateModuloFunction();

void init_modulo_function() {
  modulo_function = CreateModuloFunction();
}

double modulo(double x, double y) {
  // Note: here we rely on dependent reads being ordered. This is true
  // on all architectures we currently support.
  return (*modulo_function)(x, y);
}
#elif defined(_WIN32)

double modulo(double x, double y) {
  // Workaround MS fmod bugs. ECMA-262 says:
  // dividend is finite and divisor is an infinity => result equals dividend
  // dividend is a zero and divisor is nonzero finite => result equals dividend
  if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
      !(x == 0 && (y != 0 && std::isfinite(y)))) {
    x = fmod(x, y);
  }
  return x;
}
#else  // POSIX

double modulo(double x, double y) {
  return std::fmod(x, y);
}
#endif  // defined(_WIN64)

#define UNARY_MATH_FUNCTION(name, generator)             \
static UnaryMathFunction fast_##name##_function = NULL;  \
void init_fast_##name##_function() {                     \
  fast_##name##_function = generator;                    \
}                                                        \
double fast_##name(double x) {                           \
  return (*fast_##name##_function)(x);                   \
}

UNARY_MATH_FUNCTION(exp, CreateExpFunction())
UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())

#undef UNARY_MATH_FUNCTION

void lazily_initialize_fast_exp() {
  if (fast_exp_function == NULL) {
    init_fast_exp_function();
  }
}

#define __ ACCESS_MASM(masm_)

#ifdef DEBUG

Comment::Comment(MacroAssembler* masm, const char* msg)
    : masm_(masm), msg_(msg) {
  __ RecordComment(msg);
}

Comment::~Comment() {
  if (msg_[0] == '[') __ RecordComment("]");
}

#endif  // DEBUG

#undef __

void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
  bool print_source = false;
  bool print_ast = false;
  const char* ftype;

  if (info->isolate()->bootstrapper()->IsActive()) {
    print_source = FLAG_print_builtin_source;
    print_ast = FLAG_print_builtin_ast;
    ftype = "builtin";
  } else {
    print_source = FLAG_print_source;
    print_ast = FLAG_print_ast;
    ftype = "user-defined";
  }

  if (FLAG_trace_codegen || print_source || print_ast) {
    PrintF("[generating %s code for %s function: ", kind, ftype);
    if (info->IsStub()) {
      const char* name =
          CodeStub::MajorName(info->code_stub()->MajorKey(), true);
      PrintF("%s", name == NULL ? "<unknown>" : name);
    } else {
      AllowDeferredHandleDereference allow_deference_for_trace;
      PrintF("%s", info->function()->debug_name()->ToCString().get());
    }
    PrintF("]\n");
  }

#ifdef DEBUG
  if (!info->IsStub() && print_source) {
    PrintF("--- Source from AST ---\n%s\n",
           PrettyPrinter(info->zone()).PrintProgram(info->function()));
  }

  if (!info->IsStub() && print_ast) {
    PrintF("--- AST ---\n%s\n",
           AstPrinter(info->zone()).PrintProgram(info->function()));
  }
#endif  // DEBUG
}

Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
                                             Code::Flags flags,
                                             CompilationInfo* info) {
  Isolate* isolate = info->isolate();

  // Allocate and install the code.
  CodeDesc desc;
  bool is_crankshafted =
      Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
      info->IsStub();
  masm->GetCode(&desc);
  Handle<Code> code =
      isolate->factory()->NewCode(desc, flags, masm->CodeObject(),
                                  false, is_crankshafted,
                                  info->prologue_offset(),
                                  info->is_debug() && !is_crankshafted);
  isolate->counters()->total_compiled_code_size()->Increment(
      code->instruction_size());
  isolate->heap()->IncrementCodeGeneratedBytes(is_crankshafted,
      code->instruction_size());
  return code;
}

void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
#ifdef ENABLE_DISASSEMBLER
  AllowDeferredHandleDereference allow_deference_for_print_code;
  bool print_code = info->isolate()->bootstrapper()->IsActive()
      ? FLAG_print_builtin_code
      : (FLAG_print_code ||
         (info->IsStub() && FLAG_print_code_stubs) ||
         (info->IsOptimizing() && FLAG_print_opt_code));
  if (print_code) {
    // Print the source code if available.
    FunctionLiteral* function = info->function();
    bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION ||
        code->kind() == Code::FUNCTION;

    CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
    OFStream os(tracing_scope.file());
    if (print_source) {
      Handle<Script> script = info->script();
      if (!script->IsUndefined() && !script->source()->IsUndefined()) {
        os << "--- Raw source ---\n";
        ConsStringIteratorOp op;
        StringCharacterStream stream(String::cast(script->source()),
                                     &op,
                                     function->start_position());
        // fun->end_position() points to the last character in the stream. We
        // need to compensate by adding one to calculate the length.
        int source_len =
            function->end_position() - function->start_position() + 1;
        for (int i = 0; i < source_len; i++) {
          if (stream.HasMore()) {
            os << AsReversiblyEscapedUC16(stream.GetNext());
          }
        }
        os << "\n\n";
      }
    }
    if (info->IsOptimizing()) {
      if (FLAG_print_unopt_code) {
        os << "--- Unoptimized code ---\n";
        info->closure()->shared()->code()->Disassemble(
            function->debug_name()->ToCString().get(), os);
      }
      os << "--- Optimized code ---\n"
         << "optimization_id = " << info->optimization_id() << "\n";
    } else {
      os << "--- Code ---\n";
    }
    if (print_source) {
      os << "source_position = " << function->start_position() << "\n";
    }
    if (info->IsStub()) {
      CodeStub::Major major_key = info->code_stub()->MajorKey();
      code->Disassemble(CodeStub::MajorName(major_key, false), os);
    } else {
      code->Disassemble(function->debug_name()->ToCString().get(), os);
    }
    os << "--- End code ---\n";
  }
#endif  // ENABLE_DISASSEMBLER
}

bool CodeGenerator::RecordPositions(MacroAssembler* masm,
                                    int pos,
                                    bool right_here) {
  if (pos != RelocInfo::kNoPosition) {
    masm->positions_recorder()->RecordStatementPosition(pos);
    masm->positions_recorder()->RecordPosition(pos);
    if (right_here) {
      return masm->positions_recorder()->WriteRecordedPositions();
    }
  }
  return false;
}

} }  // namespace v8::internal
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018, NVIDIA CORPORATION.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ---------------------------------------------------------------------------*
 * @brief Operations on GDF columns
 *
 * @file column.cpp
 * ---------------------------------------------------------------------------**/

#include <gdf/gdf.h>
#include <gdf/utils.h>
#include <gdf/errorutils.h>
#include <cuda_runtime_api.h>

// forward decl -- see validops.cu
gdf_error gdf_mask_concat(gdf_valid_type *output_mask,
                          gdf_size_type output_column_length,
                          gdf_valid_type *masks_to_concat[],
                          gdf_size_type *column_lengths,
                          gdf_size_type num_columns);

/** ---------------------------------------------------------------------------*
 * @brief Concatenates multiple gdf_columns into a single, contiguous column,
 * including the validity bitmasks.
 *
 * Note that input columns with nullptr validity masks are treated as if all
 * elements are valid.
 *
 * @param[out] output_column A column whose buffers are already allocated that
 *             will contain the concatenation of the input columns data and
 *             validity bitmasks
 * @Param[in] columns_to_concat[] The columns to concatenate
 * @Param[in] num_columns The number of columns to concatenate
 *
 * @return gdf_error GDF_SUCCESS upon completion; GDF_DATASET_EMPTY if any data
 *         pointer is NULL, GDF_COLUMN_SIZE_MISMATCH if the output column size
 *         != the total size of the input columns; GDF_DTYPE_MISMATCH if the
 *         input columns have different datatypes.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_concat(gdf_column *output_column, gdf_column *columns_to_concat[], int num_columns)
{

  if (nullptr == columns_to_concat){
    return GDF_DATASET_EMPTY;
  }

  if ((nullptr == columns_to_concat[0])
      || (nullptr == output_column)){
    return GDF_DATASET_EMPTY;
  }

  const gdf_dtype column_type = columns_to_concat[0]->dtype;

  if (column_type != output_column->dtype){
    return GDF_DTYPE_MISMATCH;
  }

  gdf_size_type total_size = 0;
  bool at_least_one_mask_present = false;

  // Ensure all the columns are properly allocated
  // and have matching types
  for (int i = 0; i < num_columns; ++i) {
    gdf_column* current_column = columns_to_concat[i];
    if (nullptr == current_column) {
      return GDF_DATASET_EMPTY;
    }
    if ((current_column->size > 0) && (nullptr == current_column->data))
    {
      return GDF_DATASET_EMPTY;
    }
    if (column_type != current_column->dtype) {
      return GDF_DTYPE_MISMATCH;
    }

    total_size += current_column->size;
    at_least_one_mask_present |= (columns_to_concat[i]->valid != 0);
  }

  // sum of the sizes of the input columns must equal output column size
  if (output_column->size != total_size) {
    return GDF_COLUMN_SIZE_MISMATCH;
  }

  int8_t* target = (int8_t*)(output_column->data);
  output_column->null_count = 0;

  // copy data
  for (int i = 0; i < num_columns; ++i) {
    gdf_size_type bytes = sizeof(column_type) * columns_to_concat[i]->size;
    cudaMemcpy(target, columns_to_concat[i]->data, bytes, cudaMemcpyDeviceToDevice);
    target += bytes;

    output_column->null_count += columns_to_concat[i]->null_count;
  }

  if (at_least_one_mask_present) {
    gdf_valid_type** masks;
    gdf_size_type* column_lengths;
    cudaMallocManaged((void**)&masks, sizeof(gdf_valid_type*)*num_columns);
    cudaMallocManaged((void**)&column_lengths, sizeof(gdf_size_type)*num_columns);

    for (int i = 0; i < num_columns; ++i) {
      masks[i] = columns_to_concat[i]->valid;
      column_lengths[i] = columns_to_concat[i]->size;
    }

    gdf_mask_concat(output_column->valid, output_column->size, masks, column_lengths, num_columns);

    cudaFree(masks);
    cudaFree(column_lengths);
  }
  else {
    // no masks, so just fill output valid mask with all 1 bits
    // TODO: async
    cudaMemset(output_column->valid, 0xff, gdf_get_num_chars_bitmask(total_size) * sizeof(gdf_valid_type));
  }

  return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Return the size of the gdf_column data type.
 *
 * @return gdf_size_type Size of the gdf_column data type.
 *b  ---------------------------------------------------------------------------**/
gdf_size_type gdf_column_sizeof() {
	return sizeof(gdf_column);
}

/** ---------------------------------------------------------------------------*
 * @brief Create a GDF column given data and validity bitmask pointers, size, and
 *        datatype
 *
 * @param[out] column The output column.
 * @param[in] data Pointer to data.
 * @param[in] valid Pointer to validity bitmask for the data.
 * @param[in] size Number of rows in the column.
 * @param[in] dtype Data type of the column.
 * @return gdf_error Returns GDF_SUCCESS upon successful creation.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_view(gdf_column *column,
                          void *data,
                          gdf_valid_type *valid,
		                      gdf_size_type size,
                          gdf_dtype dtype)
{
	column->data = data;
	column->valid = valid;
	column->size = size;
	column->dtype = dtype;
	column->null_count = 0;
	return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Create a GDF column given data and validity bitmask pointers, size, and
 *        datatype, and count of null (non-valid) elements
 *
 * @param[out] column The output column.
 * @param[in] data Pointer to data.
 * @param[in] valid Pointer to validity bitmask for the data.
 * @param[in] size Number of rows in the column.
 * @param[in] dtype Data type of the column.
 * @param[in] null_count The number of non-valid elements in the validity bitmask
 * @return gdf_error Returns GDF_SUCCESS upon successful creation.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_view_augmented(gdf_column *column,
                                    void *data,
                                    gdf_valid_type *valid,
		                                gdf_size_type size,
                                    gdf_dtype dtype,
                                    gdf_size_type null_count)
{
	column->data = data;
	column->valid = valid;
	column->size = size;
	column->dtype = dtype;
	column->null_count = null_count;
	return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Free the CUDA device memory of a gdf_column
 *
 * @param[inout] column Data and validity bitmask pointers of this column will be freed
 * @return gdf_error GDF_SUCCESS or GDF_ERROR if there is an error freeing the data
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_free(gdf_column *column)
{
  CUDA_TRY( cudaFree(column->data)  );
  CUDA_TRY( cudaFree(column->valid) );
  return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Get the byte width of a column
 *
 * @param[in] col The input column
 * @param[out] width The data type size of col
 * @return gdf_error GDF_SUCCESS, or GDF_UNSUPPORTED_DTYPE if col has an invalid
 *         datatype
 * ---------------------------------------------------------------------------**/
gdf_error get_column_byte_width(gdf_column * col,
                                int * width)
{
	switch(col->dtype) {

	case GDF_INT8 :
		*width = 1;
		break;
	case GDF_INT16 :
		*width = 2;
		break;
	case GDF_INT32 :
		*width = 4;
		break;
	case GDF_INT64 :
		*width = 8;
		break;
	case GDF_FLOAT32 :
		*width = 4;
		break;
	case GDF_FLOAT64 :
		*width = 8;
		break;
	case GDF_DATE32 :
		*width = 4;
		break;
	case GDF_DATE64 :
		*width = 8;
		break;
	case GDF_TIMESTAMP :
		*width = 8;
		break;
	default :
		*width = -1;
		return GDF_UNSUPPORTED_DTYPE;
	}

	return GDF_SUCCESS;
}
<commit_msg>Added notes on potential optimizations<commit_after>/*
 * Copyright (c) 2018, NVIDIA CORPORATION.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/** ---------------------------------------------------------------------------*
 * @brief Operations on GDF columns
 *
 * @file column.cpp
 * ---------------------------------------------------------------------------**/

#include <gdf/gdf.h>
#include <gdf/utils.h>
#include <gdf/errorutils.h>
#include <cuda_runtime_api.h>

// forward decl -- see validops.cu
gdf_error gdf_mask_concat(gdf_valid_type *output_mask,
                          gdf_size_type output_column_length,
                          gdf_valid_type *masks_to_concat[],
                          gdf_size_type *column_lengths,
                          gdf_size_type num_columns);

/** ---------------------------------------------------------------------------*
 * @brief Concatenates multiple gdf_columns into a single, contiguous column,
 * including the validity bitmasks.
 *
 * Note that input columns with nullptr validity masks are treated as if all
 * elements are valid.
 *
 * @param[out] output_column A column whose buffers are already allocated that
 *             will contain the concatenation of the input columns data and
 *             validity bitmasks
 * @Param[in] columns_to_concat[] The columns to concatenate
 * @Param[in] num_columns The number of columns to concatenate
 *
 * @return gdf_error GDF_SUCCESS upon completion; GDF_DATASET_EMPTY if any data
 *         pointer is NULL, GDF_COLUMN_SIZE_MISMATCH if the output column size
 *         != the total size of the input columns; GDF_DTYPE_MISMATCH if the
 *         input columns have different datatypes.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_concat(gdf_column *output_column, gdf_column *columns_to_concat[], int num_columns)
{

  if (nullptr == columns_to_concat){
    return GDF_DATASET_EMPTY;
  }

  if ((nullptr == columns_to_concat[0])
      || (nullptr == output_column)){
    return GDF_DATASET_EMPTY;
  }

  const gdf_dtype column_type = columns_to_concat[0]->dtype;

  if (column_type != output_column->dtype){
    return GDF_DTYPE_MISMATCH;
  }

  gdf_size_type total_size = 0;
  bool at_least_one_mask_present = false;

  // Ensure all the columns are properly allocated
  // and have matching types
  for (int i = 0; i < num_columns; ++i) {
    gdf_column* current_column = columns_to_concat[i];
    if (nullptr == current_column) {
      return GDF_DATASET_EMPTY;
    }
    if ((current_column->size > 0) && (nullptr == current_column->data))
    {
      return GDF_DATASET_EMPTY;
    }
    if (column_type != current_column->dtype) {
      return GDF_DTYPE_MISMATCH;
    }

    total_size += current_column->size;
    at_least_one_mask_present |= (columns_to_concat[i]->valid != 0);
  }

  // sum of the sizes of the input columns must equal output column size
  if (output_column->size != total_size) {
    return GDF_COLUMN_SIZE_MISMATCH;
  }

  int8_t* target = (int8_t*)(output_column->data);
  output_column->null_count = 0;

  // TODO optimizations if needed
  // 1. Either
  //    a) use cudaMemcpyAsync to copy the data and overlap copies with gdf_mask_concat
  //       (this will require getting rid of the allocations below because they will
  //       implicitly sync the device), or
  //    b) use a kernel to copy the data from all columns in one go. This will likely not
  //       overlap with the gdf_mask_concat
  // 2. Detect a zero total null count and skip gdf_mask_concat -- use cudaMemsetAsync

  // copy data
  for (int i = 0; i < num_columns; ++i) {
    gdf_size_type bytes = sizeof(column_type) * columns_to_concat[i]->size;
    cudaMemcpy(target, columns_to_concat[i]->data, bytes, cudaMemcpyDeviceToDevice);
    target += bytes;

    output_column->null_count += columns_to_concat[i]->null_count;
  }

  if (at_least_one_mask_present) {
    gdf_valid_type** masks;
    gdf_size_type* column_lengths;
    cudaMallocManaged((void**)&masks, sizeof(gdf_valid_type*)*num_columns);
    cudaMallocManaged((void**)&column_lengths, sizeof(gdf_size_type)*num_columns);

    for (int i = 0; i < num_columns; ++i) {
      masks[i] = columns_to_concat[i]->valid;
      column_lengths[i] = columns_to_concat[i]->size;
    }

    gdf_mask_concat(output_column->valid, output_column->size, masks, column_lengths, num_columns);

    cudaFree(masks);
    cudaFree(column_lengths);
  }
  else {
    // no masks, so just fill output valid mask with all 1 bits
    // TODO: async
    cudaMemset(output_column->valid, 0xff, gdf_get_num_chars_bitmask(total_size) * sizeof(gdf_valid_type));
  }

  return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Return the size of the gdf_column data type.
 *
 * @return gdf_size_type Size of the gdf_column data type.
 *b  ---------------------------------------------------------------------------**/
gdf_size_type gdf_column_sizeof() {
	return sizeof(gdf_column);
}

/** ---------------------------------------------------------------------------*
 * @brief Create a GDF column given data and validity bitmask pointers, size, and
 *        datatype
 *
 * @param[out] column The output column.
 * @param[in] data Pointer to data.
 * @param[in] valid Pointer to validity bitmask for the data.
 * @param[in] size Number of rows in the column.
 * @param[in] dtype Data type of the column.
 * @return gdf_error Returns GDF_SUCCESS upon successful creation.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_view(gdf_column *column,
                          void *data,
                          gdf_valid_type *valid,
		                      gdf_size_type size,
                          gdf_dtype dtype)
{
	column->data = data;
	column->valid = valid;
	column->size = size;
	column->dtype = dtype;
	column->null_count = 0;
	return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Create a GDF column given data and validity bitmask pointers, size, and
 *        datatype, and count of null (non-valid) elements
 *
 * @param[out] column The output column.
 * @param[in] data Pointer to data.
 * @param[in] valid Pointer to validity bitmask for the data.
 * @param[in] size Number of rows in the column.
 * @param[in] dtype Data type of the column.
 * @param[in] null_count The number of non-valid elements in the validity bitmask
 * @return gdf_error Returns GDF_SUCCESS upon successful creation.
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_view_augmented(gdf_column *column,
                                    void *data,
                                    gdf_valid_type *valid,
		                                gdf_size_type size,
                                    gdf_dtype dtype,
                                    gdf_size_type null_count)
{
	column->data = data;
	column->valid = valid;
	column->size = size;
	column->dtype = dtype;
	column->null_count = null_count;
	return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Free the CUDA device memory of a gdf_column
 *
 * @param[inout] column Data and validity bitmask pointers of this column will be freed
 * @return gdf_error GDF_SUCCESS or GDF_ERROR if there is an error freeing the data
 * ---------------------------------------------------------------------------**/
gdf_error gdf_column_free(gdf_column *column)
{
  CUDA_TRY( cudaFree(column->data)  );
  CUDA_TRY( cudaFree(column->valid) );
  return GDF_SUCCESS;
}

/** ---------------------------------------------------------------------------*
 * @brief Get the byte width of a column
 *
 * @param[in] col The input column
 * @param[out] width The data type size of col
 * @return gdf_error GDF_SUCCESS, or GDF_UNSUPPORTED_DTYPE if col has an invalid
 *         datatype
 * ---------------------------------------------------------------------------**/
gdf_error get_column_byte_width(gdf_column * col,
                                int * width)
{
	switch(col->dtype) {

	case GDF_INT8 :
		*width = 1;
		break;
	case GDF_INT16 :
		*width = 2;
		break;
	case GDF_INT32 :
		*width = 4;
		break;
	case GDF_INT64 :
		*width = 8;
		break;
	case GDF_FLOAT32 :
		*width = 4;
		break;
	case GDF_FLOAT64 :
		*width = 8;
		break;
	case GDF_DATE32 :
		*width = 4;
		break;
	case GDF_DATE64 :
		*width = 8;
		break;
	case GDF_TIMESTAMP :
		*width = 8;
		break;
	default :
		*width = -1;
		return GDF_UNSUPPORTED_DTYPE;
	}

	return GDF_SUCCESS;
}
<|endoftext|>


<commit_before>#include "common.h"
#include "Ruby.h"
#include "RubyObject.h"
#include "RubyModule.h"
#include <node.h>
#include <limits>
#include <iostream>

using namespace v8;

const int32_t MIN_INT32 = std::numeric_limits<int32_t>::min();
const int32_t MAX_INT32 = std::numeric_limits<int32_t>::max();

Handle<Value> rubyToV8(VALUE val)
{
  NanEscapableScope();

  log("Converting " << RSTRING_PTR(rb_funcall2(val, rb_intern("to_s"), 0, NULL)) << " to v8");

  int type = TYPE(val);
  switch (type) {
  case T_NONE:
  case T_NIL:
     return NanEscapeScope(NanUndefined());
  case T_FLOAT:
     return NanEscapeScope(NanNew<Number>(RFLOAT_VALUE(val)));
  case T_STRING:
     return NanEscapeScope(NanNew<String>(RSTRING_PTR(val), RSTRING_LEN(val)));
  case T_ARRAY: {
    int len = RARRAY_LEN(val);
    Local<Array> array = NanNew<Array>(len);
    for (int i = 0; i < len; i++) {
      array->Set(i, rubyToV8(rb_ary_entry(val, i)));
    }

    return NanEscapeScope(array);
  }
  case T_FIXNUM: {
    long longVal = FIX2LONG(val);
    if (longVal >= MIN_INT32 && longVal <= MAX_INT32) {
      return NanEscapeScope(NanNew<Integer>(longVal));
    }
    else
      return NanEscapeScope(NanNew<Number>(longVal));
  }
  case T_BIGNUM: {
    double dblVal = rb_big2dbl(val);
    // if (dblVal == HUGE_VAL || dblVal == -HUGE_VAL) {
    //   VALUE valStr = rb_big2str(val, 10);
    //   return NanEscapeScope(rubyToV8(valStr));
    // }
    // else
      return NanEscapeScope(NanNew<Number>(dblVal));
  }
  case T_TRUE:
    return NanEscapeScope(NanTrue());
  case T_FALSE:
    return NanEscapeScope(NanFalse());
  case T_OBJECT:
  case T_DATA: {
    Local<Object> owner = RubyObject::RubyUnwrap(val);
    if (owner.IsEmpty()) {
      owner = NanNew<Object>();
      Local<Object> ctor = RubyModule::ToV8(CLASS_OF(val));
      owner->SetPrototype(ctor->Get(NanNew<String>("prototype")));
      owner->Set(NanNew<String>("_rubyObj"), RubyObject::ToV8(val, owner));
    }

    return NanEscapeScope(owner);
  }
  case T_SYMBOL: {
    VALUE str = rb_id2str(SYM2ID(val));
    return NanEscapeScope(NanNew<String>(RSTRING_PTR(str), RSTRING_LEN(str)));
  }
  case T_MODULE:
  case T_CLASS:
    return NanEscapeScope(RubyModule::ToV8(val));
  default:
    std::cerr << "Unknown ruby type(" << type << "): " <<
                 rb_obj_classname(val) << std::endl;
    return NanEscapeScope(NanUndefined());
  }
}

VALUE v8ToRuby(Handle<Value> val)
{
  NanScope();

  log("Converting " << *String::Utf8Value(val) << " to ruby");

  if (val->IsUndefined())
    return Qnil;
  else if (val->IsNull())
    return Qnil;
  else if (val->IsTrue())
    return Qtrue;
  else if (val->IsFalse())
    return Qfalse;
  else if (val->IsString()) {
    // TODO: We should handle encoding here
    Handle<String> str = val.As<String>();
    VALUE rbStr = rb_str_new(NULL, str->Utf8Length());
    str->WriteUtf8(RSTRING_PTR(rbStr));
    return rbStr;
  }
  else if (val->IsArray()) {
    Handle<Array> v8Arr = val.As<Array>();
    VALUE rbArr = rb_ary_new2(v8Arr->Length());
    for (uint32_t i = 0; i < v8Arr->Length(); i++) {
      rb_ary_store(rbArr, i, v8ToRuby(v8Arr->Get(i)));
    }

    return rbArr;
  }
  else if (val->IsInt32())
    return INT2NUM(val->Int32Value());
  else if (val->IsUint32())
    return UINT2NUM(val->Uint32Value());
  else if (val->IsNumber())
    return rb_float_new(val->NumberValue());
  else if (val->IsFunction()) {
    Local<Object> rubyClass =
      val.As<Function>()->Get(NanNew<String>("_rubyClass")).As<Object>();
    if (!rubyClass.IsEmpty() && rubyClass->IsObject() &&
        rubyClass->InternalFieldCount() == 1) {
      return VALUE(NanGetInternalFieldPointer(rubyClass, 0));
    }
  }
  else if (val->IsObject()) {
    VALUE rbObj = RubyObject::FromV8(val.As<Object>());
    if (rbObj != Qnil)
      return rbObj;

    // TODO: Should we wrap objects here?
  }

  String::Utf8Value str(val->ToDetailString());
  std::cerr << "Unknown v8 type: " << *str << std::endl;
  return Qnil;
}

Handle<Value> rubyExToV8(VALUE ex)
{
  NanEscapableScope();

  assert(rb_obj_is_kind_of(ex, rb_eException) == Qtrue);

  VALUE msg = rb_funcall(ex, rb_intern("message"), 0);
  Local<String> msgStr = NanNew<String>(RSTRING_PTR(msg), RSTRING_LEN(msg));
  Local<Value> v8Err;

  VALUE klass = rb_class_of(ex);
  if (klass == rb_eArgError ||
      klass == rb_eLoadError)
    v8Err = Exception::Error(msgStr);
  else if (klass == rb_eNameError ||
           klass == rb_eNoMethodError)
    v8Err = Exception::ReferenceError(msgStr);
  else if (klass == rb_eTypeError)
    v8Err = Exception::TypeError(msgStr);
  else if (klass == rb_eSyntaxError)
    v8Err = Exception::SyntaxError(msgStr);
  else {
    std::cerr << "Unknown ruby exception: " <<
                 rb_obj_classname(ex) << std::endl;
    v8Err = Exception::Error(msgStr);
  }

  VALUE backtrace = rb_funcall(ex, rb_intern("backtrace"), 0);
  Local<Object> errObj = v8Err.As<Object>();
  errObj->Set(NanNew<String>("rubyStack"), rubyToV8(backtrace));

  return NanEscapeScope(v8Err);
}

VALUE RescueCB(VALUE data, VALUE ex)
{
  VALUE *storedEx = reinterpret_cast<VALUE*>(data);
  *storedEx = ex;

  return Qnil;
}

VALUE CallV8FromRuby(const Handle<Object> recv,
                     const Handle<Function> callback,
                     int argc, const VALUE* argv)
{
  NanScope();

  std::vector<Handle<Value> > v8Args(argc);
  for (int i = 0; i < argc; i++) {
    v8Args[i] = rubyToV8(argv[i]);
  }

  Handle<Value> ret = NanMakeCallback(recv, callback, argc, &v8Args[0]);

  return v8ToRuby(ret);
}

struct MethodCaller::Block
{
  Block(Handle<Function> f)
  {
    NanAssignPersistent(func, f);
    dataObj = Data_Wrap_Struct(Ruby::BLOCK_WRAPPER_CLASS, NULL, Free, this);
  }

  static VALUE Func(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    Block* block;
    Data_Get_Struct(data, Block, block);

    Local<Function> fn = NanNew<Function>(block->func);
    // TODO: Should we store args.This() and call it as the receiver?
    return CallV8FromRuby(NanGetCurrentContext()->Global(), fn,
                          argc, rbArgv);
  }

  static void Free(void* data)
  {
    Block* block = static_cast<Block*>(data);
    NanDisposePersistent(block->func);
    delete block;
  }

  Persistent<Function> func;
  VALUE dataObj;
};

MethodCaller::MethodCaller(VALUE o, _NAN_METHOD_ARGS_TYPE args, int start):
  obj(o), methodID(ID(EXTERNAL_UNWRAP(args.Data()))),
  rubyArgs(args.Length()-start), block(NULL)
{
  // TODO: Is this right? Is there a way to determine if a block is expected?
  if (args.Length()-start > 0 && args[args.Length()-1]->IsFunction()) {
    Local<Function> func = args[args.Length()-1].As<Function>();
    if (!func->Has(NanNew<String>("_rubyClass"))) {
      block = new Block(func);
      rubyArgs.resize(rubyArgs.size()-1);
    }
  }

  for (size_t i = 0; i < rubyArgs.size(); i++) {
    rubyArgs[i] = v8ToRuby(args[i+start]);
  }
}

VALUE MethodCaller::operator()() const
{
  if (block == NULL) {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
  }
  else {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() <<
        " args and a block");

    // TODO: Probably not available in Ruby < 1.9
    return rb_block_call(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0],
                        RUBY_METHOD_FUNC(Block::Func), block->dataObj);
  }
}

Handle<Value> CallRubyFromV8(VALUE recv, _NAN_METHOD_ARGS_TYPE args)
{
  NanEscapableScope();

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(recv, args), ex);
  if (ex != Qnil) {
    NanThrowError(rubyExToV8(ex));
    return NanEscapeScope(NanUndefined());
  }

  return NanEscapeScope(rubyToV8(res));
}

void DumpRubyArgs(int argc, VALUE* argv)
{
#ifdef _DEBUG
  for (int i = 0; i < argc; i++) {
    VALUE str = rb_funcall2(argv[i], rb_intern("to_s"), 0, NULL);
    std::cout << i << ": " << StringValueCStr(str) << std::endl;
  }
#endif
}

void DumpV8Props(Handle<Object> obj)
{
#ifdef _DEBUG
  NanScope();

  Local<Array> propNames = obj->GetPropertyNames();
  for (uint32_t i = 0; i < propNames->Length(); i++) {
    Local<Value> key = propNames->Get(i);

    std::cout << *String::Utf8Value(key) << std::endl;
  }
#endif
}

void DumpV8Args(_NAN_METHOD_ARGS_TYPE args)
{
#ifdef _DEBUG
  NanScope();

  for (int i = 0; i < args.Length(); i++) {
    std::cout << i << ": " << *String::Utf8Value(args[i]) << std::endl;
  }
#endif
}
<commit_msg>Fixed conversion of really big Bignums<commit_after>#include "common.h"
#include "Ruby.h"
#include "RubyObject.h"
#include "RubyModule.h"
#include <node.h>
#include <limits>
#include <iostream>
#include <math.h>

using namespace v8;

const int32_t MIN_INT32 = std::numeric_limits<int32_t>::min();
const int32_t MAX_INT32 = std::numeric_limits<int32_t>::max();

Handle<Value> rubyToV8(VALUE val)
{
  NanEscapableScope();

  log("Converting " << RSTRING_PTR(rb_funcall2(val, rb_intern("to_s"), 0, NULL)) << " to v8");

  int type = TYPE(val);
  switch (type) {
  case T_NONE:
  case T_NIL:
     return NanEscapeScope(NanUndefined());
  case T_FLOAT:
     return NanEscapeScope(NanNew<Number>(RFLOAT_VALUE(val)));
  case T_STRING:
     return NanEscapeScope(NanNew<String>(RSTRING_PTR(val), RSTRING_LEN(val)));
  case T_ARRAY: {
    int len = RARRAY_LEN(val);
    Local<Array> array = NanNew<Array>(len);
    for (int i = 0; i < len; i++) {
      array->Set(i, rubyToV8(rb_ary_entry(val, i)));
    }

    return NanEscapeScope(array);
  }
  case T_FIXNUM: {
    long longVal = FIX2LONG(val);
    if (longVal >= MIN_INT32 && longVal <= MAX_INT32) {
      return NanEscapeScope(NanNew<Integer>(longVal));
    }
    else
      return NanEscapeScope(NanNew<Number>(longVal));
  }
  case T_BIGNUM: {
    double dblVal = rb_big2dbl(val);
    if (dblVal == HUGE_VAL || dblVal == -HUGE_VAL) {
      VALUE valStr = rb_big2str(val, 10);
      return NanEscapeScope(rubyToV8(valStr));
    }
    else
      return NanEscapeScope(NanNew<Number>(dblVal));
  }
  case T_TRUE:
    return NanEscapeScope(NanTrue());
  case T_FALSE:
    return NanEscapeScope(NanFalse());
  case T_OBJECT:
  case T_DATA: {
    Local<Object> owner = RubyObject::RubyUnwrap(val);
    if (owner.IsEmpty()) {
      owner = NanNew<Object>();
      Local<Object> ctor = RubyModule::ToV8(CLASS_OF(val));
      owner->SetPrototype(ctor->Get(NanNew<String>("prototype")));
      owner->Set(NanNew<String>("_rubyObj"), RubyObject::ToV8(val, owner));
    }

    return NanEscapeScope(owner);
  }
  case T_SYMBOL: {
    VALUE str = rb_id2str(SYM2ID(val));
    return NanEscapeScope(NanNew<String>(RSTRING_PTR(str), RSTRING_LEN(str)));
  }
  case T_MODULE:
  case T_CLASS:
    return NanEscapeScope(RubyModule::ToV8(val));
  default:
    std::cerr << "Unknown ruby type(" << type << "): " <<
                 rb_obj_classname(val) << std::endl;
    return NanEscapeScope(NanUndefined());
  }
}

VALUE v8ToRuby(Handle<Value> val)
{
  NanScope();

  log("Converting " << *String::Utf8Value(val) << " to ruby");

  if (val->IsUndefined())
    return Qnil;
  else if (val->IsNull())
    return Qnil;
  else if (val->IsTrue())
    return Qtrue;
  else if (val->IsFalse())
    return Qfalse;
  else if (val->IsString()) {
    // TODO: We should handle encoding here
    Handle<String> str = val.As<String>();
    VALUE rbStr = rb_str_new(NULL, str->Utf8Length());
    str->WriteUtf8(RSTRING_PTR(rbStr));
    return rbStr;
  }
  else if (val->IsArray()) {
    Handle<Array> v8Arr = val.As<Array>();
    VALUE rbArr = rb_ary_new2(v8Arr->Length());
    for (uint32_t i = 0; i < v8Arr->Length(); i++) {
      rb_ary_store(rbArr, i, v8ToRuby(v8Arr->Get(i)));
    }

    return rbArr;
  }
  else if (val->IsInt32())
    return INT2NUM(val->Int32Value());
  else if (val->IsUint32())
    return UINT2NUM(val->Uint32Value());
  else if (val->IsNumber())
    return rb_float_new(val->NumberValue());
  else if (val->IsFunction()) {
    Local<Object> rubyClass =
      val.As<Function>()->Get(NanNew<String>("_rubyClass")).As<Object>();
    if (!rubyClass.IsEmpty() && rubyClass->IsObject() &&
        rubyClass->InternalFieldCount() == 1) {
      return VALUE(NanGetInternalFieldPointer(rubyClass, 0));
    }
  }
  else if (val->IsObject()) {
    VALUE rbObj = RubyObject::FromV8(val.As<Object>());
    if (rbObj != Qnil)
      return rbObj;

    // TODO: Should we wrap objects here?
  }

  String::Utf8Value str(val->ToDetailString());
  std::cerr << "Unknown v8 type: " << *str << std::endl;
  return Qnil;
}

Handle<Value> rubyExToV8(VALUE ex)
{
  NanEscapableScope();

  assert(rb_obj_is_kind_of(ex, rb_eException) == Qtrue);

  VALUE msg = rb_funcall(ex, rb_intern("message"), 0);
  Local<String> msgStr = NanNew<String>(RSTRING_PTR(msg), RSTRING_LEN(msg));
  Local<Value> v8Err;

  VALUE klass = rb_class_of(ex);
  if (klass == rb_eArgError ||
      klass == rb_eLoadError)
    v8Err = Exception::Error(msgStr);
  else if (klass == rb_eNameError ||
           klass == rb_eNoMethodError)
    v8Err = Exception::ReferenceError(msgStr);
  else if (klass == rb_eTypeError)
    v8Err = Exception::TypeError(msgStr);
  else if (klass == rb_eSyntaxError)
    v8Err = Exception::SyntaxError(msgStr);
  else {
    std::cerr << "Unknown ruby exception: " <<
                 rb_obj_classname(ex) << std::endl;
    v8Err = Exception::Error(msgStr);
  }

  VALUE backtrace = rb_funcall(ex, rb_intern("backtrace"), 0);
  Local<Object> errObj = v8Err.As<Object>();
  errObj->Set(NanNew<String>("rubyStack"), rubyToV8(backtrace));

  return NanEscapeScope(v8Err);
}

VALUE RescueCB(VALUE data, VALUE ex)
{
  VALUE *storedEx = reinterpret_cast<VALUE*>(data);
  *storedEx = ex;

  return Qnil;
}

VALUE CallV8FromRuby(const Handle<Object> recv,
                     const Handle<Function> callback,
                     int argc, const VALUE* argv)
{
  NanScope();

  std::vector<Handle<Value> > v8Args(argc);
  for (int i = 0; i < argc; i++) {
    v8Args[i] = rubyToV8(argv[i]);
  }

  Handle<Value> ret = NanMakeCallback(recv, callback, argc, &v8Args[0]);

  return v8ToRuby(ret);
}

struct MethodCaller::Block
{
  Block(Handle<Function> f)
  {
    NanAssignPersistent(func, f);
    dataObj = Data_Wrap_Struct(Ruby::BLOCK_WRAPPER_CLASS, NULL, Free, this);
  }

  static VALUE Func(VALUE, VALUE data, int argc, const VALUE* rbArgv)
  {
    Block* block;
    Data_Get_Struct(data, Block, block);

    Local<Function> fn = NanNew<Function>(block->func);
    // TODO: Should we store args.This() and call it as the receiver?
    return CallV8FromRuby(NanGetCurrentContext()->Global(), fn,
                          argc, rbArgv);
  }

  static void Free(void* data)
  {
    Block* block = static_cast<Block*>(data);
    NanDisposePersistent(block->func);
    delete block;
  }

  Persistent<Function> func;
  VALUE dataObj;
};

MethodCaller::MethodCaller(VALUE o, _NAN_METHOD_ARGS_TYPE args, int start):
  obj(o), methodID(ID(EXTERNAL_UNWRAP(args.Data()))),
  rubyArgs(args.Length()-start), block(NULL)
{
  // TODO: Is this right? Is there a way to determine if a block is expected?
  if (args.Length()-start > 0 && args[args.Length()-1]->IsFunction()) {
    Local<Function> func = args[args.Length()-1].As<Function>();
    if (!func->Has(NanNew<String>("_rubyClass"))) {
      block = new Block(func);
      rubyArgs.resize(rubyArgs.size()-1);
    }
  }

  for (size_t i = 0; i < rubyArgs.size(); i++) {
    rubyArgs[i] = v8ToRuby(args[i+start]);
  }
}

VALUE MethodCaller::operator()() const
{
  if (block == NULL) {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() << " args");

    return rb_funcall2(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0]);
  }
  else {
    log("Calling method: " << rb_obj_classname(obj) << "." <<
        rb_id2name(methodID) << " with " << rubyArgs.size() <<
        " args and a block");

    // TODO: Probably not available in Ruby < 1.9
    return rb_block_call(obj, methodID, rubyArgs.size(), (VALUE*)&rubyArgs[0],
                        RUBY_METHOD_FUNC(Block::Func), block->dataObj);
  }
}

Handle<Value> CallRubyFromV8(VALUE recv, _NAN_METHOD_ARGS_TYPE args)
{
  NanEscapableScope();

  VALUE ex;
  VALUE res = SafeRubyCall(MethodCaller(recv, args), ex);
  if (ex != Qnil) {
    NanThrowError(rubyExToV8(ex));
    return NanEscapeScope(NanUndefined());
  }

  return NanEscapeScope(rubyToV8(res));
}

void DumpRubyArgs(int argc, VALUE* argv)
{
#ifdef _DEBUG
  for (int i = 0; i < argc; i++) {
    VALUE str = rb_funcall2(argv[i], rb_intern("to_s"), 0, NULL);
    std::cout << i << ": " << StringValueCStr(str) << std::endl;
  }
#endif
}

void DumpV8Props(Handle<Object> obj)
{
#ifdef _DEBUG
  NanScope();

  Local<Array> propNames = obj->GetPropertyNames();
  for (uint32_t i = 0; i < propNames->Length(); i++) {
    Local<Value> key = propNames->Get(i);

    std::cout << *String::Utf8Value(key) << std::endl;
  }
#endif
}

void DumpV8Args(_NAN_METHOD_ARGS_TYPE args)
{
#ifdef _DEBUG
  NanScope();

  for (int i = 0; i < args.Length(); i++) {
    std::cout << i << ": " << *String::Utf8Value(args[i]) << std::endl;
  }
#endif
}
<|endoftext|>