<commit_before>// This pass performs some transformations to enable parallel code
// generation.

#include "astutil.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "stringutil.h"
#include "driver.h"
#include "files.h"

// Move begin blocks into their own functions so that it can be later
// interfaced with the expected thread interface.
static void
begin_encapsulation() {
  int  ufid = 1;

  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if (BLOCK_BEGIN == b->blockTag) {
          // replace with a new block w/ each stmt -> function call
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;

          char *fname = stringcat( "_begin_block", intstring( ufid++));
          FnSymbol *fn = new FnSymbol( fname);
          fn->retType = dtVoid;
          for_alist(Expr, stmt, b->body) {
            stmt->remove();
            fn->insertAtTail( stmt);        // move stmts to new begin function
          }
          b->insertAtTail( new DefExpr( fn));
          b->insertAtTail( new CallExpr( fname));
        }
      }
    }
  }
}

// This pass moves each cobegin statement into nested functions. Currently,
// each statement is moved to within it's own function and the
// appropriate function def and call expressions are added.
static void
cobegin_encapsulation() {
  int  ufid = 1;

  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if (BLOCK_COBEGIN == b->blockTag) {
          // replace with a new block w/ each stmt -> function call
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;
          for_alist(Expr, stmt, b->body) {
            char *fname = stringcat( "_cobegin_stmt", intstring( ufid++));
            FnSymbol *fn = new FnSymbol( fname);
            fn->retType = dtVoid;
            stmt->remove();
            fn->insertAtTail( stmt);            // move stmt to new function
            newb->insertAtHead( new DefExpr (fn));
            newb->insertAtTail( new CallExpr (fname));
          }
          b->insertBefore (newb);
          b->remove ();
        }
      }
    }
  }
}

void
parallel1 (void) {
  addLibInfo ("-lpthread");
  if (parallelPass) {
    begin_encapsulation();     // move begin block to within a function
    cobegin_encapsulation();   // move cobegin stmts to within a function
  }
}

// Mark locals that should be heap allocated and insert a call to allocate
// them on the heap.  This is for begin blocks where the forked child thread
// and parent thread may have different lifetimes.  The locals cannot live
// on a thread's stack.
static void
begin_mark_locals() {
  Vec<SymExpr*> arglist;

  // Find all the args that should be heap allocated -> arglist
  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      BlockStmt *b = dynamic_cast<BlockStmt*>(ast);
      if (b && (BLOCK_BEGIN == b->blockTag)) {
        // note, should only be one call expr in the body of the begin
        for_alist( Expr, stmt, b->body) {
          if (CallExpr *fcall = dynamic_cast<CallExpr*>(stmt)) {
            // add the args that need to be heap allocated
            for_actuals(arg, fcall) {
              if (SymExpr *s = dynamic_cast<SymExpr*>(arg)) {
                arglist.add( s);
              }
            }
          }
        }
      }
    }
  }

  // do a buch of stuff:
  //  - mark locals as heap allocated
  //  - create associated mutex + reference counter
  //  - add mutex + ref-counter to nested function's arg list
  //  - add calls to init ref-counter, touch, and free
  forv_Vec( SymExpr, se, arglist) {
    VarSymbol *local;             // var that is referenced

    if (!(local = dynamic_cast<VarSymbol*>( se->var))) {
      INT_FATAL( se->var, "currently can only handle locals (not args)");
    }

    Expr      *localdef = local->defPoint;

    if (!local->on_heap) {        // no reference counter associated yet
      local->on_heap = true;
      // create reference counter
      char      *refcname = stringcat( "_", stringcat(local->name, "_refc"));
      VarSymbol *refc = new VarSymbol( refcname,
                                       dtInt[INT_SIZE_32],
                                       VAR_NORMAL,
                                       VAR_VAR);
      refc->on_heap = true;
      localdef->insertBefore( new DefExpr( refc));
      local->refc = refc;
      // create reference counter mutex
      char      *mname = stringcat( "_", stringcat(local->name, "_refcmutex"));
      VarSymbol *m = new VarSymbol( mname, dtMutex, VAR_NORMAL, VAR_VAR);
      m->on_heap = true;          // needs to be heap allocated
      localdef->insertBefore( new DefExpr( m));
      local->refcMutex = m;
    }

    // add refc and mutex args as both actuals and formals
    CallExpr  *ce;
    if (!(ce = dynamic_cast<CallExpr*>( se->parentExpr))) {
      INT_FATAL( se->parentExpr, "should be walking args of a call within begin");
    }

    ce->argList->insertAtTail( new SymExpr( local->refc));
    ce->argList->insertAtTail( new SymExpr( local->refcMutex));
    ArgSymbol *rc_arg = new ArgSymbol( INTENT_REF,
                                       local->refc->name,
                                       dtInt[INT_SIZE_32]);
    ArgSymbol *rcm_arg = new ArgSymbol( INTENT_REF,
                                        local->refcMutex->name,
                                        dtMutex);
    FnSymbol  *fn = dynamic_cast<FnSymbol*>( (dynamic_cast<SymExpr*>( ce->baseExpr))->var);
    fn->insertFormalAtTail(new DefExpr( rc_arg));
    fn->insertFormalAtTail(new DefExpr( rcm_arg));

    localdef->insertAfter( new CallExpr( PRIMITIVE_REFC_TOUCH,
                                         local,
                                         local->refc,
                                         local->refcMutex));
    localdef->insertAfter( new CallExpr( PRIMITIVE_REFC_INIT,
                                         local,
                                         local->refc,
                                         local->refcMutex));
    BlockStmt *mainfb = dynamic_cast<BlockStmt*>(localdef->parentExpr);
    Expr      *laststmt = mainfb->body->last();
    if (dynamic_cast<ReturnStmt*>(laststmt)) {
      laststmt->insertBefore( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                            local,
                                            local->refc,
                                            local->refcMutex));
    } else {
      laststmt->insertAfter( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                           local,
                                           local->refc,
                                           local->refcMutex));
    }

    // add touch + release for the begin block
    se->getStmtExpr()->parentExpr->insertBefore( new CallExpr( PRIMITIVE_REFC_TOUCH,
                                                               local,
                                                               local->refc,
                                                               local->refcMutex));
    ArgSymbol *fa = dynamic_cast<ArgSymbol*>( actual_to_formal( se));
    fn->body->body->last()->insertBefore( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                                        fa,
                                                        rc_arg,
                                                        rcm_arg));
  }

  // for each on_heap variable, add call to allocate it
  forv_Vec(ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    asts.clear();
    collect_asts_postorder(&asts, mod);
    forv_Vec(BaseAST, ast, asts) {
      if (VarSymbol *vs = dynamic_cast<VarSymbol*>(ast)) {
        if (vs->on_heap) {
          CallExpr *alloc = new CallExpr( PRIMITIVE_CHPL_ALLOC,
                                          vs->type->symbol,
                                          new_StringSymbol("heap alloc'd via begin"));
          vs->defPoint->insertAfter(new CallExpr(PRIMITIVE_SET_HEAPVAR,
                                                 vs->defPoint->sym,
                                                 alloc));
        }
      }
    }
  }
}

// Package args into a class and call a wrapper function with that
// object. The wrapper function will then call the function
// created by the previous parallel pass. This is a way to pass along
// multiple args through the limitation of one arg in the runtime's
// thread creation interface.
static void
thread_args() {
  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if ((BLOCK_BEGIN == b->blockTag) ||
            (BLOCK_COBEGIN == b->blockTag)) {
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;
          for_alist(Expr, expr, b->body) {
            if (CallExpr *fcall = dynamic_cast<CallExpr*>(expr)) {
              // create a new class to capture refs to locals
              char* fname = (dynamic_cast<SymExpr*>(fcall->baseExpr))->var->name;
              ClassType* ctype = new ClassType( CLASS_CLASS);
              TypeSymbol* new_c = new TypeSymbol( stringcat("_class_locals",
                                                            fname),
                                                  ctype);

              // disable reference counting, handle manually
              new_c->addPragma("no gc");

              // add the function args as fields in the class
              for_actuals(arg, fcall) {
                SymExpr *s = dynamic_cast<SymExpr*>(arg);
                Symbol  *var = s->var; // arg or var
                VarSymbol* field = new VarSymbol(var->name, var->type);
                field->is_ref = true;
                ctype->fields->insertAtTail(new DefExpr(field));
              }
              mod->stmts->insertAtHead(new DefExpr(new_c));

              // create the class variable instance and allocate it
              VarSymbol *tempc = new VarSymbol( stringcat( "_args_for",
                                                           fname),
                                                ctype);
              b->insertBefore( new DefExpr( tempc));
              CallExpr *tempc_alloc = new CallExpr( PRIMITIVE_CHPL_ALLOC,
                                                    ctype->symbol,
                                                    new_StringSymbol( stringcat( "instance of class ", ctype->symbol->name)));
              b->insertBefore( new CallExpr( PRIMITIVE_MOVE,
                                             tempc,
                                             tempc_alloc));

              // set the references in the class instance
              for_actuals(arg, fcall) {
                SymExpr *s = dynamic_cast<SymExpr*>(arg);
                Symbol  *var = s->var; // var or arg
                CallExpr *setc=new CallExpr(PRIMITIVE_SET_MEMBER_REF_TO,
                                            tempc,
                                            ctype->getField(var->name),
                                            var);
                b->insertBefore( setc);
              }

              // create wrapper-function that uses the class instance
              FnSymbol *wrap_fn = new FnSymbol( stringcat("wrap", fname));
              DefExpr  *fcall_def= (dynamic_cast<SymExpr*>( fcall->baseExpr))->var->defPoint;
              ArgSymbol *wrap_c = new ArgSymbol( INTENT_BLANK, "c", ctype);
              wrap_fn->insertFormalAtTail( wrap_c);
              mod->stmts->insertAtTail(new DefExpr(wrap_fn));
              newb->insertAtTail( new CallExpr( wrap_fn, tempc));
              wrap_fn->insertAtTail(new CallExpr(PRIMITIVE_CHPL_FREE, wrap_c));

              // translate the original cobegin function
              CallExpr *new_cofn = new CallExpr( (dynamic_cast<SymExpr*>(fcall->baseExpr))->var);
              for_fields(field, ctype) {  // insert args
                new_cofn->insertAtTail( new CallExpr(PRIMITIVE_GET_MEMBER_REF_TO,
                                                     wrap_c,
                                                     field));
              }

              // WAW: touch + free for the class arg wrapper
              /* WAW: this strategy doesn't work because the _touch/_free
                 functions are not defined.
              if (!no_gc && (BLOCK_BEGIN == b->blockTag)) {
                b->insertBefore( new CallExpr( new FnSymbol("_touch"), tempc));
                wrap_fn->insertAtTail( new CallExpr( new FnSymbol("_free"), wrap_c));
              }
              */

              wrap_fn->retType = dtVoid;
              fcall->remove();                     // rm orig. call
              wrap_fn->insertAtHead(new_cofn);    // add new call
              wrap_fn->insertAtHead(new CallExpr(PRIMITIVE_THREAD_INIT));
              fcall_def->remove();                 // move orig. def
              mod->stmts->insertAtTail(fcall_def); // to top-level
              normalize(wrap_fn);
            }
          }
          b->replace(newb);
        }
      }
    }
  }
}

void
parallel2 (void) {
  if (parallelPass) {
    begin_mark_locals();
    thread_args();
  }
}
<commit_msg>Minor comment changes and cleanup.<commit_after>// This pass performs some transformations to enable parallel code
// generation for begin and cobegin blocks.

#include "astutil.h"
#include "expr.h"
#include "passes.h"
#include "stmt.h"
#include "symbol.h"
#include "stringutil.h"
#include "driver.h"
#include "files.h"

// Move begin blocks into their own functions so that it can be later
// interfaced with the expected thread interface.
static void
begin_encapsulation() {
  int  ufid = 1;

  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if (BLOCK_BEGIN == b->blockTag) {
          // replace with a new block w/ each stmt -> function call
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;

          char *fname = stringcat( "_begin_block", intstring( ufid++));
          FnSymbol *fn = new FnSymbol( fname);
          fn->retType = dtVoid;
          for_alist(Expr, stmt, b->body) {
            stmt->remove();
            fn->insertAtTail( stmt);        // move stmts to new begin function
          }
          b->insertAtTail( new DefExpr( fn));
          b->insertAtTail( new CallExpr( fname));
        }
      }
    }
  }
}

// This pass moves each cobegin statement into nested functions. Currently,
// each statement is moved to within it's own function and the
// appropriate function def and call expressions are added.
static void
cobegin_encapsulation() {
  int  ufid = 1;

  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if (BLOCK_COBEGIN == b->blockTag) {
          // replace with a new block w/ each stmt -> function call
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;
          for_alist(Expr, stmt, b->body) {
            char *fname = stringcat( "_cobegin_stmt", intstring( ufid++));
            FnSymbol *fn = new FnSymbol( fname);
            fn->retType = dtVoid;
            stmt->remove();
            fn->insertAtTail( stmt);            // move stmt to new function
            newb->insertAtHead( new DefExpr (fn));
            newb->insertAtTail( new CallExpr (fname));
          }
          b->insertBefore (newb);
          b->remove ();
        }
      }
    }
  }
}

// First pass of the parallel transformations for begin and cobegin blocks.
void
parallel1 (void) {
  addLibInfo ("-lpthread");
  if (parallelPass) {
    begin_encapsulation();     // move begin block to within a function
    cobegin_encapsulation();   // move cobegin stmts to within a function
  }
}

// Mark locals that should be heap allocated and insert a call to allocate
// them on the heap.  This is for begin blocks where the forked child thread
// and parent thread may have different lifetimes.  The locals cannot live
// on a thread's stack.
//   In addition to moving these vars to the heap, we will also use
// reference counting to garbage collect.  Will need a counter and mutex
// for each var.  Of course, those will be heap allocated also.
static void
begin_mark_locals() {
  Vec<SymExpr*> arglist;

  // Find all the args that should be heap allocated -> arglist
  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      BlockStmt *b = dynamic_cast<BlockStmt*>(ast);
      if (b && (BLOCK_BEGIN == b->blockTag)) {
        // note, should only be one call expr in the body of the begin
        for_alist( Expr, stmt, b->body) {
          if (CallExpr *fcall = dynamic_cast<CallExpr*>(stmt)) {
            // add the args that need to be heap allocated
            for_actuals(arg, fcall) {
              if (SymExpr *s = dynamic_cast<SymExpr*>(arg)) {
                arglist.add( s);
              }
            }
          }
        }
      }
    }
  }

  // do a buch of stuff:
  //  - mark locals as heap allocated
  //  - create associated mutex + reference counter
  //  - add mutex + ref-counter to nested function's arg list
  //  - add calls to init ref-counter, touch, and free
  forv_Vec( SymExpr, se, arglist) {
    VarSymbol *local;             // var that is referenced

    if (!(local = dynamic_cast<VarSymbol*>( se->var))) {
      INT_FATAL( se->var, "currently can only handle locals (not args)");
    }

    Expr      *localdef = local->defPoint;

    if (!local->on_heap) {        // no reference counter associated yet
      local->on_heap = true;
      // create reference counter
      char      *refcname = stringcat( "_", stringcat(local->name, "_refc"));
      VarSymbol *refc = new VarSymbol( refcname,
                                       dtInt[INT_SIZE_32],
                                       VAR_NORMAL,
                                       VAR_VAR);
      refc->on_heap = true;
      localdef->insertBefore( new DefExpr( refc));
      local->refc = refc;
      // create reference counter mutex
      char      *mname = stringcat( "_", stringcat(local->name, "_refcmutex"));
      VarSymbol *m = new VarSymbol( mname, dtMutex, VAR_NORMAL, VAR_VAR);
      m->on_heap = true;          // needs to be heap allocated
      localdef->insertBefore( new DefExpr( m));
      local->refcMutex = m;
    }

    // add refc and mutex args as both actuals and formals
    CallExpr  *ce;
    if (!(ce = dynamic_cast<CallExpr*>( se->parentExpr))) {
      INT_FATAL( se->parentExpr, "should be walking args of a call within begin");
    }

    ce->argList->insertAtTail( new SymExpr( local->refc));
    ce->argList->insertAtTail( new SymExpr( local->refcMutex));
    ArgSymbol *rc_arg = new ArgSymbol( INTENT_REF,
                                       local->refc->name,
                                       dtInt[INT_SIZE_32]);
    ArgSymbol *rcm_arg = new ArgSymbol( INTENT_REF,
                                        local->refcMutex->name,
                                        dtMutex);
    FnSymbol  *fn = dynamic_cast<FnSymbol*>( (dynamic_cast<SymExpr*>( ce->baseExpr))->var);
    fn->insertFormalAtTail(new DefExpr( rc_arg));
    fn->insertFormalAtTail(new DefExpr( rcm_arg));

    localdef->insertAfter( new CallExpr( PRIMITIVE_REFC_TOUCH,
                                         local,
                                         local->refc,
                                         local->refcMutex));
    localdef->insertAfter( new CallExpr( PRIMITIVE_REFC_INIT,
                                         local,
                                         local->refc,
                                         local->refcMutex));
    BlockStmt *mainfb = dynamic_cast<BlockStmt*>(localdef->parentExpr);
    Expr      *laststmt = mainfb->body->last();
    if (dynamic_cast<ReturnStmt*>(laststmt)) {
      laststmt->insertBefore( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                            local,
                                            local->refc,
                                            local->refcMutex));
    } else {
      laststmt->insertAfter( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                           local,
                                           local->refc,
                                           local->refcMutex));
    }

    // add touch + release for the begin block
    se->getStmtExpr()->parentExpr->insertBefore( new CallExpr( PRIMITIVE_REFC_TOUCH,
                                                               local,
                                                               local->refc,
                                                               local->refcMutex));
    ArgSymbol *fa = dynamic_cast<ArgSymbol*>( actual_to_formal( se));
    fn->body->body->last()->insertBefore( new CallExpr( PRIMITIVE_REFC_RELEASE,
                                                        fa,
                                                        rc_arg,
                                                        rcm_arg));
  }

  // for each on_heap variable, add call to allocate it
  forv_Vec(ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    asts.clear();
    collect_asts_postorder(&asts, mod);
    forv_Vec(BaseAST, ast, asts) {
      if (VarSymbol *vs = dynamic_cast<VarSymbol*>(ast)) {
        if (vs->on_heap) {
          CallExpr *alloc = new CallExpr( PRIMITIVE_CHPL_ALLOC,
                                          vs->type->symbol,
                                          new_StringSymbol("heap alloc'd via begin"));
          vs->defPoint->insertAfter(new CallExpr(PRIMITIVE_SET_HEAPVAR,
                                                 vs->defPoint->sym,
                                                 alloc));
        }
      }
    }
  }
}

// Package args into a class and call a wrapper function with that
// object. The wrapper function will then call the function
// created by the previous parallel pass. This is a way to pass along
// multiple args through the limitation of one arg in the runtime's
// thread creation interface.
static void
thread_args() {
  forv_Vec( ModuleSymbol, mod, allModules) {
    Vec<BaseAST*> asts;
    collect_asts( &asts, mod);
    forv_Vec( BaseAST, ast, asts) {
      if (BlockStmt *b = dynamic_cast<BlockStmt*>(ast)) {
        if ((BLOCK_BEGIN == b->blockTag) ||
            (BLOCK_COBEGIN == b->blockTag)) {
          BlockStmt *newb = new BlockStmt();
          newb->blockTag = b->blockTag;
          for_alist(Expr, expr, b->body) {
            if (CallExpr *fcall = dynamic_cast<CallExpr*>(expr)) {
              // create a new class to capture refs to locals
              char* fname = (dynamic_cast<SymExpr*>(fcall->baseExpr))->var->name;
              ClassType* ctype = new ClassType( CLASS_CLASS);
              TypeSymbol* new_c = new TypeSymbol( stringcat("_class_locals",
                                                            fname),
                                                  ctype);

              // disable reference counting, handle manually
              new_c->addPragma("no gc");

              // add the function args as fields in the class
              for_actuals(arg, fcall) {
                SymExpr *s = dynamic_cast<SymExpr*>(arg);
                Symbol  *var = s->var; // arg or var
                VarSymbol* field = new VarSymbol(var->name, var->type);
                field->is_ref = true;
                ctype->fields->insertAtTail(new DefExpr(field));
              }
              mod->stmts->insertAtHead(new DefExpr(new_c));

              // create the class variable instance and allocate it
              VarSymbol *tempc = new VarSymbol( stringcat( "_args_for",
                                                           fname),
                                                ctype);
              b->insertBefore( new DefExpr( tempc));
              CallExpr *tempc_alloc = new CallExpr( PRIMITIVE_CHPL_ALLOC,
                                                    ctype->symbol,
                                                    new_StringSymbol( stringcat( "instance of class ", ctype->symbol->name)));
              b->insertBefore( new CallExpr( PRIMITIVE_MOVE,
                                             tempc,
                                             tempc_alloc));

              // set the references in the class instance
              for_actuals(arg, fcall) {
                SymExpr *s = dynamic_cast<SymExpr*>(arg);
                Symbol  *var = s->var; // var or arg
                CallExpr *setc=new CallExpr(PRIMITIVE_SET_MEMBER_REF_TO,
                                            tempc,
                                            ctype->getField(var->name),
                                            var);
                b->insertBefore( setc);
              }

              // create wrapper-function that uses the class instance
              FnSymbol *wrap_fn = new FnSymbol( stringcat("wrap", fname));
              DefExpr  *fcall_def= (dynamic_cast<SymExpr*>( fcall->baseExpr))->var->defPoint;
              ArgSymbol *wrap_c = new ArgSymbol( INTENT_BLANK, "c", ctype);
              wrap_fn->insertFormalAtTail( wrap_c);
              mod->stmts->insertAtTail(new DefExpr(wrap_fn));
              newb->insertAtTail( new CallExpr( wrap_fn, tempc));
              wrap_fn->insertAtTail(new CallExpr(PRIMITIVE_CHPL_FREE, wrap_c));

              // translate the original cobegin function
              CallExpr *new_cofn = new CallExpr( (dynamic_cast<SymExpr*>(fcall->baseExpr))->var);
              for_fields(field, ctype) {  // insert args
                new_cofn->insertAtTail( new CallExpr(PRIMITIVE_GET_MEMBER_REF_TO,
                                                     wrap_c,
                                                     field));
              }

              wrap_fn->retType = dtVoid;
              fcall->remove();                     // rm orig. call
              wrap_fn->insertAtHead(new_cofn);     // add new call
              wrap_fn->insertAtHead(new CallExpr(PRIMITIVE_THREAD_INIT));
              fcall_def->remove();                 // move orig. def
              mod->stmts->insertAtTail(fcall_def); // to top-level
              normalize(wrap_fn);
            }
          }
          b->replace(newb);
        }
      }
    }
  }
}

// Second pass of the parallel transformations for begin and cobegin blocks.
void
parallel2 (void) {
  if (parallelPass) {
    begin_mark_locals();
    thread_args();
  }
}
<|endoftext|>


<commit_before>#include "peel_outer_hull_layers.h"
#include "outer_hull.h"
#include "writePLY.h"
#include <vector>
#include <iostream>
#define IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
#include "STR.h"
#endif

template <
  typename DerivedV,
  typename DerivedF,
  typename Derivedodd,
  typename Derivedflip>
IGL_INLINE size_t igl::peel_outer_hull_layers(
  const Eigen::PlainObjectBase<DerivedV > & V,
  const Eigen::PlainObjectBase<DerivedF > & F,
  Eigen::PlainObjectBase<Derivedodd > & odd,
  Eigen::PlainObjectBase<Derivedflip > & flip)
{
  using namespace Eigen;
  using namespace std;
  typedef typename DerivedF::Index Index;
  typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
  typedef Matrix<Index,Dynamic,1> MatrixXI;
  typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
  const Index m = F.rows();
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"peel outer hull layers..."<<endl;
#endif

#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"resize output ..."<<endl;
#endif
  // keep track of iteration parity and whether flipped in hull
  MatrixXF Fr = F;
  odd.resize(m,1);
  flip.resize(m,1);
  // Keep track of index map
  MatrixXI IM = MatrixXI::LinSpaced(m,0,m-1);
  // This is O(n * layers)
  bool odd_iter = true;
  MatrixXI P(m,1);
  Index iter = 0;
  while(Fr.size() > 0)
  {
    assert(Fr.rows() == IM.rows());
    // Compute outer hull of current Fr
    MatrixXF Fo;
    MatrixXI Jo;
    MatrixXflip flipr;
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"calling outer hull..."<<endl;
  writePLY(STR("outer-hull-input-"<<iter<<".ply"),V,Fr);
#endif
    outer_hull(V,Fr,Fo,Jo,flipr);
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
  cout<<"reindex, flip..."<<endl;
#endif
    assert(Fo.rows() == Jo.rows());
    // all faces in Fo of Fr
    vector<bool> in_outer(Fr.rows(),false);
    for(Index g = 0;g<Jo.rows();g++)
    {
      odd(IM(Jo(g))) = odd_iter;
      P(IM(Jo(g))) = iter;
      in_outer[Jo(g)] = true;
      flip(IM(Jo(g))) = flipr(Jo(g));
    }
    // Fr = Fr - Fo
    // update IM
    MatrixXF prev_Fr = Fr;
    MatrixXI prev_IM = IM;
    Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
    IM.resize(Fr.rows());
    {
      Index g = 0;
      for(Index f = 0;f<prev_Fr.rows();f++)
      {
        if(!in_outer[f])
        {
          Fr.row(g) = prev_Fr.row(f);
          IM(g) = prev_IM(f);
          g++;
        }
      }
    }
    odd_iter = !odd_iter;
    iter++;
  }
  return iter;
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
template size_t igl::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
#endif
<commit_msg>turn off debug<commit_after>#include "peel_outer_hull_layers.h"
#include "outer_hull.h"
#include "writePLY.h"
#include <vector>
#include <iostream>
//#define IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
#include "STR.h"
#endif

template <
  typename DerivedV,
  typename DerivedF,
  typename Derivedodd,
  typename Derivedflip>
IGL_INLINE size_t igl::peel_outer_hull_layers(
  const Eigen::PlainObjectBase<DerivedV > & V,
  const Eigen::PlainObjectBase<DerivedF > & F,
  Eigen::PlainObjectBase<Derivedodd > & odd,
  Eigen::PlainObjectBase<Derivedflip > & flip)
{
  using namespace Eigen;
  using namespace std;
  typedef typename DerivedF::Index Index;
  typedef Matrix<typename DerivedF::Scalar,Dynamic,DerivedF::ColsAtCompileTime> MatrixXF;
  typedef Matrix<Index,Dynamic,1> MatrixXI;
  typedef Matrix<typename Derivedflip::Scalar,Dynamic,Derivedflip::ColsAtCompileTime> MatrixXflip;
  const Index m = F.rows();
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"peel outer hull layers..."<<endl;
#endif

#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"resize output ..."<<endl;
#endif
  // keep track of iteration parity and whether flipped in hull
  MatrixXF Fr = F;
  odd.resize(m,1);
  flip.resize(m,1);
  // Keep track of index map
  MatrixXI IM = MatrixXI::LinSpaced(m,0,m-1);
  // This is O(n * layers)
  bool odd_iter = true;
  MatrixXI P(m,1);
  Index iter = 0;
  while(Fr.size() > 0)
  {
    assert(Fr.rows() == IM.rows());
    // Compute outer hull of current Fr
    MatrixXF Fo;
    MatrixXI Jo;
    MatrixXflip flipr;
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  cout<<"calling outer hull..."<<endl;
  writePLY(STR("outer-hull-input-"<<iter<<".ply"),V,Fr);
#endif
    outer_hull(V,Fr,Fo,Jo,flipr);
#ifdef IGL_PEEL_OUTER_HULL_LAYERS_DEBUG
  writePLY(STR("outer-hull-output-"<<iter<<".ply"),V,Fo);
  cout<<"reindex, flip..."<<endl;
#endif
    assert(Fo.rows() == Jo.rows());
    // all faces in Fo of Fr
    vector<bool> in_outer(Fr.rows(),false);
    for(Index g = 0;g<Jo.rows();g++)
    {
      odd(IM(Jo(g))) = odd_iter;
      P(IM(Jo(g))) = iter;
      in_outer[Jo(g)] = true;
      flip(IM(Jo(g))) = flipr(Jo(g));
    }
    // Fr = Fr - Fo
    // update IM
    MatrixXF prev_Fr = Fr;
    MatrixXI prev_IM = IM;
    Fr.resize(prev_Fr.rows() - Fo.rows(),F.cols());
    IM.resize(Fr.rows());
    {
      Index g = 0;
      for(Index f = 0;f<prev_Fr.rows();f++)
      {
        if(!in_outer[f])
        {
          Fr.row(g) = prev_Fr.row(f);
          IM(g) = prev_IM(f);
          g++;
        }
      }
    }
    odd_iter = !odd_iter;
    iter++;
  }
  return iter;
}

#ifdef IGL_STATIC_LIBRARY
// Explicit template specialization
template size_t igl::peel_outer_hull_layers<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<bool, -1, 1, 0, -1, 1>, Eigen::Matrix<bool, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<bool, -1, 1, 0, -1, 1> >&);
#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_STRINGIFIER_HPP
#define MAPNIK_JSON_STRINGIFIER_HPP

// mapnik
#include <mapnik/json/generic_json.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/variant.hpp>
// stl
#include <string>

namespace mapnik { namespace json {

struct stringifier
{
    std::string operator()(std::string const& val) const
    {
        return "\"" + val + "\"";
    }

    std::string operator()(value_null) const
    {
        return "null";
    }

    std::string operator()(value_bool val) const
    {
        return val ? "true" : "false";
    }

    std::string operator()(value_integer val) const
    {
        std::string str;
        util::to_string(str, val);
        return str;
    }

    std::string operator()(value_double val) const
    {
        std::string str;
        util::to_string(str, val);
        return str;
    }

    std::string operator()(std::vector<mapnik::json::json_value> const& array) const
    {
        std::string str = "[";
        bool first = true;
        for (auto const& val : array)
        {
            if (first) first = false;
            else str += ",";
            str += mapnik::util::apply_visitor(*this, val);
        }
        str += "]";
        return str;
    }

    std::string operator()(std::vector<std::pair<std::string, mapnik::json::json_value>> const& object) const
    {
        std::string str = "{";
        bool first = true;
        for (auto const& kv : object)
        {
            if (first) first = false;
            else str += ",";
            str += kv.first;
            str += ":";
            str += mapnik::util::apply_visitor(*this, kv.second);
        }
        str += "}";
        return str;
    }
};

}}

#endif // MAPNIK_JSON_STRINGIFIER_HPP
<commit_msg>json stringifier - add missing quoting in nested json objects (ref #3491)<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_JSON_STRINGIFIER_HPP
#define MAPNIK_JSON_STRINGIFIER_HPP

// mapnik
#include <mapnik/json/generic_json.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/util/variant.hpp>
// stl
#include <string>

namespace mapnik { namespace json {

struct stringifier
{
    std::string operator()(std::string const& val) const
    {
        return "\"" + val + "\"";
    }

    std::string operator()(value_null) const
    {
        return "null";
    }

    std::string operator()(value_bool val) const
    {
        return val ? "true" : "false";
    }

    std::string operator()(value_integer val) const
    {
        std::string str;
        util::to_string(str, val);
        return str;
    }

    std::string operator()(value_double val) const
    {
        std::string str;
        util::to_string(str, val);
        return str;
    }

    std::string operator()(std::vector<mapnik::json::json_value> const& array) const
    {
        std::string str = "[";
        bool first = true;
        for (auto const& val : array)
        {
            if (first) first = false;
            else str += ",";
            str += mapnik::util::apply_visitor(*this, val);
        }
        str += "]";
        return str;
    }

    std::string operator()(std::vector<std::pair<std::string, mapnik::json::json_value>> const& object) const
    {
        std::string str = "{";
        bool first = true;
        for (auto const& kv : object)
        {
            if (first) first = false;
            else str += ",";
            str +=  "\"" + kv.first + "\"";
            str += ":";
            str += mapnik::util::apply_visitor(*this, kv.second);
        }
        str += "}";
        return str;
    }
};

}}

#endif // MAPNIK_JSON_STRINGIFIER_HPP
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_SVG_PATH_PARSER_HPP
#define MAPNIK_SVG_PATH_PARSER_HPP

// mapnik
#include <mapnik/config.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
// stl
#include <string>

namespace mapnik {
namespace svg {

template <typename PathType>
bool parse_path(const char* wkt, PathType& p);

template <typename PathType>
bool parse_points(const char* wkt, PathType& p);

template <typename TransformType>
bool MAPNIK_DECL parse_svg_transform(const char* wkt, TransformType& tr);

//
extern template bool MAPNIK_DECL parse_path<svg_converter_type>(const char*, svg_converter_type&);
extern template bool MAPNIK_DECL parse_points<svg_converter_type>(const char*, svg_converter_type&);
extern template bool MAPNIK_DECL parse_svg_transform<svg_converter_type>(const char*, svg_converter_type&);
}
}

#endif // MAPNIK_SVG_PATH_PARSER_HPP
<commit_msg>remove unused include directive<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2016 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#ifndef MAPNIK_SVG_PATH_PARSER_HPP
#define MAPNIK_SVG_PATH_PARSER_HPP

// mapnik
#include <mapnik/config.hpp>
#include <mapnik/svg/svg_converter.hpp>
// stl
#include <string>

namespace mapnik {
namespace svg {

template <typename PathType>
bool parse_path(const char* wkt, PathType& p);

template <typename PathType>
bool parse_points(const char* wkt, PathType& p);

template <typename TransformType>
bool MAPNIK_DECL parse_svg_transform(const char* wkt, TransformType& tr);

//
extern template bool MAPNIK_DECL parse_path<svg_converter_type>(const char*, svg_converter_type&);
extern template bool MAPNIK_DECL parse_points<svg_converter_type>(const char*, svg_converter_type&);
extern template bool MAPNIK_DECL parse_svg_transform<svg_converter_type>(const char*, svg_converter_type&);
}
}

#endif // MAPNIK_SVG_PATH_PARSER_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2010,
 * François Bleibel,
 * Olivier Stasse,
 *
 * CNRS/AIST
 *
 */

#ifndef __SOTVECTORTOMATRIX_HH
#define __SOTVECTORTOMATRIX_HH

#include <dynamic-graph/all-signals.h>
#include <dynamic-graph/entity.h>
#include <sot/core/matrix-geometry.hh>

/* Matrix */
#include <dynamic-graph/linear-algebra.h>

/* STD */
#include <vector>

/* --------------------------------------------------------------------- */
/* --- API ------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

#if defined(WIN32)
#if defined(vector_to_rotation_EXPORTS)
#define SOTVECTORTOROTATION_EXPORT __declspec(dllexport)
#else
#define SOTVECTORTOROTATION_EXPORT __declspec(dllimport)
#endif
#else
#define SOTVECTORTOROTATION_EXPORT
#endif

/* --------------------------------------------------------------------- */
/* --- VECTOR ---------------------------------------------------------- */
/* --------------------------------------------------------------------- */
namespace dynamicgraph {
namespace sot {

class SOTVECTORTOROTATION_EXPORT VectorToRotation
    : public dynamicgraph::Entity {
  enum sotAxis { AXIS_X, AXIS_Y, AXIS_Z };

  unsigned int size;
  std::vector<sotAxis> axes;

public:
  static const std::string CLASS_NAME;
  virtual const std::string &getClassName(void) const { return CLASS_NAME; }

  VectorToRotation(const std::string &name);

  virtual ~VectorToRotation(void) {}

  dynamicgraph::SignalPtr<dynamicgraph::Vector, int> SIN;
  dynamicgraph::SignalTimeDependent<MatrixRotation, int> SOUT;

  MatrixRotation &computeRotation(const dynamicgraph::Vector &angles,
                                  MatrixRotation &res);
};

} /* namespace sot */
} /* namespace dynamicgraph */

#endif // #ifndef __SOTVECTORTOMATRIX_HH
<commit_msg>deprecate vector-to-rotation, fix #128<commit_after>/*
 * Copyright 2010,
 * François Bleibel,
 * Olivier Stasse,
 *
 * CNRS/AIST
 *
 */

#ifndef __SOTVECTORTOMATRIX_HH
#define __SOTVECTORTOMATRIX_HH

#include <dynamic-graph/all-signals.h>
#include <dynamic-graph/entity.h>
#include <sot/core/matrix-geometry.hh>

/* Matrix */
#include <dynamic-graph/linear-algebra.h>

/* STD */
#include <vector>

/* --------------------------------------------------------------------- */
/* --- API ------------------------------------------------------------- */
/* --------------------------------------------------------------------- */

#if defined(WIN32)
#if defined(vector_to_rotation_EXPORTS)
#define SOTVECTORTOROTATION_EXPORT __declspec(dllexport)
#else
#define SOTVECTORTOROTATION_EXPORT __declspec(dllimport)
#endif
#else
#define SOTVECTORTOROTATION_EXPORT
#endif

/* --------------------------------------------------------------------- */
/* --- VECTOR ---------------------------------------------------------- */
/* --------------------------------------------------------------------- */
namespace dynamicgraph {
namespace sot {

class[[deprecated("use RPYToMatrix")]] SOTVECTORTOROTATION_EXPORT
    VectorToRotation : public dynamicgraph::Entity {
  enum sotAxis { AXIS_X, AXIS_Y, AXIS_Z };

  unsigned int size;
  std::vector<sotAxis> axes;

public:
  static const std::string CLASS_NAME;
  virtual const std::string &getClassName(void) const { return CLASS_NAME; }

  VectorToRotation(const std::string &name);

  virtual ~VectorToRotation(void) {}

  dynamicgraph::SignalPtr<dynamicgraph::Vector, int> SIN;
  dynamicgraph::SignalTimeDependent<MatrixRotation, int> SOUT;

  MatrixRotation &computeRotation(const dynamicgraph::Vector &angles,
                                  MatrixRotation &res);
};

} /* namespace sot */
} /* namespace dynamicgraph */

#endif // #ifndef __SOTVECTORTOMATRIX_HH
<|endoftext|>


<commit_before>//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <GraphUtils.hpp>
#include <TestUtils.hpp>

#include <armnn/INetwork.hpp>

#include <doctest/doctest.h>

using namespace armnn;

namespace
{
#if defined(ARMNNREF_ENABLED)||defined(ARMCOMPUTECL_ENABLED)
void FoldPadIntoQuantizedAvgPoolTest(Compute backendId)
{
    // Create a network
    INetworkPtr network = INetwork::Create();

    const unsigned int inputShape[]  = {1, 2, 2, 3};
    const unsigned int paddedShape[] = {1, 4, 4, 3};
    const unsigned int outputShape[] = {1, 2, 2, 3};

    TensorInfo inputInfo(4, inputShape, DataType::QAsymmU8, 1.0f, 0.0f);
    TensorInfo paddedInfo(4, paddedShape, DataType::QAsymmU8, 1.0f, 0.0f);
    TensorInfo outputInfo(4, outputShape, DataType::QAsymmU8, 1.0f, 0.0f);

    IConnectableLayer* input = network->AddInputLayer(0, "input");
    input->GetOutputSlot(0).SetTensorInfo(inputInfo);

    PadDescriptor padDescriptor({{0, 0},
                                 {1, 1},
                                 {1, 1},
                                 {0, 0}});

    IConnectableLayer* padLayer = network->AddPadLayer(padDescriptor, "pad");
    padLayer->GetOutputSlot(0).SetTensorInfo(paddedInfo);

    Pooling2dDescriptor pooling2dDescriptor;
    pooling2dDescriptor.m_PoolType   = PoolingAlgorithm::Average;
    pooling2dDescriptor.m_PoolWidth  = 3;
    pooling2dDescriptor.m_PoolHeight = 3;
    pooling2dDescriptor.m_StrideX    = 1;
    pooling2dDescriptor.m_StrideY    = 1;
    pooling2dDescriptor.m_DataLayout = DataLayout::NHWC;

    IConnectableLayer* pool2dLayer = network->AddPooling2dLayer(pooling2dDescriptor, "pool2d");
    pool2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);

    IConnectableLayer* output = network->AddOutputLayer(0, "output");

    // Connect up layers - input -> pad -> pool2d -> output
    input->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
    padLayer->GetOutputSlot(0).Connect(pool2dLayer->GetInputSlot(0));
    pool2dLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));

    // Create ArmNN runtime
    IRuntimePtr run = IRuntime::Create(IRuntime::CreationOptions());

    // Optimise ArmNN network
    IOptimizedNetworkPtr optNet = Optimize(*network, {backendId}, run->GetDeviceSpec());

    auto checkPadFoldedIntoPool2d = [&](const Layer* const layer) {
        if (!IsLayerOfType<Pooling2dLayer>(layer) || (layer->GetNameStr() != "folded-pad-into-pool2d"))
        {
            return false;
        }

        const auto                pool2dLayer       = static_cast<const Pooling2dLayer*>(layer);
        const Pooling2dDescriptor pool2dLayerParams = pool2dLayer->GetParameters();

        Pooling2dDescriptor pool2dLayerParamsNoPad = pool2dLayerParams;
        pool2dLayerParamsNoPad.m_PadLeft       = 0;
        pool2dLayerParamsNoPad.m_PadRight      = 0;
        pool2dLayerParamsNoPad.m_PadTop        = 0;
        pool2dLayerParamsNoPad.m_PadBottom     = 0;
        // If we fold then PaddingMethod will be set to Ignore. The original will be Exclude.
        pool2dLayerParamsNoPad.m_PaddingMethod = PaddingMethod::Exclude;

        return (pool2dLayerParamsNoPad == pooling2dDescriptor) && (pool2dLayerParams.m_PadLeft == 1) &&
            (pool2dLayerParams.m_PadRight == 1) && (pool2dLayerParams.m_PadTop == 1) &&
            (pool2dLayerParams.m_PadBottom == 1) && (pool2dLayerParams.m_PaddingMethod == PaddingMethod::IgnoreValue);
    };

    Graph& graph = GetGraphForTesting(optNet.get());
    CHECK(CheckSequence(graph.cbegin(), graph.cend(),
                        &IsLayerOfType<InputLayer>,
                        checkPadFoldedIntoPool2d,
                        &IsLayerOfType<OutputLayer>));
}
#endif
}

TEST_SUITE("Optimizer_FoldPadIntoQuantizedAvgPoolCpuRef")
{
TEST_CASE("FoldPadIntoQuantizedAvgPoolCpuRefTest")
{
    FoldPadIntoQuantizedAvgPoolTest(Compute::CpuRef);
}
}

#if defined(ARMCOMPUTECL_ENABLED)
TEST_SUITE("Optimizer_FoldPadIntoQuantizedAvgPoolGpuAcc")
{
TEST_CASE("FoldPadIntoQuantizedAvgPoolGpuAccTest")
{
    FoldPadIntoQuantizedAvgPoolTest(Compute::GpuAcc);
}
}
#endif
<commit_msg>IVGCVSW-7149 FoldPadIntoQuantizedAvgPoolCpuRefTest test failing while running Arm NN Unittest<commit_after>//
// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <GraphUtils.hpp>
#include <TestUtils.hpp>

#include <armnn/INetwork.hpp>

#include <doctest/doctest.h>

using namespace armnn;

namespace
{
#if defined(ARMNNREF_ENABLED)||defined(ARMCOMPUTECL_ENABLED)
void FoldPadIntoQuantizedAvgPoolTest(Compute backendId)
{
    // Create a network
    INetworkPtr network = INetwork::Create();

    const unsigned int inputShape[]  = {1, 2, 2, 3};
    const unsigned int paddedShape[] = {1, 4, 4, 3};
    const unsigned int outputShape[] = {1, 2, 2, 3};

    TensorInfo inputInfo(4, inputShape, DataType::QAsymmU8, 1.0f, 0.0f);
    TensorInfo paddedInfo(4, paddedShape, DataType::QAsymmU8, 1.0f, 0.0f);
    TensorInfo outputInfo(4, outputShape, DataType::QAsymmU8, 1.0f, 0.0f);

    IConnectableLayer* input = network->AddInputLayer(0, "input");
    input->GetOutputSlot(0).SetTensorInfo(inputInfo);

    PadDescriptor padDescriptor({{0, 0},
                                 {1, 1},
                                 {1, 1},
                                 {0, 0}});

    IConnectableLayer* padLayer = network->AddPadLayer(padDescriptor, "pad");
    padLayer->GetOutputSlot(0).SetTensorInfo(paddedInfo);

    Pooling2dDescriptor pooling2dDescriptor;
    pooling2dDescriptor.m_PoolType   = PoolingAlgorithm::Average;
    pooling2dDescriptor.m_PoolWidth  = 3;
    pooling2dDescriptor.m_PoolHeight = 3;
    pooling2dDescriptor.m_StrideX    = 1;
    pooling2dDescriptor.m_StrideY    = 1;
    pooling2dDescriptor.m_DataLayout = DataLayout::NHWC;

    IConnectableLayer* pool2dLayer = network->AddPooling2dLayer(pooling2dDescriptor, "pool2d");
    pool2dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);

    IConnectableLayer* output = network->AddOutputLayer(0, "output");

    // Connect up layers - input -> pad -> pool2d -> output
    input->GetOutputSlot(0).Connect(padLayer->GetInputSlot(0));
    padLayer->GetOutputSlot(0).Connect(pool2dLayer->GetInputSlot(0));
    pool2dLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));

    // Create ArmNN runtime
    IRuntimePtr run = IRuntime::Create(IRuntime::CreationOptions());

    // Optimise ArmNN network
    IOptimizedNetworkPtr optNet = Optimize(*network, {backendId}, run->GetDeviceSpec());

    auto checkPadFoldedIntoPool2d = [&](const Layer* const layer) {
        if (!IsLayerOfType<Pooling2dLayer>(layer) || (layer->GetNameStr() != "folded-pad-into-pool2d"))
        {
            return false;
        }

        const auto                pool2dLayer       = static_cast<const Pooling2dLayer*>(layer);
        const Pooling2dDescriptor pool2dLayerParams = pool2dLayer->GetParameters();

        Pooling2dDescriptor pool2dLayerParamsNoPad = pool2dLayerParams;
        pool2dLayerParamsNoPad.m_PadLeft       = 0;
        pool2dLayerParamsNoPad.m_PadRight      = 0;
        pool2dLayerParamsNoPad.m_PadTop        = 0;
        pool2dLayerParamsNoPad.m_PadBottom     = 0;
        // If we fold then PaddingMethod will be set to Ignore. The original will be Exclude.
        pool2dLayerParamsNoPad.m_PaddingMethod = PaddingMethod::Exclude;

        return (pool2dLayerParamsNoPad == pooling2dDescriptor) && (pool2dLayerParams.m_PadLeft == 1) &&
            (pool2dLayerParams.m_PadRight == 1) && (pool2dLayerParams.m_PadTop == 1) &&
            (pool2dLayerParams.m_PadBottom == 1) && (pool2dLayerParams.m_PaddingMethod == PaddingMethod::IgnoreValue);
    };

    Graph& graph = GetGraphForTesting(optNet.get());
    CHECK(CheckSequence(graph.cbegin(), graph.cend(),
                        &IsLayerOfType<InputLayer>,
                        checkPadFoldedIntoPool2d,
                        &IsLayerOfType<OutputLayer>));
}
#endif
}

#if defined(ARMNNREF_ENABLED)
TEST_SUITE("Optimizer_FoldPadIntoQuantizedAvgPoolCpuRef")
{
TEST_CASE("FoldPadIntoQuantizedAvgPoolCpuRefTest")
{
    FoldPadIntoQuantizedAvgPoolTest(Compute::CpuRef);
}
}
#endif

#if defined(ARMCOMPUTECL_ENABLED)
TEST_SUITE("Optimizer_FoldPadIntoQuantizedAvgPoolGpuAcc")
{
TEST_CASE("FoldPadIntoQuantizedAvgPoolGpuAccTest")
{
    FoldPadIntoQuantizedAvgPoolTest(Compute::GpuAcc);
}
}
#endif
<|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Base class for a torsion-bar suspension system using linear dampers (template
// definition).
//
// =============================================================================

#include "chrono/assets/ChCylinderShape.h"
#include "chrono/assets/ChColorAsset.h"

#include "chrono_vehicle/tracked_vehicle/suspension/ChLinearDamperRWAssembly.h"

namespace chrono {
namespace vehicle {

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ChLinearDamperRWAssembly::ChLinearDamperRWAssembly(const std::string& name, bool has_shock)
    : ChRoadWheelAssembly(name), m_has_shock(has_shock) {
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::Initialize(ChSharedPtr<ChBodyAuxRef> chassis, const ChVector<>& location) {
    // Express the suspension reference frame in the absolute coordinate system.
    ChFrame<> susp_to_abs(location);
    susp_to_abs.ConcatenatePreTransformation(chassis->GetFrame_REF_to_abs());

    // Transform all points and directions to absolute frame.
    std::vector<ChVector<> > points(NUM_POINTS);

    for (int i = 0; i < NUM_POINTS; i++) {
        ChVector<> rel_pos = GetLocation(static_cast<PointId>(i));
        points[i] = susp_to_abs.TransformPointLocalToParent(rel_pos);
    }

    // Sanity check.
    assert(points[ARM_WHEEL].x == 0 && points[ARM_WHEEL].z == 0);

    // Create the trailing arm body. The reference frame of the arm body has its
    // x-axis aligned with the line between the arm-chassis connection point and
    // the arm-wheel connection point.
    ChVector<> u = susp_to_abs.GetPos() - points[ARM_CHASSIS];
    u.Normalize();
    ChVector<> w = Vcross(u, susp_to_abs.GetA().Get_A_Yaxis());
    w.Normalize();
    ChVector<> v = Vcross(w, u);
    ChMatrix33<> rot;
    rot.Set_A_axis(u, v, w);

    m_arm = ChSharedPtr<ChBody>(new ChBody(chassis->GetSystem()->GetContactMethod()));
    m_arm->SetNameString(m_name + "_arm");
    m_arm->SetPos(points[ARM]);
    m_arm->SetRot(rot);
    m_arm->SetMass(GetArmMass());
    m_arm->SetInertiaXX(GetArmInertia());
    AddVisualizationArm(susp_to_abs.GetPos(), points[ARM], points[ARM_WHEEL], points[ARM_CHASSIS], points[SHOCK_A]);
    chassis->GetSystem()->AddBody(m_arm);

    // Create and initialize the revolute joint between arm and chassis.
    // The axis of rotation is the y axis of the suspension reference frame.
    m_revolute = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute);
    m_revolute->SetNameString(m_name + "_revolute");
    m_revolute->Initialize(chassis, m_arm,
                           ChCoordsys<>(points[ARM_CHASSIS], susp_to_abs.GetRot() * Q_from_AngX(CH_C_PI_2)));
    // Add torsional spring associated with m_revolute
    m_revolute->SetForce_Rz(GetTorsionForceFunction());
    chassis->GetSystem()->AddLink(m_revolute);

    // Create and initialize the shock force element.
    if (m_has_shock) {
        m_shock = ChSharedPtr<ChLinkSpringCB>(new ChLinkSpringCB);
        m_shock->SetNameString(m_name + "_shock");
        m_shock->Initialize(chassis, m_arm, false, points[SHOCK_C], points[SHOCK_A]);
        m_shock->Set_SpringCallback(GetShockForceCallback());
        chassis->GetSystem()->AddLink(m_shock);
    }

    // Invoke the base class implementation. This initializes the associated road wheel.
    // Note: we must call this here, after the m_arm body is created.
    ChRoadWheelAssembly::Initialize(chassis, location);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::AddVisualizationArm(const ChVector<>& pt_O,
                                                   const ChVector<>& pt_A,
                                                   const ChVector<>& pt_AW,
                                                   const ChVector<>& pt_AC,
                                                   const ChVector<>& pt_AS) {
    static const double threshold2 = 1e-6;
    double radius = GetArmVisRadius();

    // Express hardpoint locations in body frame.
    ChVector<> p_O = m_arm->TransformPointParentToLocal(pt_O);
    ChVector<> p_A = m_arm->TransformPointParentToLocal(pt_A);
    ChVector<> p_AC = m_arm->TransformPointParentToLocal(pt_AC);
    ChVector<> p_AW = m_arm->TransformPointParentToLocal(pt_AW);
    ChVector<> p_AS = m_arm->TransformPointParentToLocal(pt_AS);

    if ((p_A - p_AW).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AW;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_A - p_AC).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AC;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_A - p_AS).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AS;
        cyl->GetCylinderGeometry().rad = 0.75 * radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_O - p_AW).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        double len = (p_O - p_AW).Length();
        cyl->GetCylinderGeometry().p1 = p_O;
        cyl->GetCylinderGeometry().p2 = p_AW + (p_AW - p_O) * radius/len;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0.2f, 0.6f, 0.3f));
    m_arm->AddAsset(col);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::LogConstraintViolations() {
    ChMatrix<>* C = m_revolute->GetC();
    GetLog() << "  Arm-chassis revolute\n";
    GetLog() << "  " << C->GetElement(0, 0) << "  ";
    GetLog() << "  " << C->GetElement(1, 0) << "  ";
    GetLog() << "  " << C->GetElement(2, 0) << "  ";
    GetLog() << "  " << C->GetElement(3, 0) << "  ";
    GetLog() << "  " << C->GetElement(4, 0) << "\n";

    m_road_wheel->LogConstraintViolations();
}

}  // end namespace vehicle
}  // end namespace chrono
<commit_msg>Fix incorrect assert<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban
// =============================================================================
//
// Base class for a torsion-bar suspension system using linear dampers (template
// definition).
//
// =============================================================================

#include "chrono/assets/ChCylinderShape.h"
#include "chrono/assets/ChColorAsset.h"

#include "chrono_vehicle/tracked_vehicle/suspension/ChLinearDamperRWAssembly.h"

namespace chrono {
namespace vehicle {

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ChLinearDamperRWAssembly::ChLinearDamperRWAssembly(const std::string& name, bool has_shock)
    : ChRoadWheelAssembly(name), m_has_shock(has_shock) {
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::Initialize(ChSharedPtr<ChBodyAuxRef> chassis, const ChVector<>& location) {
    // Express the suspension reference frame in the absolute coordinate system.
    ChFrame<> susp_to_abs(location);
    susp_to_abs.ConcatenatePreTransformation(chassis->GetFrame_REF_to_abs());

    // Transform all points and directions to absolute frame.
    std::vector<ChVector<> > points(NUM_POINTS);

    for (int i = 0; i < NUM_POINTS; i++) {
        ChVector<> rel_pos = GetLocation(static_cast<PointId>(i));
        points[i] = susp_to_abs.TransformPointLocalToParent(rel_pos);
    }

    // Sanity check.
    assert(points[ARM_WHEEL].x == susp_to_abs.GetPos().x && points[ARM_WHEEL].z == susp_to_abs.GetPos().z);

    // Create the trailing arm body. The reference frame of the arm body has its
    // x-axis aligned with the line between the arm-chassis connection point and
    // the arm-wheel connection point.
    ChVector<> u = susp_to_abs.GetPos() - points[ARM_CHASSIS];
    u.Normalize();
    ChVector<> w = Vcross(u, susp_to_abs.GetA().Get_A_Yaxis());
    w.Normalize();
    ChVector<> v = Vcross(w, u);
    ChMatrix33<> rot;
    rot.Set_A_axis(u, v, w);

    m_arm = ChSharedPtr<ChBody>(new ChBody(chassis->GetSystem()->GetContactMethod()));
    m_arm->SetNameString(m_name + "_arm");
    m_arm->SetPos(points[ARM]);
    m_arm->SetRot(rot);
    m_arm->SetMass(GetArmMass());
    m_arm->SetInertiaXX(GetArmInertia());
    AddVisualizationArm(susp_to_abs.GetPos(), points[ARM], points[ARM_WHEEL], points[ARM_CHASSIS], points[SHOCK_A]);
    chassis->GetSystem()->AddBody(m_arm);

    // Create and initialize the revolute joint between arm and chassis.
    // The axis of rotation is the y axis of the suspension reference frame.
    m_revolute = ChSharedPtr<ChLinkLockRevolute>(new ChLinkLockRevolute);
    m_revolute->SetNameString(m_name + "_revolute");
    m_revolute->Initialize(chassis, m_arm,
                           ChCoordsys<>(points[ARM_CHASSIS], susp_to_abs.GetRot() * Q_from_AngX(CH_C_PI_2)));
    // Add torsional spring associated with m_revolute
    m_revolute->SetForce_Rz(GetTorsionForceFunction());
    chassis->GetSystem()->AddLink(m_revolute);

    // Create and initialize the shock force element.
    if (m_has_shock) {
        m_shock = ChSharedPtr<ChLinkSpringCB>(new ChLinkSpringCB);
        m_shock->SetNameString(m_name + "_shock");
        m_shock->Initialize(chassis, m_arm, false, points[SHOCK_C], points[SHOCK_A]);
        m_shock->Set_SpringCallback(GetShockForceCallback());
        chassis->GetSystem()->AddLink(m_shock);
    }

    // Invoke the base class implementation. This initializes the associated road wheel.
    // Note: we must call this here, after the m_arm body is created.
    ChRoadWheelAssembly::Initialize(chassis, location);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::AddVisualizationArm(const ChVector<>& pt_O,
                                                   const ChVector<>& pt_A,
                                                   const ChVector<>& pt_AW,
                                                   const ChVector<>& pt_AC,
                                                   const ChVector<>& pt_AS) {
    static const double threshold2 = 1e-6;
    double radius = GetArmVisRadius();

    // Express hardpoint locations in body frame.
    ChVector<> p_O = m_arm->TransformPointParentToLocal(pt_O);
    ChVector<> p_A = m_arm->TransformPointParentToLocal(pt_A);
    ChVector<> p_AC = m_arm->TransformPointParentToLocal(pt_AC);
    ChVector<> p_AW = m_arm->TransformPointParentToLocal(pt_AW);
    ChVector<> p_AS = m_arm->TransformPointParentToLocal(pt_AS);

    if ((p_A - p_AW).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AW;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_A - p_AC).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AC;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_A - p_AS).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        cyl->GetCylinderGeometry().p1 = p_A;
        cyl->GetCylinderGeometry().p2 = p_AS;
        cyl->GetCylinderGeometry().rad = 0.75 * radius;
        m_arm->AddAsset(cyl);
    }

    if ((p_O - p_AW).Length2() > threshold2) {
        ChSharedPtr<ChCylinderShape> cyl(new ChCylinderShape);
        double len = (p_O - p_AW).Length();
        cyl->GetCylinderGeometry().p1 = p_O;
        cyl->GetCylinderGeometry().p2 = p_AW + (p_AW - p_O) * radius/len;
        cyl->GetCylinderGeometry().rad = radius;
        m_arm->AddAsset(cyl);
    }

    ChSharedPtr<ChColorAsset> col(new ChColorAsset);
    col->SetColor(ChColor(0.2f, 0.6f, 0.3f));
    m_arm->AddAsset(col);
}

// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ChLinearDamperRWAssembly::LogConstraintViolations() {
    ChMatrix<>* C = m_revolute->GetC();
    GetLog() << "  Arm-chassis revolute\n";
    GetLog() << "  " << C->GetElement(0, 0) << "  ";
    GetLog() << "  " << C->GetElement(1, 0) << "  ";
    GetLog() << "  " << C->GetElement(2, 0) << "  ";
    GetLog() << "  " << C->GetElement(3, 0) << "  ";
    GetLog() << "  " << C->GetElement(4, 0) << "\n";

    m_road_wheel->LogConstraintViolations();
}

}  // end namespace vehicle
}  // end namespace chrono
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * 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.
 */

// This example demonstrates startup tracing with a custom data source.
// Startup tracing can work only with kSystemBackend. Before running
// this example, `traced` must already be running in a separate process.

// Run system tracing: ninja -C out/default/ traced && ./out/default/traced
// And then run this example: ninja -C out/default example_startup_trace &&
//                            ./out/default/example_startup_trace

#if defined(PERFETTO_SDK_EXAMPLE_USE_INTERNAL_HEADERS)
#include "perfetto/tracing.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/data_source.h"
#include "perfetto/tracing/tracing.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
#else
#include <perfetto.h>
#endif

#include <unistd.h>
#include <fstream>
#include <iostream>
#include <thread>

namespace {

// The definition of our custom data source. Instances of this class will be
// automatically created and destroyed by Perfetto.
class CustomDataSource : public perfetto::DataSource<CustomDataSource> {};

void InitializePerfetto() {
  perfetto::TracingInitArgs args;
  // The backends determine where trace events are recorded. For this example we
  // are going to use the system-wide tracing service, because the in-process
  // backend doesn't support startup tracing.
  args.backends = perfetto::kSystemBackend;
  perfetto::Tracing::Initialize(args);

  // Register our custom data source. Only the name is required, but other
  // properties can be advertised too.
  perfetto::DataSourceDescriptor dsd;
  dsd.set_name("com.example.startup_trace");
  CustomDataSource::Register(dsd);
}

// The trace config defines which types of data sources are enabled for
// recording.
perfetto::TraceConfig GetTraceConfig() {
  perfetto::TraceConfig cfg;
  cfg.add_buffers()->set_size_kb(1024);
  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
  ds_cfg->set_name("com.example.startup_trace");
  return cfg;
}

void StartStartupTracing() {
  perfetto::Tracing::SetupStartupTracingOpts args;
  args.backend = perfetto::kSystemBackend;
  perfetto::Tracing::SetupStartupTracingBlocking(GetTraceConfig(), args);
}

std::unique_ptr<perfetto::TracingSession> StartTracing() {
  auto tracing_session = perfetto::Tracing::NewTrace();
  tracing_session->Setup(GetTraceConfig());
  tracing_session->StartBlocking();
  return tracing_session;
}

void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
  // Flush to make sure the last written event ends up in the trace.
  CustomDataSource::Trace(
      [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });

  // Stop tracing and read the trace data.
  tracing_session->StopBlocking();
  std::vector<char> trace_data(tracing_session->ReadTraceBlocking());

  // Write the result into a file.
  // Note: To save memory with longer traces, you can tell Perfetto to write
  // directly into a file by passing a file descriptor into Setup() above.
  std::ofstream output;
  const char* filename = "example_startup_trace.pftrace";
  output.open(filename, std::ios::out | std::ios::binary);
  output.write(&trace_data[0], static_cast<std::streamsize>(trace_data.size()));
  output.close();
  PERFETTO_LOG(
      "Trace written in %s file. To read this trace in "
      "text form, run `./tools/traceconv text %s`",
      filename, filename);
}

}  // namespace

PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);

int main(int, const char**) {
  InitializePerfetto();

  StartStartupTracing();

  // Write an event using our custom data source before starting tracing
  // session.
  CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
    auto packet = ctx.NewTracePacket();
    packet->set_timestamp(41);
    packet->set_for_testing()->set_str("Startup Event");
  });

  auto tracing_session = StartTracing();

  // Write an event using our custom data source.
  CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
    auto packet = ctx.NewTracePacket();
    packet->set_timestamp(42);
    packet->set_for_testing()->set_str("Main Event");
  });
  StopTracing(std::move(tracing_session));

  return 0;
}
<commit_msg>Fix example_startup_trace build on windows<commit_after>/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * 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.
 */

// This example demonstrates startup tracing with a custom data source.
// Startup tracing can work only with kSystemBackend. Before running
// this example, `traced` must already be running in a separate process.

// Run system tracing: ninja -C out/default/ traced && ./out/default/traced
// And then run this example: ninja -C out/default example_startup_trace &&
//                            ./out/default/example_startup_trace

#if defined(PERFETTO_SDK_EXAMPLE_USE_INTERNAL_HEADERS)
#include "perfetto/tracing.h"
#include "perfetto/tracing/core/data_source_descriptor.h"
#include "perfetto/tracing/core/trace_config.h"
#include "perfetto/tracing/data_source.h"
#include "perfetto/tracing/tracing.h"
#include "protos/perfetto/trace/test_event.pbzero.h"
#else
#include <perfetto.h>
#endif

#include <fstream>
#include <iostream>
#include <thread>

namespace {

// The definition of our custom data source. Instances of this class will be
// automatically created and destroyed by Perfetto.
class CustomDataSource : public perfetto::DataSource<CustomDataSource> {};

void InitializePerfetto() {
  perfetto::TracingInitArgs args;
  // The backends determine where trace events are recorded. For this example we
  // are going to use the system-wide tracing service, because the in-process
  // backend doesn't support startup tracing.
  args.backends = perfetto::kSystemBackend;
  perfetto::Tracing::Initialize(args);

  // Register our custom data source. Only the name is required, but other
  // properties can be advertised too.
  perfetto::DataSourceDescriptor dsd;
  dsd.set_name("com.example.startup_trace");
  CustomDataSource::Register(dsd);
}

// The trace config defines which types of data sources are enabled for
// recording.
perfetto::TraceConfig GetTraceConfig() {
  perfetto::TraceConfig cfg;
  cfg.add_buffers()->set_size_kb(1024);
  auto* ds_cfg = cfg.add_data_sources()->mutable_config();
  ds_cfg->set_name("com.example.startup_trace");
  return cfg;
}

void StartStartupTracing() {
  perfetto::Tracing::SetupStartupTracingOpts args;
  args.backend = perfetto::kSystemBackend;
  perfetto::Tracing::SetupStartupTracingBlocking(GetTraceConfig(), args);
}

std::unique_ptr<perfetto::TracingSession> StartTracing() {
  auto tracing_session = perfetto::Tracing::NewTrace();
  tracing_session->Setup(GetTraceConfig());
  tracing_session->StartBlocking();
  return tracing_session;
}

void StopTracing(std::unique_ptr<perfetto::TracingSession> tracing_session) {
  // Flush to make sure the last written event ends up in the trace.
  CustomDataSource::Trace(
      [](CustomDataSource::TraceContext ctx) { ctx.Flush(); });

  // Stop tracing and read the trace data.
  tracing_session->StopBlocking();
  std::vector<char> trace_data(tracing_session->ReadTraceBlocking());

  // Write the result into a file.
  // Note: To save memory with longer traces, you can tell Perfetto to write
  // directly into a file by passing a file descriptor into Setup() above.
  std::ofstream output;
  const char* filename = "example_startup_trace.pftrace";
  output.open(filename, std::ios::out | std::ios::binary);
  output.write(trace_data.data(),
               static_cast<std::streamsize>(trace_data.size()));
  output.close();
  PERFETTO_LOG(
      "Trace written in %s file. To read this trace in "
      "text form, run `./tools/traceconv text %s`",
      filename, filename);
}

}  // namespace

PERFETTO_DECLARE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);
PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(CustomDataSource);

int main(int, const char**) {
  InitializePerfetto();

  StartStartupTracing();

  // Write an event using our custom data source before starting tracing
  // session.
  CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
    auto packet = ctx.NewTracePacket();
    packet->set_timestamp(41);
    packet->set_for_testing()->set_str("Startup Event");
  });

  auto tracing_session = StartTracing();

  // Write an event using our custom data source.
  CustomDataSource::Trace([](CustomDataSource::TraceContext ctx) {
    auto packet = ctx.NewTracePacket();
    packet->set_timestamp(42);
    packet->set_for_testing()->set_str("Main Event");
  });
  StopTracing(std::move(tracing_session));

  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Shuffle: make sure not to fail if getClipPreferences was not called<commit_after><|endoftext|>


<commit_before>// @(#)root/reflex:$Id$
// Author: Stefan Roiser 2004

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#ifndef REFLEX_BUILD
# define REFLEX_BUILD
#endif

#include "Reflex/internal/MemberBase.h"

#include "Reflex/internal/OwnedMember.h"
#include "Reflex/Scope.h"
#include "Reflex/Type.h"
#include "Reflex/Base.h"
#include "Reflex/Object.h"
#include "Reflex/internal/OwnedPropertyList.h"
#include "Reflex/DictionaryGenerator.h"

#include "Reflex/Tools.h"
#include "Class.h"

//-------------------------------------------------------------------------------
Reflex::MemberBase::MemberBase(const char* name,
                               const Type& type,
                               TYPE memberType,
                               unsigned int modifiers)
//-------------------------------------------------------------------------------
   : fType(type, modifiers & (CONST | VOLATILE | REFERENCE), Type::APPEND),
   fModifiers(modifiers),
   fName(name),
   fScope(Scope()),
   fMemberType(memberType),
   fPropertyList(OwnedPropertyList(new PropertyListImpl())) {
// Construct the dictionary info for a member
   fThisMember = new Member(this);
}

//-------------------------------------------------------------------------------
Reflex::MemberBase::~MemberBase() {
//-------------------------------------------------------------------------------
// Destructor.
   delete fThisMember;
   fPropertyList.Delete();
}

//-------------------------------------------------------------------------------
Reflex::MemberBase::operator
Reflex::Member() const {
//-------------------------------------------------------------------------------
// Conversion operator to Member.
   return *fThisMember;
}

//-------------------------------------------------------------------------------
void*
Reflex::MemberBase::CalculateBaseObject(const Object& obj) const {
//-------------------------------------------------------------------------------
// Return the object address a member lives in.
   char* mem = (char*) obj.Address();
   // check if its a dummy object
   Type cl = obj.TypeOf();

   while (cl && cl.IsTypedef()) {
      cl = cl.ToType();
   }

   // if the object type is not implemented return the Address of the object
   if (!cl) {
      return mem;
   }

   if (cl.IsClass()) {
      if (DeclaringScope() && (cl.Id() != (dynamic_cast<const Class*>(DeclaringScope().ToScopeBase()))->ThisType().Id())) {
         // now we know that the Member type is an inherited one
         std::vector<OffsetFunction> basePath = (dynamic_cast<const Class*>(cl.ToTypeBase()))->PathToBase(DeclaringScope());

         if (basePath.size()) {
            // there is a path described from the object to the class containing the Member
            std::vector<OffsetFunction>::iterator pIter;

            for (pIter = basePath.begin(); pIter != basePath.end(); ++pIter) {
               mem += (*pIter)(mem);
            }
         } else {
            throw RuntimeError(std::string(": ERROR: There is no path available from class ")
                               + cl.Name(SCOPED) + " to " + Name(SCOPED));
         }
      }
   } else {
      throw RuntimeError(std::string("Object ") + cl.Name(SCOPED) + " does not represent a class");
   }
   return (void*) mem;
} // CalculateBaseObject

//-------------------------------------------------------------------------------
Reflex::Scope
Reflex::MemberBase::DeclaringScope() const {
//-------------------------------------------------------------------------------
// Return the scope the member lives in.
   return fScope;
}

//-------------------------------------------------------------------------------
Reflex::Type
Reflex::MemberBase::DeclaringType() const {
//-------------------------------------------------------------------------------
// Return the type the member lives in.
   return DeclaringScope();
}

//-------------------------------------------------------------------------------
std::string
Reflex::MemberBase::MemberTypeAsString() const {
//-------------------------------------------------------------------------------
// Remember type of the member as a string.
   switch (fMemberType) {
   case DATAMEMBER:
      return "DataMember";
      break;
   case FUNCTIONMEMBER:
      return "FunctionMember";
      break;
   default:
      return Reflex::Argv0() + ": ERROR: Member " + Name() +
             " has no Species associated";
   }
}

//-------------------------------------------------------------------------------
Reflex::PropertyList
Reflex::MemberBase::Properties() const {
//-------------------------------------------------------------------------------
// Return the property list attached to this member.
   return fPropertyList;
}

//-------------------------------------------------------------------------------
Reflex::Type
Reflex::MemberBase::TemplateArgumentAt(size_t /* nth */) const {
//-------------------------------------------------------------------------------
// Return the nth template argument (in FunMemTemplInstance)
   return Dummy::Type();
}

//-------------------------------------------------------------------------------
void
Reflex::MemberBase::GenerateDict(DictionaryGenerator& /* generator */) const {
//-------------------------------------------------------------------------------
// Generate Dictionary information about itself.
}
<commit_msg>Fix Cov CID 10240, check dyn_cast != 0<commit_after>// @(#)root/reflex:$Id$
// Author: Stefan Roiser 2004

// Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#ifndef REFLEX_BUILD
# define REFLEX_BUILD
#endif

#include "Reflex/internal/MemberBase.h"

#include "Reflex/internal/OwnedMember.h"
#include "Reflex/Scope.h"
#include "Reflex/Type.h"
#include "Reflex/Base.h"
#include "Reflex/Object.h"
#include "Reflex/internal/OwnedPropertyList.h"
#include "Reflex/DictionaryGenerator.h"

#include "Reflex/Tools.h"
#include "Class.h"

//-------------------------------------------------------------------------------
Reflex::MemberBase::MemberBase(const char* name,
                               const Type& type,
                               TYPE memberType,
                               unsigned int modifiers)
//-------------------------------------------------------------------------------
   : fType(type, modifiers & (CONST | VOLATILE | REFERENCE), Type::APPEND),
   fModifiers(modifiers),
   fName(name),
   fScope(Scope()),
   fMemberType(memberType),
   fPropertyList(OwnedPropertyList(new PropertyListImpl())) {
// Construct the dictionary info for a member
   fThisMember = new Member(this);
}

//-------------------------------------------------------------------------------
Reflex::MemberBase::~MemberBase() {
//-------------------------------------------------------------------------------
// Destructor.
   delete fThisMember;
   fPropertyList.Delete();
}

//-------------------------------------------------------------------------------
Reflex::MemberBase::operator
Reflex::Member() const {
//-------------------------------------------------------------------------------
// Conversion operator to Member.
   return *fThisMember;
}

//-------------------------------------------------------------------------------
void*
Reflex::MemberBase::CalculateBaseObject(const Object& obj) const {
//-------------------------------------------------------------------------------
// Return the object address a member lives in.
   char* mem = (char*) obj.Address();
   // check if its a dummy object
   Type cl = obj.TypeOf();

   while (cl && cl.IsTypedef()) {
      cl = cl.ToType();
   }

   // if the object type is not implemented return the Address of the object
   if (!cl) {
      return mem;
   }

   if (cl.IsClass()) {
      const Class* clTB = 0;
      if (DeclaringScope() && (cl.Id() != (dynamic_cast<const Class*>(DeclaringScope().ToScopeBase()))->ThisType().Id())) {
         // now we know that the Member type is an inherited one
         clTB = dynamic_cast<const Class*>(cl.ToTypeBase());
      }
      if (clTB) {
         std::vector<OffsetFunction> basePath = clTB->PathToBase(DeclaringScope());

         if (basePath.size()) {
            // there is a path described from the object to the class containing the Member
            std::vector<OffsetFunction>::iterator pIter;

            for (pIter = basePath.begin(); pIter != basePath.end(); ++pIter) {
               mem += (*pIter)(mem);
            }
         } else {
            throw RuntimeError(std::string(": ERROR: There is no path available from class ")
                               + cl.Name(SCOPED) + " to " + Name(SCOPED));
         }
      }
   } else {
      throw RuntimeError(std::string("Object ") + cl.Name(SCOPED) + " does not represent a class");
   }
   return (void*) mem;
} // CalculateBaseObject

//-------------------------------------------------------------------------------
Reflex::Scope
Reflex::MemberBase::DeclaringScope() const {
//-------------------------------------------------------------------------------
// Return the scope the member lives in.
   return fScope;
}

//-------------------------------------------------------------------------------
Reflex::Type
Reflex::MemberBase::DeclaringType() const {
//-------------------------------------------------------------------------------
// Return the type the member lives in.
   return DeclaringScope();
}

//-------------------------------------------------------------------------------
std::string
Reflex::MemberBase::MemberTypeAsString() const {
//-------------------------------------------------------------------------------
// Remember type of the member as a string.
   switch (fMemberType) {
   case DATAMEMBER:
      return "DataMember";
      break;
   case FUNCTIONMEMBER:
      return "FunctionMember";
      break;
   default:
      return Reflex::Argv0() + ": ERROR: Member " + Name() +
             " has no Species associated";
   }
}

//-------------------------------------------------------------------------------
Reflex::PropertyList
Reflex::MemberBase::Properties() const {
//-------------------------------------------------------------------------------
// Return the property list attached to this member.
   return fPropertyList;
}

//-------------------------------------------------------------------------------
Reflex::Type
Reflex::MemberBase::TemplateArgumentAt(size_t /* nth */) const {
//-------------------------------------------------------------------------------
// Return the nth template argument (in FunMemTemplInstance)
   return Dummy::Type();
}

//-------------------------------------------------------------------------------
void
Reflex::MemberBase::GenerateDict(DictionaryGenerator& /* generator */) const {
//-------------------------------------------------------------------------------
// Generate Dictionary information about itself.
}
<|endoftext|>


<commit_before><commit_msg>ENH: Added fractional diffs<commit_after><|endoftext|>